[vlc-commits] videotoolbox: implement decoder restart

Felix Paul Kühne git at videolan.org
Tue Aug 9 19:21:34 CEST 2016


vlc | branch: master | Felix Paul Kühne <fkuehne at videolan.org> | Tue Aug  9 18:05:37 2016 +0200| [3109980955250b8686102cf0ddd0c99ed7be9397] | committer: Felix Paul Kühne

videotoolbox: implement decoder restart

This is triggered if the session becomes invalid (e.g. when the app is backgrounded on iOS)

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=3109980955250b8686102cf0ddd0c99ed7be9397
---

 modules/codec/videotoolbox.m | 154 ++++++++++++++++++++++++++++---------------
 1 file changed, 100 insertions(+), 54 deletions(-)

diff --git a/modules/codec/videotoolbox.m b/modules/codec/videotoolbox.m
index 62696ab..dcfac97 100644
--- a/modules/codec/videotoolbox.m
+++ b/modules/codec/videotoolbox.m
@@ -112,6 +112,7 @@ struct decoder_sys_t
     uint8_t                     i_nal_length_size;
 
     bool                        b_started;
+    bool                        b_is_restarting;
     bool                        b_is_avcc;
     VTDecompressionSessionRef   session;
     CMVideoFormatDescriptionRef videoFormatDescription;
@@ -273,6 +274,68 @@ static CMVideoCodecType CodecPrecheck(decoder_t *p_dec)
     return codec;
 }
 
+static int StartVideoToolboxSession(decoder_t *p_dec)
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    /* setup decoder callback record */
+    VTDecompressionOutputCallbackRecord decoderCallbackRecord;
+    decoderCallbackRecord.decompressionOutputCallback = DecoderCallback;
+    decoderCallbackRecord.decompressionOutputRefCon = p_dec;
+
+    /* create decompression session */
+    OSStatus status = VTDecompressionSessionCreate(kCFAllocatorDefault,
+                                                   p_sys->videoFormatDescription,
+                                                   p_sys->decoderConfiguration,
+                                                   p_sys->destinationPixelBufferAttributes,
+                                                   &decoderCallbackRecord,
+                                                   &p_sys->session);
+
+    /* check if the session is valid */
+    if (status) {
+
+        switch (status) {
+            case -12470:
+                msg_Err(p_dec, "VT is not supported on this hardware");
+                break;
+            case -12471:
+                msg_Err(p_dec, "Video format is not supported by VT");
+                break;
+            case -12903:
+                msg_Err(p_dec, "created session is invalid, could not select and open decoder instance");
+                break;
+            case -12906:
+                msg_Err(p_dec, "could not find decoder");
+                break;
+            case -12910:
+                msg_Err(p_dec, "unsupported data");
+                break;
+            case -12913:
+                msg_Err(p_dec, "VT is not available to sandboxed apps on this OS release or maximum number of decoders reached");
+                break;
+            case -12917:
+                msg_Err(p_dec, "Insufficient source color data");
+                break;
+            case -12918:
+                msg_Err(p_dec, "Could not create color correction data");
+                break;
+            case -12210:
+                msg_Err(p_dec, "Insufficient authorization to create decoder");
+                break;
+            case -8973:
+                msg_Err(p_dec, "Could not select and open decoder instance");
+                break;
+
+            default:
+                msg_Err(p_dec, "Decompression session creation failed (%i)", status);
+                break;
+        }
+        return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
+
 static int StartVideoToolbox(decoder_t *p_dec, block_t *p_block)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
@@ -548,58 +611,7 @@ static int StartVideoToolbox(decoder_t *p_dec, block_t *p_block)
                          kCVPixelBufferBytesPerRowAlignmentKey,
                          i_video_width * 2);
 
-    /* setup decoder callback record */
-    VTDecompressionOutputCallbackRecord decoderCallbackRecord;
-    decoderCallbackRecord.decompressionOutputCallback = DecoderCallback;
-    decoderCallbackRecord.decompressionOutputRefCon = p_dec;
-
-    /* create decompression session */
-    status = VTDecompressionSessionCreate(kCFAllocatorDefault,
-                                          p_sys->videoFormatDescription,
-                                          p_sys->decoderConfiguration,
-                                          p_sys->destinationPixelBufferAttributes,
-                                          &decoderCallbackRecord,
-                                          &p_sys->session);
-
-    /* check if the session is valid */
-    if (status) {
-
-        switch (status) {
-            case -12470:
-                msg_Err(p_dec, "VT is not supported on this hardware");
-                break;
-            case -12471:
-                msg_Err(p_dec, "Video format is not supported by VT");
-                break;
-            case -12903:
-                msg_Err(p_dec, "created session is invalid, could not select and open decoder instance");
-                break;
-            case -12906:
-                msg_Err(p_dec, "could not find decoder");
-                break;
-            case -12910:
-                msg_Err(p_dec, "unsupported data");
-                break;
-            case -12913:
-                msg_Err(p_dec, "VT is not available to sandboxed apps on this OS release or maximum number of decoders reached");
-                break;
-            case -12917:
-                msg_Err(p_dec, "Insufficient source color data");
-                break;
-            case -12918:
-                msg_Err(p_dec, "Could not create color correction data");
-                break;
-            case -12210:
-                msg_Err(p_dec, "Insufficient authorization to create decoder");
-                break;
-            case -8973:
-                msg_Err(p_dec, "Could not select and open decoder instance");
-                break;
-
-            default:
-                msg_Err(p_dec, "Decompression session creation failed (%i)", status);
-                break;
-        }
+    if (StartVideoToolboxSession(p_dec) != VLC_SUCCESS) {
         return VLC_EGENERIC;
     }
 
@@ -624,6 +636,7 @@ static int StartVideoToolbox(decoder_t *p_dec, block_t *p_block)
     }
 
     p_sys->b_started = YES;
+    p_sys->b_is_restarting = NO;
 
     return VLC_SUCCESS;
 }
@@ -664,6 +677,34 @@ static void StopVideoToolbox(decoder_t *p_dec)
     }
 }
 
+static void RestartVideoToolbox(decoder_t *p_dec)
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    msg_Dbg(p_dec, "Restarting decoder session");
+
+    p_sys->b_is_restarting = true;
+    p_sys->b_started = false;
+
+    if (p_sys->session != nil) {
+        VTDecompressionSessionInvalidate(p_sys->session);
+        CFRelease(p_sys->session);
+        p_sys->session = nil;
+    }
+
+    p_sys->b_format_propagated = false;
+
+    Flush(p_dec);
+
+    if (StartVideoToolboxSession(p_dec) == VLC_SUCCESS) {
+        p_sys->b_started = true;
+    } else {
+        msg_Warn(p_dec, "Decoder session restart failed");
+    }
+
+    p_sys->b_is_restarting = false;
+}
+
 #pragma mark - module open and close
 
 static int OpenDecoder(vlc_object_t *p_this)
@@ -698,6 +739,8 @@ static int OpenDecoder(vlc_object_t *p_this)
     p_sys->b_is_avcc = false;
     p_sys->codec = codec;
     p_sys->videoFormatDescription = nil;
+    p_sys->decoderConfiguration = nil;
+    p_sys->destinationPixelBufferAttributes = nil;
 
     int i_ret = StartVideoToolbox(p_dec, NULL);
     if (i_ret != VLC_SUCCESS) {
@@ -964,7 +1007,7 @@ static picture_t *DecodeBlock(decoder_t *p_dec, block_t **pp_block)
     p_block = *pp_block;
 
     if (likely(p_block != NULL)) {
-        if (unlikely(p_block->i_flags&(BLOCK_FLAG_CORRUPTED))) {
+        if (unlikely(p_block->i_flags&(BLOCK_FLAG_CORRUPTED) || p_sys->b_is_restarting)) {
             Flush(p_dec);
             block_Release(p_block);
             goto skip;
@@ -1024,7 +1067,10 @@ static picture_t *DecodeBlock(decoder_t *p_dec, block_t **pp_block)
                         StopVideoToolbox(p_dec);
                     } else if (status == -8960 || status == -12911) {
                         msg_Err(p_dec, "decoder failure: internal malfunction (%i)", status);
-                        StopVideoToolbox(p_dec);
+                        RestartVideoToolbox(p_dec);
+                    } else if (status == -12903) {
+                        msg_Warn(p_dec, "decoder failure: session invalid");
+                        RestartVideoToolbox(p_dec);
                     } else
                         msg_Dbg(p_dec, "decoding frame failed (%i)", status);
                 }



More information about the vlc-commits mailing list