2013-06-04 4 views
1

Je travaille actuellement sur une application de preuve de concept écrite en monotouch qui enregistrerait des vidéos. J'ai besoin d'ajuster l'heure du CMSampleBuffer, j'ai trouvé un code qui fait exactement cela mais il est écrit en Objective-C. J'ai essayé de traduire le code ci-dessous, mais je ne trouve aucun mappage à cette fonction - CMSampleBufferGetSampleTimingInfoArray, comment allons-nous appeler cette fonction dans monotouch? Ci-dessous le code complet pour le réglage du temps, mais en Objective-C:Monotouch - CMSampleBufferGetSampleTimingInfoArray

- (CMSampleBufferRef) adjustTime:(CMSampleBufferRef) sample by:(CMTime) offset 
{ 
    CMItemCount count; 
    CMSampleBufferGetSampleTimingInfoArray(sample, 0, nil, &count); 
    CMSampleTimingInfo* pInfo = malloc(sizeof(CMSampleTimingInfo) * count); 
    CMSampleBufferGetSampleTimingInfoArray(sample, count, pInfo, &count); 
    for (CMItemCount i = 0; i < count; i++) 
    { 
     pInfo[i].decodeTimeStamp = CMTimeSubtract(pInfo[i].decodeTimeStamp, offset); 
     pInfo[i].presentationTimeStamp = CMTimeSubtract(pInfo[i].presentationTimeStamp, offset); 
    } 
    CMSampleBufferRef sout; 
    CMSampleBufferCreateCopyWithNewTiming(nil, sample, count, pInfo, &sout); 
    free(pInfo); 
    return sout; 
} 
+0

Avez-vous vu cela? https://github.com/mono/maccore/blob/master/src/CoreMedia/CMSampleBuffer.cs la fonctionnalité que vous mentionnez est commentée, mais selon ce que vous faites, cela peut être utile –

+0

Oui, je l'ai vu, La réponse de Rolf fonctionne presque, sauf pour la partie où nous créons un CMSampleBuffer en lui passant un handle. Le constructeur CMSampleBuffer pour cela est déclaré interne. – lmumar

+0

J'essaie d'implémenter une fonctionnalité d'enregistrement vidéo similaire à celle de la vigne, où vous pouvez enregistrer/suspendre plusieurs fois. J'ai réussi à le dupliquer en enregistrant plusieurs fichiers et en combinant les fichiers après (AVMutableComposition) mais je ne peux pas résoudre le problème de scintillement de la vidéo surtout si vous faites la séquence d'enregistrement/pause trop rapidement. J'ai pensé qu'il n'est pas nécessaire de l'enregistrer dans plusieurs fichiers, mais chaque fois que j'ai besoin de reprendre, je dois recalculer l'heure du CMSampleBuffer pour que la vidéo soit lue en continu. – lmumar

Répondre

1

Ce n'est pas testé, mais je crois que vous devriez obtenir sur la bonne voie:

[DllImport(Constants.CoreMediaLibrary)] 
int CMSampleBufferGetSampleTimingInfoArray (
    IntPtr sbuf, 
    int timingArrayEntries, 
    CMSampleTimingInfo [] timingArrayOut, 
    out int timingArrayEntriesNeededOut 
); 

[DllImport(Constants.CoreMediaLibrary)] 
int CMSampleBufferCreateCopyWithNewTiming (
    IntPtr allocator, 
    IntPtr originalSBuf, 
    int numSampleTimingEntries, 
    CMSampleTimingInfo []sampleTimingArray, 
    out IntPtr sBufCopyOut 
); 

CMSampleBuffer AdjustTime (CMSampleBuffer sample, CMTime offset) 
{ 
    int count; 
    CMSampleBufferGetSampleTimingInfoArray (sample.Handle, 0, null, out count); 
    CMSampleTimingInfo [] pInfo = new CMSampleTimingInfo [count]; 
    CMSampleBufferGetSampleTimingInfoArray (sample.Handle, count, pInfo, out count); 
    for (int i = 0; i < count; i++) { 
     pInfo [i].DecodeTimeStamp = CMTime.Subtract (pInfo [i].DecodeTimeStamp, offset); 
     pInfo [i].PresentationTimeStamp = CMTime.Subtract (pInfo [i].PresentationTimeStamp, offset); 
    } 
    IntPtr sout; 
    CMSampleBufferCreateCopyWithTiming (IntPtr.Zero, sample, count, pInfo, out sout); 
    // Unfortunately the constructor we need is internal, but that can be fixed 
    // for a future version of Xamarin.iOS. 
    return (CMSampleBuffer) typeof (CMSampleBuffer).GetConstructor (BindingFlags.Instance | BindingFlags.NonPublic, null, new Type [] { typeof (IntPtr), typeof (bool) }, null).Invoke (new object [] { sout, true }); 
} 

Mise à jour

J'ai implémenté une partie de l'API requise dans Xamarin.iOS, donc dans les prochaines versions, vous pourrez faire ceci:

CMSampleBuffer AdjustTime (CMSampleBuffer sample, CMTime offset) 
{ 
    var info = sample.GetSampleTimingInfo(); 
    for (int i = 0; i < info.Length; i++) { 
     info [i].DecodeTimeStamp = CMTime.Subtract (info [i].DecodeTimeStamp, offset); 
     info [i].PresentationTimeStamp = CMTime.Subtract (info [i].PresentationTimeStamp, offset); 
    } 
    return CMSampleBuffer.CreateWithNewTiming (sample, info) 
} 
+0

hi Rolf, Je ne pense pas que nous pouvons invoquer ce constructeur -> CMSampleBuffer (IntPtr handle), Il est déclaré avec une accessibilité de l'interne. Lorsque j'ai essayé de compiler le code, le compilateur se plaint que le constructeur est inaccessible en raison de son niveau de protection. Existe-t-il un autre moyen de créer un CMSampleBuffer à partir d'un handle? – lmumar

+0

J'ai mis à jour l'exemple pour utiliser la réflexion pour obtenir et appeler le constructeur interne. Faites-moi savoir si cela fonctionne réellement et je vais rendre le constructeur public (ou fournir une API pour tout cela). –

+0

hi Rolf, ne fonctionnait toujours pas CMSampleBufferCreateCopyWithTiming renvoyait un statut == 0, cependant l'appel GetConstructor (..). Invoke lançait une exception de pointeur NULL. – lmumar