lavc/videotoolboxenc: Workaround encoder error
authorRick Kern <kernrj@gmail.com>
Thu, 24 Mar 2016 17:56:04 +0000 (01:56 +0800)
committerwm4 <nfxjfg@googlemail.com>
Sat, 2 Apr 2016 17:16:20 +0000 (19:16 +0200)
CMVideoFormatDescriptionGetH264ParameterSetAtIndex() fails on some
hardware/OS versions when retrieving the parameter set count alone.

Signed-off-by: Rick Kern <kernrj@gmail.com>
Signed-off-by: wm4 <nfxjfg@googlemail.com>
libavcodec/videotoolboxenc.c

index 0791146..3177074 100644 (file)
@@ -194,6 +194,7 @@ static int get_params_size(
 {
     size_t total_size = 0;
     size_t ps_count;
+    int is_count_bad = 0;
     size_t i;
     int status;
     status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt,
@@ -203,11 +204,12 @@ static int get_params_size(
                                                                 &ps_count,
                                                                 NULL);
     if (status) {
-        av_log(avctx, AV_LOG_ERROR, "Error getting parameter set count: %d\n", status);
-        return AVERROR_EXTERNAL;
+        is_count_bad = 1;
+        ps_count     = 0;
+        status       = 0;
     }
 
-    for(i = 0; i < ps_count; i++){
+    for (i = 0; i < ps_count || is_count_bad; i++) {
         const uint8_t *ps;
         size_t ps_size;
         status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt,
@@ -216,14 +218,24 @@ static int get_params_size(
                                                                     &ps_size,
                                                                     NULL,
                                                                     NULL);
-        if(status){
-            av_log(avctx, AV_LOG_ERROR, "Error getting parameter set size for index %zd: %d\n", i, status);
-            return AVERROR_EXTERNAL;
+        if (status) {
+            /*
+             * When ps_count is invalid, status != 0 ends the loop normally
+             * unless we didn't get any parameter sets.
+             */
+            if (i > 0 && is_count_bad) status = 0;
+
+            break;
         }
 
         total_size += ps_size + sizeof(start_code);
     }
 
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "Error getting parameter set sizes: %d\n", status);
+        return AVERROR_EXTERNAL;
+    }
+
     *size = total_size;
     return 0;
 }
@@ -235,6 +247,7 @@ static int copy_param_sets(
     size_t                      dst_size)
 {
     size_t ps_count;
+    int is_count_bad = 0;
     int status;
     size_t offset = 0;
     size_t i;
@@ -246,11 +259,13 @@ static int copy_param_sets(
                                                                 &ps_count,
                                                                 NULL);
     if (status) {
-        av_log(avctx, AV_LOG_ERROR, "Error getting parameter set count for copying: %d\n", status);
-        return AVERROR_EXTERNAL;
+        is_count_bad = 1;
+        ps_count     = 0;
+        status       = 0;
     }
 
-    for (i = 0; i < ps_count; i++) {
+
+    for (i = 0; i < ps_count || is_count_bad; i++) {
         const uint8_t *ps;
         size_t ps_size;
         size_t next_offset;
@@ -262,8 +277,9 @@ static int copy_param_sets(
                                                                     NULL,
                                                                     NULL);
         if (status) {
-            av_log(avctx, AV_LOG_ERROR, "Error getting parameter set data for index %zd: %d\n", i, status);
-            return AVERROR_EXTERNAL;
+            if (i > 0 && is_count_bad) status = 0;
+
+            break;
         }
 
         next_offset = offset + sizeof(start_code) + ps_size;
@@ -279,6 +295,11 @@ static int copy_param_sets(
         offset = next_offset;
     }
 
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "Error getting parameter set data: %d\n", status);
+        return AVERROR_EXTERNAL;
+    }
+
     return 0;
 }