[vlc-commits] codec: videotoolbox: always check device capabilities

Thomas Guillem git at videolan.org
Thu Sep 28 11:10:43 CEST 2017


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Thu Sep 28 11:06:19 2017 +0200| [41ce842d1cdfcbc3c76952f7e999598f5444e309] | committer: Thomas Guillem

codec: videotoolbox: always check device capabilities

The H264 profile/level check was only done for avcC content and not when a new
SPS/PPS was parsed.

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

 modules/codec/videotoolbox.m | 129 +++++++++++++++++++++++--------------------
 1 file changed, 70 insertions(+), 59 deletions(-)

diff --git a/modules/codec/videotoolbox.m b/modules/codec/videotoolbox.m
index 8fa4904d52..1267930716 100644
--- a/modules/codec/videotoolbox.m
+++ b/modules/codec/videotoolbox.m
@@ -468,69 +468,14 @@ static void OnDecodedFrame(decoder_t *p_dec, frame_info_t *p_info)
     InsertIntoDPB(p_sys, p_info);
 }
 
-static CMVideoCodecType CodecPrecheck(decoder_t *p_dec, int *p_cvpx_chroma)
+static CMVideoCodecType CodecPrecheck(decoder_t *p_dec)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
 
     /* check for the codec we can and want to decode */
     switch (p_dec->fmt_in.i_codec) {
         case VLC_CODEC_H264:
-        {
-            uint8_t i_profile, i_level;
-            if (!h264_get_profile_level(&p_dec->fmt_in, &i_profile, &i_level, NULL))
-            {
-                msg_Warn(p_dec, "H264 profile and level parsing failed because it didn't arrive yet");
-                return kCMVideoCodecType_H264;
-            }
-
-            msg_Dbg(p_dec, "trying to decode MPEG-4 Part 10: profile %" PRIx8 ", level %" PRIx8, i_profile, i_level);
-
-            switch (i_profile) {
-                case PROFILE_H264_BASELINE:
-                case PROFILE_H264_MAIN:
-                case PROFILE_H264_HIGH:
-                    break;
-
-                case PROFILE_H264_HIGH_10:
-                {
-                    if (deviceSupportsAdvancedProfiles())
-                    {
-                        /* FIXME: There is no YUV420 10bits chroma. The
-                         * decoder seems to output RGBA when decoding 10bits
-                         * content, but there is an unknown crash when
-                         * displaying such output, so force NV12 for now. */
-                        *p_cvpx_chroma =
-                                kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
-                        break;
-                    }
-                }
-
-                default:
-                {
-                    msg_Dbg(p_dec, "unsupported H264 profile %" PRIx8, i_profile);
-                    return -1;
-                }
-            }
-
-#if !TARGET_OS_IPHONE
-            /* a level higher than 5.2 was not tested, so don't dare to
-             * try to decode it*/
-            if (i_level > 52) {
-                msg_Dbg(p_dec, "unsupported H264 level %" PRIx8, i_level);
-                return -1;
-            }
-#else
-            /* on SoC A8, 4.2 is the highest specified profile */
-            if (i_level > 42) {
-                /* on Twister, we can do up to 5.2 */
-                if (!deviceSupportsAdvancedLevels() || i_level > 52) {
-                    msg_Dbg(p_dec, "unsupported H264 level %" PRIx8, i_level);
-                    return -1;
-                }
-            }
-#endif
             return kCMVideoCodecType_H264;
-        }
 
         case VLC_CODEC_MP4V:
         {
@@ -923,8 +868,8 @@ static int OpenDecoder(vlc_object_t *p_this)
 
     /* check quickly if we can digest the offered data */
     CMVideoCodecType codec;
-    int codec_cvpx_chroma = 0;
-    codec = CodecPrecheck(p_dec, &codec_cvpx_chroma);
+
+    codec = CodecPrecheck(p_dec);
     if (codec == -1)
         return VLC_EGENERIC;
 
@@ -966,7 +911,7 @@ static int OpenDecoder(vlc_object_t *p_this)
         free(cvpx_chroma);
     }
     else
-        p_sys->i_forced_cvpx_format = codec_cvpx_chroma;
+        p_dec->p_sys->i_forced_cvpx_format = 0;
 
     h264_poc_context_init( &p_sys->pocctx );
     vlc_mutex_init(&p_sys->lock);
@@ -1146,6 +1091,55 @@ static CFMutableDictionaryRef H264ExtradataInfoCreate(const struct hxxx_helper *
     return extradataInfo;
 }
 
+static bool IsH264ProfileLevelSupported(decoder_t *p_dec, uint8_t i_profile,
+                                        uint8_t i_level)
+{
+    switch (i_profile) {
+        case PROFILE_H264_BASELINE:
+        case PROFILE_H264_MAIN:
+        case PROFILE_H264_HIGH:
+            break;
+
+        case PROFILE_H264_HIGH_10:
+        {
+            if (deviceSupportsAdvancedProfiles())
+            {
+                /* FIXME: There is no YUV420 10bits chroma. The
+                 * decoder seems to output RGBA when decoding 10bits
+                 * content, but there is an unknown crash when
+                 * displaying such output, so force NV12 for now. */
+                if (p_dec->p_sys->i_forced_cvpx_format == 0)
+                    p_dec->p_sys->i_forced_cvpx_format =
+                        kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
+                break;
+            }
+            else
+            {
+                msg_Err(p_dec, "current device doesn't support H264 10bits");
+                return false;
+            }
+        }
+
+        default:
+        {
+            msg_Warn(p_dec, "unknown H264 profile %" PRIx8, i_profile);
+            return false;
+        }
+    }
+
+    /* A level higher than 5.2 was not tested, so don't dare to try to decode
+     * it. On SoC A8, 4.2 is the highest specified profile. on Twister, we can
+     * do up to 5.2 */
+    if (i_level > 52 || (i_level > 42 && !deviceSupportsAdvancedLevels()))
+    {
+        msg_Err(p_dec, "current device doesn't support this H264 level: %"
+                PRIx8, i_level);
+        return false;
+    }
+
+    return true;
+}
+
 static int SetH264DecoderInfo(decoder_t *p_dec, CFMutableDictionaryRef extradataInfo)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
@@ -1153,8 +1147,16 @@ static int SetH264DecoderInfo(decoder_t *p_dec, CFMutableDictionaryRef extradata
     if (p_sys->hh.h264.i_sps_count == 0 || p_sys->hh.h264.i_pps_count == 0)
         return VLC_EGENERIC;
 
+    uint8_t i_profile, i_level;
     unsigned i_h264_width, i_h264_height, i_video_width, i_video_height;
     int i_sar_num, i_sar_den, i_ret;
+
+    i_ret = h264_helper_get_current_profile_level(&p_sys->hh, &i_profile, &i_level);
+    if (i_ret != VLC_SUCCESS)
+        return i_ret;
+    if (!IsH264ProfileLevelSupported(p_dec, i_profile, i_level))
+        return VLC_ENOMOD; /* This error is critical */
+
     i_ret = h264_helper_get_current_picture_size(&p_sys->hh,
                                                  &i_h264_width, &i_h264_height,
                                                  &i_video_width, &i_video_height);
@@ -1463,6 +1465,15 @@ static int DecodeBlock(decoder_t *p_dec, block_t *p_block)
                 msg_Dbg(p_dec, "Got SPS/PPS: late opening of H264 decoder");
                 StartVideoToolbox(p_dec);
             }
+            else if (i_ret == VLC_ENOMOD)
+            {
+                /* The current device doesn't handle the h264 profile/level,
+                 * abort */
+                vlc_mutex_lock(&p_sys->lock);
+                p_sys->vtsession_status = VTSESSION_STATUS_ABORT;
+                vlc_mutex_unlock(&p_sys->lock);
+                goto skip;
+            }
         }
 
         if (!p_sys->session)



More information about the vlc-commits mailing list