Commit 41ce842d authored by Thomas Guillem's avatar 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.
parent 6ab01528
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment