Pregunta

Me gustaría empezar de disculpándose por este ridículamente largo post, pero me trató de proporcionar la mayor cantidad de código y datos como sea posible para que usted alude.

Estoy trabajando en un proyecto de vídeo, donde voy a necesitar la flexibilidad de la AVQueuePlayer (sobre todo la capacidad de escala y el diseño de la capa de vídeo libremente, así como la creación de mis controles personalizados). El problema es que tengo que ser capaz de mezclar el contenido de vídeo de diferentes tipos (en este caso progresiva descarga .mp4 y la transmisión HTTP .m3u8). Aquí es donde las cosas se ponen de moda.

En primer lugar algo de código para que te va:

- (void)viewDidLoad {
   [super viewDidLoad];

   NSArray *assetsArray = [NSArray arrayWithObjects:
                        [AVPlayerItem playerItemWithURL: [NSURL URLWithString: kTestPrerollURL]], // .mp4-file on server
                        [AVPlayerItem playerItemWithURL: [NSURL URLWithString: kTestVideoURL]],   // .m3u8-file on server
                        [AVPlayerItem playerItemWithURL: [NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource: @"2" ofType:@"m4v"]]], // local m4v-file
                        [AVPlayerItem playerItemWithURL: [NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource: @"3" ofType:@"m4v"]]], // local m4v-file
                        nil];

    // Add KVO observation on each player item to track when they are ready for playback
    for(id playerItem in assetsArray) {
       [playerItem addObserver: self forKeyPath:@"status" options: 0 context: NULL];
    }

    [self setPlayer: [AVQueuePlayer queuePlayerWithItems: assetsArray]];


    [self setPlayerLayer: [AVPlayerLayer playerLayerWithPlayer: [self player]]];
    [[self playerLayer] setFrame: [playerView bounds]];
    // Additional layer customization...
    [[playerView layer] addSublayer: [self playerLayer]];
    [playerView setBackgroundColor: [UIColor clearColor]];

    [[NSNotificationCenter defaultCenter] addObserver: self
                                             selector: @selector(playerItemDidReachEnd:)
                                                 name: AVPlayerItemDidPlayToEndTimeNotification
                                               object: nil];
}

Y cuando el AVPlayerItem cambia de estado, se invoca este método:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

   // A bunch of loggers...
   if([(AVPlayerItem *)object status] == AVPlayerItemStatusReadyToPlay) {
      CGSize   movieSize = [[[player currentItem] asset] naturalSize];
      CGRect   playerRect = [playerView frame];
      playerRect.size.height  = playerRect.size.width * movieSize.height/movieSize.width + 7.0;
      [playerView  setFrame: playerRect];
      [playerLayer setFrame: [playerView bounds]];

      [player play];
   }
}

Si los elige usuario pulse un botón "Siguiente", el reproductor salta al siguiente clip:

- (IBAction)next:(id)sender {
   NSLog(@"------ USER SWITCHED TO NEXT ------");
   AVPlayerItem *object = (AVPlayerItem *)[player currentItem];
   [object removeObserver:self forKeyPath: @"status"];
   [player advanceToNextItem];
}

Finalmente, cuando el AVPlayerItem llega al final, se invoca este método:

- (void)playerItemDidReachEnd:(NSNotification *)notification {
   NSLog(@"------ PLAYER ITEM DID REACH END ------");
   AVPlayerItem *object = (AVPlayerItem *)[notification object];
   [object removeObserver:self forKeyPath: @"status"];
}

Ok, así que mi problema es que la mezcla de diferentes formatos (en este caso el M3U8-archivo) provoca un comportamiento cobarde.

Si se me carga el archivo M3U8-primero en la cola, se reproduce correctamente, pero si advanceToNextItem la aplicación se bloquea. informes NSZombieEnabled:

*** -[Not A Type retain]: message sent to deallocated instance 0x684dfe0
[Switching to process 67957]

y los espectáculos de la pila de llamadas de una liberación fuera de mis límites (myPlayer es el nombre del proyecto):

po [NSThread callStackSymbols]
2011-01-05 16:12:57.151 MyPlayer[67957:6303] *** __NSAutoreleaseNoPool(): Object 0x56a0580 of class _NSCallStackArray autoreleased with no pool in place - just leaking
<_NSCallStackArray 0x56a0580>(
0   MyPlayer                            0x00002154 start + 0,
1   CoreFoundation                      0x00e72f22 _CF_forwarding_prep_0 + 50,
2   CoreFoundation                      0x00e140bc CFRetain + 92,
3   CFNetwork                           0x014c436e _ZN21XConnectionEventQueueI12XLoaderEvent18XLoaderEventParamsE10pushEventsEP20XConnectionEventInfoIS0_S1_El + 120,
4   CFNetwork                           0x014c4252 _ZN19URLConnectionLoader16pushEventsLockedEP20XConnectionEventInfoI12XLoaderEvent18XLoaderEventParamsEl + 120,
5   CFNetwork                           0x014c41c7 _ZN19URLConnectionLoader10pushEventsEP20XConnectionEventInfoI12XLoaderEvent18XLoaderEventParamsEl + 57,
6   CFNetwork                           0x015976b6 _ZN19URLConnectionClient25getRequestForTransmissionEhP14_CFURLResponsePK13_CFURLRequestPP9__CFError + 942,
7   CFNetwork                           0x014c3030 _ZN19URLConnectionClient22_clientWillSendRequestEPK13_CFURLRequestP14_CFURLResponsePNS_26ClientConnectionEventQueueE + 230,
8   CFNetwork                           0x01597789 _ZN19URLConnectionClient26ClientConnectionEventQueue33processAllEventsAndConsumePayloadEP20XConnectionEventInfoI12XClientEvent18XClientEventParamsEl + 141,
9   CFNetwork                           0x014c2e3c _ZN19URLConnectionClient13processEventsEv + 100,
10  CFNetwork                           0x014c2cb7 _ZN17MultiplexerSource7performEv + 251,
11  CoreFoundation                      0x00ee301f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15,
12  CoreFoundation                      0x00e4128b __CFRunLoopDoSources0 + 571,
13  CoreFoundation                      0x00e40786 __CFRunLoopRun + 470,
14  CoreFoundation                      0x00e40240 CFRunLoopRunSpecific + 208,
15  CoreFoundation                      0x00e43504 CFRunLoopRun + 84,
16  CoreMedia                           0x00cb39af FigThreadGlobalNetworkBufferingRunloop + 149,
17  CoreMedia                           0x00cb624a figThreadMain + 308,
18  libSystem.B.dylib                   0x9473885d _pthread_start + 345,
19  libSystem.B.dylib                   0x947386e2 thread_start + 34
)

si el .m3u8-archivo se coloca en algún lugar después de la primera posición en la cola, aparece un estado de AVPlayerItemStatusFailed, y los saltos clip al siguiente clip de la cola.

Me da cuenta de esto podría estar relacionado con alguna de gestión de memoria, pero al mismo tiempo empezar a dudar de él. Sin embargo, es bastante evidente que estoy haciendo algo mal, por lo que cada sugerencia de una solución es más que bienvenido.

¿Fue útil?

Solución

No se puede hacer esto - AVPlayer puede jugar cualquiera contenido HLS (M3U) o no escuchados, pero no una mezcla. Ver este para más detalles: https://devforums.apple.com/message/570406#570406

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top