11
votes

Comment utiliser AvasSeTreader et AvaisetWriter pour plusieurs pistes (audio et vidéo) simultanément?

Je sais utiliser AvasSetreader et AvaisetWriter , et les avez utilisé avec succès pour saisir une piste vidéo d'un film et transcodez-la dans une autre. Cependant, j'aimerais faire cela avec l'audio aussi. Dois-je créer et AvasseTExportsession après que j'ai terminé avec le transcode initial, ou existe-t-il un moyen de basculer entre les pistes au milieu d'une séance d'écriture? Je détesterais devoir faire face aux frais généraux d'un avaissetexportsession .

Je demande car, à l'aide de la méthode de style de tirage - tandis que ([ASTRETWRITRINPUT ISREADYFORMEDIADATA]) {...} - suppose une piste seulement. Comment pourrait-il être utilisé pour plus d'une piste, c'est-à-dire à la fois un audio et une piste vidéo?


1 commentaires

Seriez-vous capable de me diriger dans la bonne direction pour apprendre à transcoder à l'aide d'Avaisetwriter? Je cherche juste à transcoder un bittrate et une résolution plus bas?


3 Réponses :


1
votes

Avez-vous essayé d'utiliser deux avaisetwriterinput et poussant les échantillons à travers une file d'attente de travailleur? Voici un croquis approximatif.

processing_queue = dispatch_queue_create("com.mydomain.gcdqueue.mediaprocessor", NULL);

[videoAVAssetWriterInput requestMediaDataWhenReadyOnQueue:myInputSerialQueue usingBlock:^{
    dispatch_asyc(processing_queue, ^{process video});
}];

[audioAVAssetWriterInput requestMediaDataWhenReadyOnQueue:myInputSerialQueue usingBlock:^{
    dispatch_asyc(processing_queue, ^{process audio});
}];


5 commentaires

Merci pour la suggestion. Je l'ai essayé, mais je n'ai pas pu comprendre comment terminer correctement la session d'écriture. Avec une piste, je viens de voir si la copie -extsampluffer retourne vide, puis terminez la session. Avec plusieurs pistes, j'ai essayé de créer un drapeau lorsque l'audio ou la vidéo a été effectuée et si les deux étaient complètes, je terminerais la session. Cependant, même si j'ai fait une vérification du statut de lecteur d'actif étant avastsereaderstatusreading, j'ai continué à obtenir l'erreur: [AvastreeaderAkTrackutput CopyNextsampluffer] ne peut pas copier le tampon d'échantillon suivant, à moins que le lecteur d'actif ne soit dans l'état "Lecture"


Je parierai à tester une stratégie comme celle-ci dans un proche avenir. Si je trouve une solution, je posterai.


Appelez-vous [avastetwriterinput markasfini]; Dans votre méthode de demandeMediawawhenReadyOnqueur? Je n'appellerais pas de cette méthode du tout, mais plutôt d'appeler la fin de course sur l'avaisetwriter lorsque tout est complet.


Désolé pour la réponse tardive, je n'ai pas été informé du commentaire. Je n'appelle que le finisseur d'arrivée, tout comme vous faites.


À propos, votre erreur "Lecture" State "peut en réalité être un problème de codec. Si les entrées et les sorties ne sont pas des formats compatibles qui sont la façon dont il va parfois surface.



8
votes

Avaisetwriter CODE> interstilisera automatiquement les demandes sur son avastetwriterinput code> S afin d'intégrer différentes pistes dans le fichier de sortie. Il suffit d'ajouter un avaissetwriterinput code> pour chacune des pistes que vous avez, puis appelle DemandeMediatawhenreadyonQueue: UtilisationBLOCK: Code> sur chacun de vos Avaisetwriterinput code> s. > Voici une méthode que j'ai cet appels DemandeMediatawhenreadyONOnQueue: UtilisationBlock: code>. J'appelle cette méthode à partir d'une boucle sur le nombre de paires de sortie / d'entrée que j'ai. (Une méthode distincte est bonne à la fois pour la lisibilité du code et également parce que, contrairement à une boucle, chaque appel définit un cadre de pile séparé pour le bloc.) P>

Vous n'avez besoin que d'un DisPatch_Queue_t code> et peut le réutiliser pour toutes les pistes. Notez que vous devriez définitivement pas em> appel DISTATCH_ASYNC code> à partir de votre bloc, car DemandeMediatawhenreadyonQueue: UtilisationBLOCK: CODE> attend le blocage, eh bien, bloquer jusqu'à ce qu'il soit rempli Dans autant de données que le avastetwriterinput code> prendra. Vous ne voulez pas revenir avant alors. P>

- (void)requestMediaDataForTrack:(int)i {
  AVAssetReaderOutput *output = [[_reader outputs] objectAtIndex:i];
  AVAssetWriterInput *input = [[_writer inputs] objectAtIndex:i];

  [input requestMediaDataWhenReadyOnQueue:_processingQueue usingBlock:
    ^{
      [self retain];
      while ([input isReadyForMoreMediaData]) {
        CMSampleBufferRef sampleBuffer;
        if ([_reader status] == AVAssetReaderStatusReading &&
            (sampleBuffer = [output copyNextSampleBuffer])) {

          BOOL result = [input appendSampleBuffer:sampleBuffer];
          CFRelease(sampleBuffer);

          if (!result) {
            [_reader cancelReading];
            break;
          }
        } else {
          [input markAsFinished];

          switch ([_reader status]) {
            case AVAssetReaderStatusReading:
              // the reader has more for other tracks, even if this one is done
              break;

            case AVAssetReaderStatusCompleted:
              // your method for when the conversion is done
              // should call finishWriting on the writer
              [self readingCompleted];
              break;

            case AVAssetReaderStatusCancelled:
              [_writer cancelWriting];
              [_delegate converterDidCancel:self];
              break;

            case AVAssetReaderStatusFailed:
              [_writer cancelWriting];
              break;
          }

          break;
        }
      }
    }
  ];
}


2 commentaires

Qu'est-ce qui est avec le [auto retenue] ? Est-ce que cela ne veut que continuer à incrémenter le nombre de retenons sur l'objet un montant arbitraire? Qui relâche cet objet?


L'intention a peut-être pu être pour LectureCompleted pour libérer l'objet. Cela étant dit, il peut être inutile que la présence de la [auto lecturecommée] appelle doit faire conserver le temps d'exécution auto / code> automatiquement.



0
votes

Vous pouvez utiliser des groupes d'expédition!

Consultez l'exemple AvreaderWriter pour macosx ...

Je cite directement à partir de l'échantillon rwdocument.m: xxx


2 commentaires

Remarquez la commande de premier groupe Notify à la fin de savoir quand tout audio / vidéo est terminé ... C'est un rendu hors écran ... pas un temps réel


"Offscreen" et "temps réel" ne sont pas des contraires; "Rendu" et "Off-Screen" sont (et font). "Real-Time" est subjectif à un observateur et décrit le taux d'affichage des cadres vidéo comme ils sont acquis à partir de leur source. Il n'a pas d'opposition, pas même "non réel". Vous ne voudriez pas qu'un transcodeur fonctionne à un rythme en temps réel. Le transcodage devrait arriver le plus rapidement possible; Il existe des dispositifs dédiés à cela dans l'industrie de la radiodiffusion. Rien ne va plus lentement que la normale en temps réel, de toute façon. Même le logiciel de lecture doit peser une vidéo pour le garder d'affichage plus rapide qu'il ne peut être perçu.