محتوى نوع الفيديو المختلط في قائمة انتظار في AvqueUeplayer على iPhone
-
25-09-2019 - |
سؤال
أود أن أبدأ بالاعتذار عن هذا المنشور الطويل يبعث على السخرية ، لكنني حاولت تقديم أكبر قدر ممكن من التعليمات البرمجية والبيانات.
أنا أعمل على مشروع فيديو حيث سأحتاج إلى مرونة AvqueUeplayer (في كل مكان القدرة على توسيع وتخطيط طبقة الفيديو بحرية ، وكذلك إنشاء عناصر التحكم المخصصة). المشكلة هي أنني بحاجة إلى أن أكون قادرًا على مزج محتوى الفيديو من أنواع مختلفة (في هذه الحالة تنزيل تدريجي. MP4 و HTTP Dreaming .m3u8). هنا حيث تصبح الأمور غير تقليدية.
أولا بعض التعليمات البرمجية لجعلك تذهب:
- (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];
}
وعندما يغير AvplayerItem حالة ، يتم استدعاء هذه الطريقة:
- (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];
}
}
إذا اختار المستخدم الضغط على "التالي"-ولكن ، يتخطى اللاعب إلى المقطع التالي:
- (IBAction)next:(id)sender {
NSLog(@"------ USER SWITCHED TO NEXT ------");
AVPlayerItem *object = (AVPlayerItem *)[player currentItem];
[object removeObserver:self forKeyPath: @"status"];
[player advanceToNextItem];
}
أخيرًا ، عندما يصل AvplayerItem إلى النهاية ، يتم استدعاء هذه الطريقة:
- (void)playerItemDidReachEnd:(NSNotification *)notification {
NSLog(@"------ PLAYER ITEM DID REACH END ------");
AVPlayerItem *object = (AVPlayerItem *)[notification object];
[object removeObserver:self forKeyPath: @"status"];
}
حسنًا ، مشكلتي هي أن خلط التنسيقات المختلفة (في هذه الحالة تسبب ملخص M3U8) يؤدي إلى بعض السلوك غير التقليدي.
إذا قمت بتحميل ملف M3U8 أولاً في قائمة الانتظار ، فسيتم تشغيله بشكل صحيح ، ولكن إذا تعطلت AdvancetOnextItem في تعطل التطبيق. تقارير nszombieenabled:
*** -[Not A Type retain]: message sent to deallocated instance 0x684dfe0
[Switching to process 67957]
ويظهر مكدس المكالمات إصدارًا من حدودي (MyPlayer هو اسم المشروع):
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
)
إذا تم وضع ملف .m3u8 في مكان ما بعد الموضع الأول في قائمة الانتظار ، أحصل على حالة avplayeritemstatusfailed ، وتتخطى المقطع إلى المقطع التالي في قائمة الانتظار.
أدرك أن هذا قد يكون مرتبطًا ببعض إدارة الذاكرة ، لكن في نفس الوقت أبدأ في الشك. ومع ذلك ، فمن الواضح تمامًا أنني أفعل شيئًا خاطئًا ، لذا فإن كل اقتراح بحل ما هو أكثر من موضع ترحيب.
المحلول
لا يمكنك القيام بذلك - يمكن لـ Avplayer إما تشغيل محتوى HLS (M3U) أو غير المجرمين ، ولكن ليس مزيجًا. انظر هذا للحصول على التفاصيل: https://devforums.apple.com/message/570406#570406