requestMediaDataWhenReadyOnQueue: usingBlock: crea más de un bloque en paralelo -> se bloquea

Estoy tratando de agregar CGPixelBufferRefs a un AVAssetWriterInput para crear una película QuickTime.

Estoy usando el siguiente código:

BOOL __block shouldContinue = YES;

[self.assetWriterInput requestMediaDataWhenReadyOnQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
usingBlock:^(void)
{
BXLog(@"processing Block");

while ([self.assetWriterInput isReadyForMoreMediaData] && shouldContinue)
{
    BXLog(@"assetWriter isReadyForMoreMediaData, shouldContinue %i", shouldContinue);

    NSError *error = nil;
    CGImageRef image = [inClip copyImageAtIndex:frameCounter withSize:CGSizeZero error:&error];
    CGFloat progress = (CGFloat)frameCounter / (CGFloat)inRange.length;

    if (image != NULL)
    {
        size_t width = CGImageGetWidth(image);
        size_t height = CGImageGetHeight(image);
        CVPixelBufferRef pixelBuffer = [self pixelBufferFromCGImage:image andSize:CGSizeMake(width, height)];

        if (! [self.assetWriterInputPixelBufferAdaptor appendPixelBuffer:pixelBuffer 
          withPresentationTime:CMTimeMake(frameCounter * inClip.lengthOfOneFrame.value,       inClip.lengthOfOneFrame.timescale)])
        {
            [self.assetWriter finishWriting];

             BXLogInDomain(kLogDomainSharing, kLogLevelError, @"Error while appending pixel butter: %@", self.assetWriter.error);
             error = [NSError errorWithDomain:kErrorDomainExport
                                         code:ZBExportAppendImageError 
                                     userInfo:nil];
        }

        CVPixelBufferRelease(pixelBuffer);
    }   
    else
    {
        [self.assetWriter finishWriting];

        BXLogInDomain(kLogDomainSharing, kLogLevelError, @"Error while coping image from clip %@", self.assetWriter.error);
        // create a Framedrop Error - we couldn't find a frame
        error = [NSError errorWithDomain:kErrorDomainExport 
                                    code:ZBExportFrameDropError
                                userInfo:nil];
     }

     [[NSOperationQueue mainQueue] addOperationWithBlock:^(void)
      {
           self.currentProgress = flag ? progress * 0.5 : progress;
      }];

     dispatch_sync(handlerQueue,
      ^(void)
      {
          shouldContinue = inProgressHandler(progress, image);
      });
      BXLog(@"should continue %i", shouldContinue);

      CGImageRelease(image);

      frameCounter++;
      // Movie is finished
      if (frameCounter >= inRange.location + inRange.length)
      {
          [self.assetWriterInput markAsFinished];
          [self.assetWriter finishWriting];
          [[NSOperationQueue mainQueue] addOperationWithBlock:^(void)
           {
               self.currentProgress = 1.0;
           }];
          dispatch_async(handlerQueue, ^(void)
           {
               inCompletionHandler(self.filePath, error);
               dispatch_release(handlerQueue);
           });
          shouldContinue = NO;
      }
      else if (shouldContinue == NO)
      {
         [self.assetWriterInput markAsFinished];
         [self.assetWriter finishWriting];

         // call the completion handler
         if (frameCounter < inRange.location + inRange.length)
         {
             dispatch_async(handlerQueue, ^(void)
              {
                  // cancel error
                  inCompletionHandler(NULL, [NSError errorWithDomain:kErrorDomainEport
                                                                code:ZBExportCancelError
                                                            userInfo:nil]);
                  dispatch_release(handlerQueue);
               });
          }

          // do not export any longer
          // simply calling the completion handler is not enough


      BXLog(@"End of while – should continue %i - asset writer is ready for more media %i", shouldContinue, [self.assetWriterInput isReadyForMoreMediaData]);
    }

    BXLog(@"out of while");

}];

}

La mayoría de las veces funciona muy bien, pero a veces falla. Podría desglosar la situación del accidente a lo siguiente:

  1. Para la mayoría de las exportaciones, solo se crea un bloque, el bucle while se maneja fotograma a fotograma y, al final, el bloque sale.
  2. Hay una exportación, donde se usa más de un bloque. Se crea un bloque, manipula 4 o 5 imágenes y luego deja el ciclo while con [self.assetWriterInput isReadyForMoreMediaData == NO. Se crea un nuevo bloque, manejando un poco más de marco y luego dejando el bucle while.
  3. Ocurre que a veces no se crea un bloque sino dos y ambos funcionan en paralelo.

Obtengo el siguiente resultado:

2011-11-08 12:42:41.161 iStopMotion[22804:1c003] processing Block
2011-11-08 12:42:41.168 iStopMotion[22804:1c003] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.278 iStopMotion[22804:1c003] should continue 1
2011-11-08 12:42:41.279 iStopMotion[22804:1c003] End of while - should continue 1 - asset writer is ready for more media 1
2011-11-08 12:42:41.285 iStopMotion[22804:1c003] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.370 iStopMotion[22804:1c003] should continue 1
2011-11-08 12:42:41.391 iStopMotion[22804:1c003] End of while - should continue 1 - asset writer is ready for more media 1
2011-11-08 12:42:41.399 iStopMotion[22804:1c003] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.420 iStopMotion[22804:1c003] should continue 1
2011-11-08 12:42:41.422 iStopMotion[22804:1c003] End of while - should continue 1 - asset writer is ready for more media 0
2011-11-08 12:42:41.423 iStopMotion[22804:1c003] out of while
2011-11-08 12:42:41.442 iStopMotion[22804:1e507] processing Block
2011-11-08 12:42:41.457 iStopMotion[22804:1e507] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.476 iStopMotion[22804:1e507] should continue 1
2011-11-08 12:42:41.476 iStopMotion[22804:1e507] End of while - should continue 1 - asset writer is ready for more media 0
2011-11-08 12:42:41.477 iStopMotion[22804:1e507] out of while
2011-11-08 12:42:41.498 iStopMotion[22804:1e507] processing Block
2011-11-08 12:42:41.515 iStopMotion[22804:1e507] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.541 iStopMotion[22804:1e507] should continue 1
2011-11-08 12:42:41.553 iStopMotion[22804:1e507] End of while - should continue 1 - asset writer is ready for more media 0
2011-11-08 12:42:41.583 iStopMotion[22804:1e507] out of while
2011-11-08 12:42:41.614 iStopMotion[22804:1e507] processing Block
2011-11-08 12:42:41.628 iStopMotion[22804:1e507] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.689 iStopMotion[22804:1f107] processing Block
2011-11-08 12:42:41.710 iStopMotion[22804:1f107] assetWriter isReadyForMoreMediaData, shouldContinue 1
2011-11-08 12:42:41.668 iStopMotion[22804:1e507] should continue 1
2011-11-08 12:42:41.730 iStopMotion[22804:1e507] End of while - should continue 1 - asset writer is ready for more media 1
2011-11-08 12:42:41.751 iStopMotion[22804:1f107] should continue 1
2011-11-08 12:42:41.766 iStopMotion[22804:1f107] End of while - should continue 1 - asset writer is ready for more media 0
2011-11-08 12:42:41.789 iStopMotion[22804:1f107] out of while
2011-11-08 12:42:41.766 iStopMotion[22804:1e507] assetWriter isReadyForMoreMediaData, shouldContinue 1

Esto arroja una excepción:

'NSInternalInconsistencyException', reason: '*** -[AVAssetWriterInputPixelBufferAdaptor appendPixelBuffer:withPresentationTime:]
A pixel buffer cannot be appended when readyForMoreMediaData is NO.'

Parece que AVAssetWriterInput está procesando datos del primer bloque y, por lo tanto, no está readyForMoreMediaData, donde el segundo bloque también intenta agregar un búfer de píxeles.

¿Alguien tiene una idea, cómo viene esto y qué hacer contra él?

preguntado el 08 de noviembre de 11 a las 12:11

Yo también me he dado cuenta de esto. ¿Qué versión de iOS? ¿Ha intentado capturar la excepción y volver a intentarlo más tarde? -

0 Respuestas

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.