[vlc-commits] codec: videotoolbox: refactor for other codecs support
Francois Cartegnie
git at videolan.org
Fri Nov 24 13:12:02 CET 2017
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Tue Oct 3 17:18:27 2017 +0200| [e96c4427790ca7ae8847f30bea32345fc6d5b72a] | committer: Thomas Guillem
codec: videotoolbox: refactor for other codecs support
Signed-off-by: Thomas Guillem <thomas at gllm.fr>
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=e96c4427790ca7ae8847f30bea32345fc6d5b72a
---
modules/codec/videotoolbox.m | 680 +++++++++++++++++++++++--------------------
1 file changed, 367 insertions(+), 313 deletions(-)
diff --git a/modules/codec/videotoolbox.m b/modules/codec/videotoolbox.m
index 8200d59ff5..e5f862d71f 100644
--- a/modules/codec/videotoolbox.m
+++ b/modules/codec/videotoolbox.m
@@ -99,10 +99,10 @@ enum vtsession_status
VTSESSION_STATUS_ABORT,
};
-static int SetH264DecoderInfo(decoder_t *, CFMutableDictionaryRef);
+static int ConfigureVout(decoder_t *);
static CFMutableDictionaryRef ESDSExtradataInfoCreate(decoder_t *, uint8_t *, uint32_t);
static CFMutableDictionaryRef ExtradataInfoCreate(CFStringRef, void *, size_t);
-static CFMutableDictionaryRef H264ExtradataInfoCreate(const struct hxxx_helper *hh);
+static CFMutableDictionaryRef CreateSessionDescriptionFormat(decoder_t *, unsigned, unsigned);
static int HandleVTStatus(decoder_t *, OSStatus, enum vtsession_status *);
static int DecodeBlock(decoder_t *, block_t *);
static void RequestFlush(decoder_t *);
@@ -138,11 +138,25 @@ struct decoder_sys_t
CMVideoCodecType codec;
struct hxxx_helper hh;
+ /* Codec specific callbacks */
+ bool (*pf_codec_init)(decoder_t *);
+ void (*pf_codec_clean)(decoder_t *);
+ bool (*pf_codec_supported)(decoder_t *);
+ bool (*pf_late_start)(decoder_t *);
+ block_t* (*pf_process_block)(decoder_t *,
+ block_t *, bool *);
+ bool (*pf_need_restart)(decoder_t *,
+ VTDecompressionSessionRef);
+ bool (*pf_configure_vout)(decoder_t *);
+ CFMutableDictionaryRef (*pf_get_extradata)(decoder_t *);
+ bool (*pf_fill_reorder_info)(decoder_t *, const block_t *,
+ frame_info_t *);
+ /* !Codec specific callbacks */
+
bool b_vt_feed;
bool b_vt_flush;
VTDecompressionSessionRef session;
CMVideoFormatDescriptionRef videoFormatDescription;
- CFMutableDictionaryRef extradataInfo;
vlc_mutex_t lock;
frame_info_t *p_pic_reorder;
@@ -159,13 +173,15 @@ struct decoder_sys_t
int i_forced_cvpx_format;
- h264_poc_context_t pocctx;
+ h264_poc_context_t h264_pocctx;
date_t pts;
};
#pragma mark - start & stop
-static void GetSPSPPS(uint8_t i_pps_id, void *priv,
+/* Codec Specific */
+
+static void GetxPSH264(uint8_t i_pps_id, void *priv,
const h264_sequence_parameter_set_t **pp_sps,
const h264_picture_parameter_set_t **pp_pps)
{
@@ -178,7 +194,7 @@ static void GetSPSPPS(uint8_t i_pps_id, void *priv,
*pp_sps = p_sys->hh.h264.sps_list[(*pp_pps)->i_sps_id].h264_sps;
}
-struct sei_callback_s
+struct sei_callback_h264_s
{
uint8_t i_pic_struct;
const h264_sequence_parameter_set_t *p_sps;
@@ -186,10 +202,9 @@ struct sei_callback_s
static bool ParseH264SEI(const hxxx_sei_data_t *p_sei_data, void *priv)
{
-
if(p_sei_data->i_type == HXXX_SEI_PIC_TIMING)
{
- struct sei_callback_s *s = priv;
+ struct sei_callback_h264_s *s = priv;
if(s->p_sps && s->p_sps->vui.b_valid)
{
if(s->p_sps->vui.b_hrd_parameters_present_flag)
@@ -207,13 +222,13 @@ static bool ParseH264SEI(const hxxx_sei_data_t *p_sei_data, void *priv)
return true;
}
-static bool ParseH264NAL(decoder_t *p_dec,
- const uint8_t *p_buffer, size_t i_buffer,
- uint8_t i_nal_length_size, frame_info_t *p_info)
+static bool FillReorderInfoH264(decoder_t *p_dec, const block_t *p_block,
+ frame_info_t *p_info)
{
decoder_sys_t *p_sys = p_dec->p_sys;
hxxx_iterator_ctx_t itctx;
- hxxx_iterator_init(&itctx, p_buffer, i_buffer, i_nal_length_size);
+ hxxx_iterator_init(&itctx, p_block->p_buffer, p_block->i_buffer,
+ p_sys->hh.i_nal_length_size);
const uint8_t *p_nal; size_t i_nal;
const uint8_t *p_sei_nal = NULL; size_t i_sei_nal = 0;
@@ -227,12 +242,12 @@ static bool ParseH264NAL(decoder_t *p_dec,
if (i_nal_type <= H264_NAL_SLICE_IDR && i_nal_type != H264_NAL_UNKNOWN)
{
h264_slice_t slice;
- if(!h264_decode_slice(p_nal, i_nal, GetSPSPPS, p_sys, &slice))
+ if(!h264_decode_slice(p_nal, i_nal, GetxPSH264, p_sys, &slice))
return false;
const h264_sequence_parameter_set_t *p_sps;
const h264_picture_parameter_set_t *p_pps;
- GetSPSPPS(slice.i_pic_parameter_set_id, p_sys, &p_sps, &p_pps);
+ GetxPSH264(slice.i_pic_parameter_set_id, p_sys, &p_sps, &p_pps);
if(p_sps)
{
if(!p_sys->b_invalid_pic_reorder_max && i_nal_type == H264_NAL_SLICE_IDR)
@@ -246,7 +261,7 @@ static bool ParseH264NAL(decoder_t *p_dec,
}
int bFOC;
- h264_compute_poc(p_sps, &slice, &p_sys->pocctx,
+ h264_compute_poc(p_sps, &slice, &p_sys->h264_pocctx,
&p_info->i_poc, &p_info->i_foc, &bFOC);
p_info->b_flush = (slice.type == H264_SLICE_TYPE_I) || slice.has_mmco5;
@@ -254,7 +269,7 @@ static bool ParseH264NAL(decoder_t *p_dec,
p_info->b_progressive = !p_sps->mb_adaptive_frame_field_flag &&
!slice.i_field_pic_flag;
- struct sei_callback_s sei;
+ struct sei_callback_h264_s sei;
sei.p_sps = p_sps;
sei.i_pic_struct = UINT8_MAX;
@@ -289,6 +304,225 @@ static bool ParseH264NAL(decoder_t *p_dec,
return false;
}
+
+static block_t *ProcessBlockH264(decoder_t *p_dec, block_t *p_block, bool *pb_config_changed)
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ return p_sys->hh.pf_process_block(&p_sys->hh, p_block, pb_config_changed);
+}
+
+
+static bool InitH264(decoder_t *p_dec)
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ h264_poc_context_init(&p_sys->h264_pocctx);
+ hxxx_helper_init(&p_sys->hh, VLC_OBJECT(p_dec),
+ p_dec->fmt_in.i_codec, true);
+ return hxxx_helper_set_extra(&p_sys->hh, p_dec->fmt_in.p_extra,
+ p_dec->fmt_in.i_extra) == VLC_SUCCESS;
+}
+
+static void CleanH264(decoder_t *p_dec)
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ hxxx_helper_clean(&p_sys->hh);
+}
+
+static CFMutableDictionaryRef GetDecoderExtradataH264(decoder_t *p_dec)
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+
+ CFMutableDictionaryRef extradata = nil;
+ if(p_dec->fmt_in.i_extra) /* copy DecoderConfiguration */
+ {
+ extradata = ExtradataInfoCreate(CFSTR("avcC"),
+ p_dec->fmt_in.p_extra,
+ p_dec->fmt_in.i_extra);
+ }
+ else if (p_sys->hh.h264.i_pps_count && p_sys->hh.h264.i_sps_count)
+ {
+ /* build DecoderConfiguration from gathered */
+ block_t *p_avcC = h264_helper_get_avcc_config(&p_sys->hh);
+ if (p_avcC)
+ {
+ extradata = ExtradataInfoCreate(CFSTR("avcC"),
+ p_avcC->p_buffer,
+ p_avcC->i_buffer);
+ block_Release(p_avcC);
+ }
+ }
+ return extradata;
+}
+
+static bool CodecSupportedH264(decoder_t *p_dec)
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+
+ uint8_t i_profile, i_level;
+ if (hxxx_helper_get_current_profile_level(&p_sys->hh, &i_profile, &i_level))
+ return true;
+
+ 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 bool LateStartH264(decoder_t *p_dec)
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ return (p_dec->fmt_in.i_extra == 0 &&
+ (!p_sys->hh.h264.i_pps_count || !p_sys->hh.h264.i_sps_count) );
+}
+
+static bool ConfigureVoutH264(decoder_t *p_dec)
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+
+ if(p_dec->fmt_in.video.primaries == COLOR_PRIMARIES_UNDEF)
+ {
+ video_color_primaries_t primaries;
+ video_transfer_func_t transfer;
+ video_color_space_t colorspace;
+ bool full_range;
+ if (hxxx_helper_get_colorimetry(&p_sys->hh,
+ &primaries,
+ &transfer,
+ &colorspace,
+ &full_range) == VLC_SUCCESS)
+ {
+ p_dec->fmt_out.video.primaries = primaries;
+ p_dec->fmt_out.video.transfer = transfer;
+ p_dec->fmt_out.video.space = colorspace;
+ p_dec->fmt_out.video.b_color_range_full = full_range;
+ }
+ }
+
+ if (!p_dec->fmt_in.video.i_visible_width || !p_dec->fmt_in.video.i_visible_height)
+ {
+ unsigned i_width, i_height, i_vis_width, i_vis_height;
+ if(VLC_SUCCESS ==
+ hxxx_helper_get_current_picture_size(&p_sys->hh,
+ &i_width, &i_height,
+ &i_vis_width, &i_vis_height))
+ {
+ p_dec->fmt_out.video.i_visible_width = i_vis_width;
+ p_dec->fmt_out.video.i_width = ALIGN_16( i_vis_width );
+ p_dec->fmt_out.video.i_visible_height = i_vis_height;
+ p_dec->fmt_out.video.i_height = ALIGN_16( i_vis_height );
+ }
+ else return false;
+ }
+
+ if(!p_dec->fmt_in.video.i_sar_num || !p_dec->fmt_in.video.i_sar_den)
+ {
+ int i_sar_num, i_sar_den;
+ if (VLC_SUCCESS ==
+ hxxx_helper_get_current_sar(&p_sys->hh, &i_sar_num, &i_sar_den))
+ {
+ p_dec->fmt_out.video.i_sar_num = i_sar_num;
+ p_dec->fmt_out.video.i_sar_den = i_sar_den;
+ }
+ }
+
+ return true;
+}
+
+static bool VideoToolboxNeedsToRestartH264(decoder_t *p_dec,
+ VTDecompressionSessionRef session)
+{
+ const struct hxxx_helper *hh = &p_dec->p_sys->hh;
+
+ unsigned w, h, vw, vh;
+ int sarn, sard;
+
+ if (hxxx_helper_get_current_picture_size(hh, &w, &h, &vw, &vh) != VLC_SUCCESS)
+ return true;
+
+ if (hxxx_helper_get_current_sar(hh, &sarn, &sard) != VLC_SUCCESS)
+ return true;
+
+ bool b_ret = true;
+
+ CFMutableDictionaryRef decoderConfiguration =
+ CreateSessionDescriptionFormat(p_dec, sarn, sard);
+ if (decoderConfiguration != nil)
+ {
+ CMFormatDescriptionRef newvideoFormatDesc;
+ /* create new video format description */
+ OSStatus status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
+ kCMVideoCodecType_H264,
+ vw, vh,
+ decoderConfiguration,
+ &newvideoFormatDesc);
+ if (!status)
+ {
+ b_ret = !VTDecompressionSessionCanAcceptFormatDescription(session,
+ newvideoFormatDesc);
+ CFRelease(newvideoFormatDesc);
+ }
+ CFRelease(decoderConfiguration);
+ }
+
+ return b_ret;
+}
+
+static CFMutableDictionaryRef GetDecoderExtradataMPEG4(decoder_t *p_dec)
+{
+ if (p_dec->fmt_in.i_extra)
+ return ESDSExtradataInfoCreate(p_dec, p_dec->fmt_in.p_extra,
+ p_dec->fmt_in.i_extra);
+ else
+ return nil; /* MPEG4 without esds ? */
+}
+
+static CFMutableDictionaryRef GetDecoderExtradataDefault(decoder_t *p_dec)
+{
+ return ExtradataInfoCreate(NULL, NULL, 0); /* Empty Needed ? */
+}
+
+/* !Codec Specific */
+
static void InsertIntoDPB(decoder_sys_t *p_sys, frame_info_t *p_info)
{
frame_info_t **pp_lead_in = &p_sys->p_pic_reorder;
@@ -397,13 +631,10 @@ static frame_info_t * CreateReorderInfo(decoder_t *p_dec, const block_t *p_block
if (!p_info)
return NULL;
- if (p_sys->b_poc_based_reorder)
+ if (p_sys->pf_fill_reorder_info)
{
- if (p_sys->codec != kCMVideoCodecType_H264 ||
- !ParseH264NAL(p_dec, p_block->p_buffer, p_block->i_buffer,
- p_sys->hh.i_nal_length_size , p_info))
+ if(!p_sys->pf_fill_reorder_info(p_dec, p_block, p_info))
{
- assert(p_sys->codec == kCMVideoCodecType_H264);
free(p_info);
return NULL;
}
@@ -548,15 +779,27 @@ static CMVideoCodecType CodecPrecheck(decoder_t *p_dec)
vlc_assert_unreachable();
}
-
static CFMutableDictionaryRef CreateSessionDescriptionFormat(decoder_t *p_dec,
unsigned i_sar_num,
unsigned i_sar_den)
{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+
CFMutableDictionaryRef decoderConfiguration = cfdict_create(2);
if (decoderConfiguration == NULL)
return nil;
+ CFMutableDictionaryRef extradata = p_sys->pf_get_extradata
+ ? p_sys->pf_get_extradata(p_dec) : nil;
+ if(extradata)
+ {
+ /* then decoder will also fail if required, no need to handle it */
+ CFDictionarySetValue(decoderConfiguration,
+ kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms,
+ extradata);
+ CFRelease(extradata);
+ }
+
CFDictionarySetValue(decoderConfiguration,
kCVImageBufferChromaLocationBottomFieldKey,
kCVImageBufferChromaLocation_Left);
@@ -565,23 +808,26 @@ static CFMutableDictionaryRef CreateSessionDescriptionFormat(decoder_t *p_dec,
kCVImageBufferChromaLocation_Left);
/* pixel aspect ratio */
- CFMutableDictionaryRef pixelaspectratio = cfdict_create(2);
- if(pixelaspectratio == NULL)
+ if(i_sar_num && i_sar_den)
{
- CFRelease(decoderConfiguration);
- return nil;
- }
+ CFMutableDictionaryRef pixelaspectratio = cfdict_create(2);
+ if(pixelaspectratio == NULL)
+ {
+ CFRelease(decoderConfiguration);
+ return nil;
+ }
- cfdict_set_int32(pixelaspectratio,
- kCVImageBufferPixelAspectRatioHorizontalSpacingKey,
- i_sar_num);
- cfdict_set_int32(pixelaspectratio,
- kCVImageBufferPixelAspectRatioVerticalSpacingKey,
- i_sar_den);
- CFDictionarySetValue(decoderConfiguration,
- kCVImageBufferPixelAspectRatioKey,
- pixelaspectratio);
- CFRelease(pixelaspectratio);
+ cfdict_set_int32(pixelaspectratio,
+ kCVImageBufferPixelAspectRatioHorizontalSpacingKey,
+ i_sar_num);
+ cfdict_set_int32(pixelaspectratio,
+ kCVImageBufferPixelAspectRatioVerticalSpacingKey,
+ i_sar_den);
+ CFDictionarySetValue(decoderConfiguration,
+ kCVImageBufferPixelAspectRatioKey,
+ pixelaspectratio);
+ CFRelease(pixelaspectratio);
+ }
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpartial-availability"
@@ -612,55 +858,20 @@ static CFMutableDictionaryRef CreateSessionDescriptionFormat(decoder_t *p_dec,
return decoderConfiguration;
}
-static bool VideoToolboxNeedsToRestartH264(decoder_t *p_dec,
- VTDecompressionSessionRef session,
- const struct hxxx_helper *hh)
+static int StartVideoToolbox(decoder_t *p_dec)
{
- unsigned w, h, vw, vh;
- int sarn, sard;
-
- if (hxxx_helper_get_current_picture_size(hh, &w, &h, &vw, &vh) != VLC_SUCCESS)
- return true;
-
- if (hxxx_helper_get_current_sar(hh, &sarn, &sard) != VLC_SUCCESS)
- return true;
-
- CFMutableDictionaryRef extradataInfo = H264ExtradataInfoCreate(hh);
- if(extradataInfo == nil)
- return true;
-
- bool b_ret = true;
+ decoder_sys_t *p_sys = p_dec->p_sys;
- CFMutableDictionaryRef decoderConfiguration =
- CreateSessionDescriptionFormat(p_dec, sarn, sard);
- if (decoderConfiguration != nil)
+ /* Late starts */
+ if(p_sys->pf_late_start && p_sys->pf_late_start(p_dec))
{
- CFDictionarySetValue(decoderConfiguration,
- kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms,
- extradataInfo);
- CMFormatDescriptionRef newvideoFormatDesc;
- /* create new video format description */
- OSStatus status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
- kCMVideoCodecType_H264,
- vw, vh,
- decoderConfiguration,
- &newvideoFormatDesc);
- if (!status)
- {
- b_ret = !VTDecompressionSessionCanAcceptFormatDescription(session,
- newvideoFormatDesc);
- CFRelease(newvideoFormatDesc);
- }
- CFRelease(decoderConfiguration);
+ assert(p_sys->session == NULL);
+ return VLC_SUCCESS;
}
- CFRelease(extradataInfo);
- return b_ret;
-}
-
-static int StartVideoToolbox(decoder_t *p_dec)
-{
- decoder_sys_t *p_sys = p_dec->p_sys;
+ /* Fills fmt_out (from extradata if any) */
+ if(ConfigureVout(p_dec) != VLC_SUCCESS)
+ return VLC_EGENERIC;
/* destination pixel buffer attributes */
CFMutableDictionaryRef destinationPixelBufferAttributes = cfdict_create(2);
@@ -677,13 +888,6 @@ static int StartVideoToolbox(decoder_t *p_dec)
return VLC_EGENERIC;
}
- if(p_sys->extradataInfo)
- {
- CFDictionarySetValue(decoderConfiguration,
- kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms,
- p_sys->extradataInfo);
- }
-
/* create video format description */
OSStatus status = CMVideoFormatDescriptionCreate(
kCFAllocatorDefault,
@@ -811,48 +1015,6 @@ static int RestartVideoToolbox(decoder_t *p_dec, bool b_reset_format)
#pragma mark - module open and close
-static int SetupDecoderExtradata(decoder_t *p_dec)
-{
- decoder_sys_t *p_sys = p_dec->p_sys;
- CFMutableDictionaryRef extradata_info = NULL;
-
- assert(p_sys->extradataInfo == nil);
- if (p_sys->codec == kCMVideoCodecType_H264)
- {
- hxxx_helper_init(&p_sys->hh, VLC_OBJECT(p_dec),
- p_dec->fmt_in.i_codec, true);
- int i_ret = hxxx_helper_set_extra(&p_sys->hh, p_dec->fmt_in.p_extra,
- p_dec->fmt_in.i_extra);
- if (i_ret != VLC_SUCCESS)
- return i_ret;
- assert(p_sys->hh.pf_process_block != NULL);
-
- if (p_dec->fmt_in.p_extra)
- {
- p_sys->extradataInfo = ExtradataInfoCreate(CFSTR("avcC"),
- p_dec->fmt_in.p_extra,
- p_dec->fmt_in.i_extra);
- if (SetH264DecoderInfo(p_dec, p_sys->extradataInfo) != VLC_SUCCESS)
- return VLC_EGENERIC;
- }
- else
- {
- /* AnnexB case, we'll get extradata from first input blocks */
- return VLC_SUCCESS;
- }
- }
- else if (p_sys->codec == kCMVideoCodecType_MPEG4Video)
- {
- if (!p_dec->fmt_in.i_extra)
- return VLC_EGENERIC;
- p_sys->extradataInfo = ESDSExtradataInfoCreate(p_dec, p_dec->fmt_in.p_extra,
- p_dec->fmt_in.i_extra);
- }
- else
- p_sys->extradataInfo = ExtradataInfoCreate(NULL, NULL, 0);
-
- return p_sys->extradataInfo != nil ? VLC_SUCCESS : VLC_EGENERIC;
-}
static int OpenDecoder(vlc_object_t *p_this)
{
@@ -879,22 +1041,14 @@ static int OpenDecoder(vlc_object_t *p_this)
/* now that we see a chance to decode anything, allocate the
* internals and start the decoding session */
decoder_sys_t *p_sys;
- p_sys = malloc(sizeof(*p_sys));
+ p_sys = calloc(1, sizeof(*p_sys));
if (!p_sys)
return VLC_ENOMEM;
p_dec->p_sys = p_sys;
p_sys->session = nil;
- p_sys->b_vt_feed = false;
- p_sys->b_vt_flush = false;
p_sys->codec = codec;
p_sys->videoFormatDescription = nil;
- p_sys->extradataInfo = nil;
- p_sys->p_pic_reorder = NULL;
- p_sys->i_pic_reorder = 0;
p_sys->i_pic_reorder_max = 4;
- p_sys->b_invalid_pic_reorder_max = false;
- p_sys->b_poc_based_reorder = false;
- p_sys->b_format_propagated = false;
p_sys->vtsession_status = VTSESSION_STATUS_OK;
p_sys->b_enable_temporal_processing =
var_InheritBool(p_dec, "videotoolbox-temporal-deinterlacing");
@@ -913,53 +1067,52 @@ static int OpenDecoder(vlc_object_t *p_this)
p_sys->i_forced_cvpx_format = ntohl(p_sys->i_forced_cvpx_format);
free(cvpx_chroma);
}
- else
- p_dec->p_sys->i_forced_cvpx_format = 0;
- h264_poc_context_init( &p_sys->pocctx );
vlc_mutex_init(&p_sys->lock);
- /* return our proper VLC internal state */
- p_dec->fmt_out.video = p_dec->fmt_in.video;
- if (!p_dec->fmt_out.video.i_sar_num || !p_dec->fmt_out.video.i_sar_den)
- {
- p_dec->fmt_out.video.i_sar_num = 1;
- p_dec->fmt_out.video.i_sar_den = 1;
- }
- if (!p_dec->fmt_out.video.i_visible_width
- || !p_dec->fmt_out.video.i_visible_height)
- {
- p_dec->fmt_out.video.i_visible_width = p_dec->fmt_out.video.i_width;
- p_dec->fmt_out.video.i_visible_height = p_dec->fmt_out.video.i_height;
- }
- p_dec->fmt_out.video.i_width = ALIGN_16( p_dec->fmt_out.video.i_visible_width );
- p_dec->fmt_out.video.i_height = ALIGN_16( p_dec->fmt_out.video.i_visible_height );
-
- p_dec->fmt_out.i_codec = 0;
-
- if( codec == kCMVideoCodecType_H264 )
- p_sys->b_poc_based_reorder = true;
-
- int i_ret = SetupDecoderExtradata(p_dec);
- if (i_ret != VLC_SUCCESS)
- goto error;
+ p_dec->pf_decode = DecodeBlock;
+ p_dec->pf_flush = RequestFlush;
- if (p_sys->extradataInfo != nil)
+ switch(codec)
{
- i_ret = StartVideoToolbox(p_dec);
- if (i_ret != VLC_SUCCESS)
- goto error;
- } /* else: late opening */
+ case kCMVideoCodecType_H264:
+ p_sys->pf_codec_init = InitH264;
+ p_sys->pf_codec_clean = CleanH264;
+ p_sys->pf_codec_supported = CodecSupportedH264;
+ p_sys->pf_late_start = LateStartH264;
+ p_sys->pf_process_block = ProcessBlockH264;
+ p_sys->pf_need_restart = VideoToolboxNeedsToRestartH264;
+ p_sys->pf_configure_vout = ConfigureVoutH264;
+ p_sys->pf_get_extradata = GetDecoderExtradataH264;
+ p_sys->pf_fill_reorder_info = FillReorderInfoH264;
+ p_sys->b_poc_based_reorder = true;
+ break;
- p_dec->pf_decode = DecodeBlock;
- p_dec->pf_flush = RequestFlush;
+ case kCMVideoCodecType_MPEG4Video:
+ p_sys->pf_get_extradata = GetDecoderExtradataMPEG4;
+ break;
- msg_Info(p_dec, "Using Video Toolbox to decode '%4.4s'", (char *)&p_dec->fmt_in.i_codec);
+ default:
+ p_sys->pf_get_extradata = GetDecoderExtradataDefault;
+ break;
+ }
- return VLC_SUCCESS;
+ if(p_sys->pf_codec_init && !p_sys->pf_codec_init(p_dec))
+ {
+ CloseDecoder(p_this);
+ return VLC_EGENERIC;
+ }
-error:
- CloseDecoder(p_this);
+ int i_ret = StartVideoToolbox(p_dec);
+ if(i_ret == VLC_SUCCESS)
+ {
+ msg_Info(p_dec, "Using Video Toolbox to decode '%4.4s'",
+ (char *)&p_dec->fmt_in.i_codec);
+ }
+ else
+ {
+ CloseDecoder(p_this);
+ }
return i_ret;
}
@@ -969,11 +1122,9 @@ static void CloseDecoder(vlc_object_t *p_this)
decoder_sys_t *p_sys = p_dec->p_sys;
StopVideoToolbox(p_dec, true);
- if (p_sys->extradataInfo)
- CFRelease(p_sys->extradataInfo);
- if (p_sys->codec == kCMVideoCodecType_H264)
- hxxx_helper_clean(&p_sys->hh);
+ if(p_sys->pf_codec_clean)
+ p_sys->pf_codec_clean(p_dec);
vlc_mutex_destroy(&p_sys->lock);
free(p_sys);
@@ -1085,125 +1236,33 @@ static CFMutableDictionaryRef ESDSExtradataInfoCreate(decoder_t *p_dec,
return extradataInfo;
}
-static CFMutableDictionaryRef H264ExtradataInfoCreate(const struct hxxx_helper *hh)
-{
- CFMutableDictionaryRef extradataInfo = nil;
- block_t *p_avcC = h264_helper_get_avcc_config(hh);
- if (p_avcC)
- {
- extradataInfo = ExtradataInfoCreate(CFSTR("avcC"),
- p_avcC->p_buffer, p_avcC->i_buffer);
- block_Release(p_avcC);
- }
- return extradataInfo;
-}
-
-static bool IsH264ProfileLevelSupported(decoder_t *p_dec, uint8_t i_profile,
- uint8_t i_level)
+static int ConfigureVout(decoder_t *p_dec)
{
- 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;
+ /* return our proper VLC internal state */
+ p_dec->fmt_out.video = p_dec->fmt_in.video;
+ p_dec->fmt_out.video.p_palette = NULL;
+ p_dec->fmt_out.i_codec = 0;
- if (p_sys->hh.h264.i_sps_count == 0 || p_sys->hh.h264.i_pps_count == 0)
+ if(p_dec->p_sys->pf_configure_vout &&
+ !p_dec->p_sys->pf_configure_vout(p_dec))
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 = hxxx_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 = hxxx_helper_get_current_picture_size(&p_sys->hh,
- &i_h264_width, &i_h264_height,
- &i_video_width, &i_video_height);
- if (i_ret != VLC_SUCCESS)
- return i_ret;
-
- i_ret = hxxx_helper_get_current_sar(&p_sys->hh, &i_sar_num, &i_sar_den);
- if (i_ret != VLC_SUCCESS)
- return i_ret;
-
- video_color_primaries_t primaries;
- video_transfer_func_t transfer;
- video_color_space_t colorspace;
- bool full_range;
- if (hxxx_helper_get_colorimetry(&p_sys->hh, &primaries, &transfer,
- &colorspace, &full_range) == VLC_SUCCESS
- && primaries != COLOR_PRIMARIES_UNDEF && transfer != TRANSFER_FUNC_UNDEF
- && colorspace != COLOR_SPACE_UNDEF)
+ if (!p_dec->fmt_out.video.i_sar_num || !p_dec->fmt_out.video.i_sar_den)
{
- p_dec->fmt_out.video.primaries = primaries;
- p_dec->fmt_out.video.transfer = transfer;
- p_dec->fmt_out.video.space = colorspace;
- p_dec->fmt_out.video.b_color_range_full = full_range;
+ p_dec->fmt_out.video.i_sar_num = 1;
+ p_dec->fmt_out.video.i_sar_den = 1;
}
- p_dec->fmt_out.video.i_visible_width = i_video_width;
- p_dec->fmt_out.video.i_width = ALIGN_16( i_video_width );
- p_dec->fmt_out.video.i_visible_height = i_video_height;
- p_dec->fmt_out.video.i_height = ALIGN_16( i_video_height );
- p_dec->fmt_out.video.i_sar_num = i_sar_num;
- p_dec->fmt_out.video.i_sar_den = i_sar_den;
-
- if (extradataInfo == nil)
+ if (!p_dec->fmt_out.video.i_visible_width || !p_dec->fmt_out.video.i_visible_height)
{
- if (p_sys->extradataInfo != nil)
- CFRelease(p_sys->extradataInfo);
- p_sys->extradataInfo = H264ExtradataInfoCreate(&p_sys->hh);
+ p_dec->fmt_out.video.i_visible_width = p_dec->fmt_out.video.i_width;
+ p_dec->fmt_out.video.i_visible_height = p_dec->fmt_out.video.i_height;
}
- return (p_sys->extradataInfo == nil) ? VLC_EGENERIC: VLC_SUCCESS;
+ p_dec->fmt_out.video.i_width = ALIGN_16( p_dec->fmt_out.video.i_visible_width );
+ p_dec->fmt_out.video.i_height = ALIGN_16( p_dec->fmt_out.video.i_visible_height );
+
+ return VLC_SUCCESS;
}
static CFMutableDictionaryRef ExtradataInfoCreate(CFStringRef name,
@@ -1440,9 +1499,9 @@ static int DecodeBlock(decoder_t *p_dec, block_t *p_block)
}
bool b_config_changed = false;
- if (p_sys->codec == kCMVideoCodecType_H264)
+ if(p_sys->pf_process_block)
{
- p_block = p_sys->hh.pf_process_block(&p_sys->hh, p_block, &b_config_changed);
+ p_block = p_sys->pf_process_block(p_dec, p_block, &b_config_changed);
if (!p_block)
return VLCDEC_SUCCESS;
}
@@ -1451,40 +1510,35 @@ static int DecodeBlock(decoder_t *p_dec, block_t *p_block)
if(unlikely(!p_info))
goto skip;
- if (b_config_changed && p_info->b_flush)
+ if (!p_sys->session /* Late Start */||
+ (b_config_changed && p_info->b_flush))
{
- assert(p_sys->codec == kCMVideoCodecType_H264);
- if (!p_sys->session ||
- VideoToolboxNeedsToRestartH264(p_dec,p_sys->session, &p_sys->hh))
+ if (p_sys->session &&
+ p_sys->pf_need_restart &&
+ p_sys->pf_need_restart(p_dec,p_sys->session))
{
- if (p_sys->session)
- {
- msg_Dbg(p_dec, "SPS/PPS changed: draining H264 decoder");
- Drain(p_dec, false);
- msg_Dbg(p_dec, "SPS/PPS changed: restarting H264 decoder");
- StopVideoToolbox(p_dec, true);
- }
- /* else decoding didn't start yet, which is ok for H264, let's see
- * if we can use this block to get going */
+ msg_Dbg(p_dec, "parameters sets changed: draining decoder");
+ Drain(p_dec, false);
+ msg_Dbg(p_dec, "parameters sets changed: restarting decoder");
+ StopVideoToolbox(p_dec, true);
+ }
- int i_ret = SetH264DecoderInfo(p_dec, nil);
- if (i_ret == VLC_SUCCESS)
+ if(!p_sys->session)
+ {
+ if(!p_sys->pf_codec_supported || p_sys->pf_codec_supported(p_dec))
{
- msg_Dbg(p_dec, "Got SPS/PPS: late opening of H264 decoder");
StartVideoToolbox(p_dec);
}
- else if (i_ret == VLC_ENOMOD)
+ else
{
- /* The current device doesn't handle the h264 profile/level,
- * abort */
+ /* The current device doesn't handle the 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)
+ if (!p_sys->session) /* Start Failed */
{
free(p_info);
goto skip;
More information about the vlc-commits
mailing list