[vlc-commits] decoder: VideoToolBox: use POC for H264
Francois Cartegnie
git at videolan.org
Wed Mar 29 18:46:17 CEST 2017
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Mon Mar 20 17:27:23 2017 +0100| [017f1b05530e53ab35e525327586325685ffa5e4] | committer: Francois Cartegnie
decoder: VideoToolBox: use POC for H264
Also fixes the PTS less playback
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=017f1b05530e53ab35e525327586325685ffa5e4
---
modules/codec/Makefile.am | 2 +
modules/codec/videotoolbox.m | 492 ++++++++++++++++++++++++++++++++-----------
2 files changed, 368 insertions(+), 126 deletions(-)
diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am
index f749853..8b58032 100644
--- a/modules/codec/Makefile.am
+++ b/modules/codec/Makefile.am
@@ -318,6 +318,8 @@ codec_LTLIBRARIES += $(LTLIBoggspots)
libvideotoolbox_plugin_la_SOURCES = video_chroma/copy.c video_chroma/copy.h \
codec/videotoolbox.m codec/hxxx_helper.c codec/hxxx_helper.h \
packetizer/hxxx_nal.h packetizer/hxxx_nal.c \
+ packetizer/hxxx_sei.h packetizer/hxxx_sei.c \
+ packetizer/h264_slice.c packetizer/h264_slice.h \
packetizer/h264_nal.c packetizer/h264_nal.h \
packetizer/hevc_nal.c packetizer/hevc_nal.h
if HAVE_OSX
diff --git a/modules/codec/videotoolbox.m b/modules/codec/videotoolbox.m
index b40e118..2240969 100644
--- a/modules/codec/videotoolbox.m
+++ b/modules/codec/videotoolbox.m
@@ -30,9 +30,13 @@
#import <vlc_plugin.h>
#import <vlc_codec.h>
#import "hxxx_helper.h"
-#import "../video_chroma/copy.h"
#import <vlc_bits.h>
#import <vlc_boxes.h>
+#import "../packetizer/h264_nal.h"
+#import "../packetizer/h264_slice.h"
+#import "../packetizer/hxxx_nal.h"
+#import "../packetizer/hxxx_sei.h"
+#import "../video_chroma/copy.h"
#import <VideoToolbox/VideoToolbox.h>
#import <VideoToolbox/VTErrors.h>
@@ -86,10 +90,6 @@ static int avcCFromAnnexBCreate(decoder_t *);
static int ExtradataInfoCreate(decoder_t *, CFStringRef, void *, size_t);
static int HandleVTStatus(decoder_t *, OSStatus);
static int DecodeBlock(decoder_t *, block_t *);
-static void PicReorder_pushSorted(decoder_t *, picture_t *);
-static picture_t *PicReorder_pop(decoder_t *, bool);
-static void PicReorder_flush(decoder_t *);
-static void PicReorder_setup(decoder_t *);
static void Flush(decoder_t *);
static void DecoderCallback(void *, void *, OSStatus, VTDecodeInfoFlags,
CVPixelBufferRef, CMTime, CMTime);
@@ -103,8 +103,25 @@ struct picture_sys_t {
CFTypeRef pixelBuffer;
};
+typedef struct frame_info_t frame_info_t;
+
+struct frame_info_t
+{
+ picture_t *p_picture;
+ int i_poc;
+ int i_foc;
+ bool b_flush;
+ bool b_field;
+ bool b_progressive;
+ uint8_t i_num_ts;
+ unsigned i_length;
+ frame_info_t *p_next;
+};
+
#pragma mark - decoder structure
+#define H264_MAX_DPB 16
+
struct decoder_sys_t
{
CMVideoCodecType codec;
@@ -119,17 +136,279 @@ struct decoder_sys_t
CFMutableDictionaryRef extradataInfo;
vlc_mutex_t lock;
- picture_t *p_pic_reorder;
- size_t i_pic_reorder;
- size_t i_pic_reorder_max;
+ frame_info_t *p_pic_reorder;
+ uint8_t i_pic_reorder;
+ uint8_t i_pic_reorder_max;
+ bool b_poc_based_reorder;
bool b_enable_temporal_processing;
bool b_format_propagated;
bool b_abort;
+
+ poc_context_t pocctx;
+ date_t pts;
};
#pragma mark - start & stop
+static void GetSPSPPS(uint8_t i_pps_id, void *priv,
+ const h264_sequence_parameter_set_t **pp_sps,
+ const h264_picture_parameter_set_t **pp_pps)
+{
+ decoder_sys_t *p_sys = priv;
+
+ *pp_pps = p_sys->hh.h264.pps_list[i_pps_id].h264_pps;
+ if(*pp_pps == NULL)
+ *pp_sps = NULL;
+ else
+ *pp_sps = p_sys->hh.h264.sps_list[(*pp_pps)->i_sps_id].h264_sps;
+}
+
+struct sei_callback_s
+{
+ uint8_t i_pic_struct;
+ const h264_sequence_parameter_set_t *p_sps;
+};
+
+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;
+ if(s->p_sps && s->p_sps->vui.b_valid)
+ {
+ if(s->p_sps->vui.b_hrd_parameters_present_flag)
+ {
+ bs_read(p_sei_data->p_bs, s->p_sps->vui.i_cpb_removal_delay_length_minus1 + 1);
+ bs_read(p_sei_data->p_bs, s->p_sps->vui.i_dpb_output_delay_length_minus1 + 1);
+ }
+
+ if(s->p_sps->vui.b_pic_struct_present_flag)
+ s->i_pic_struct = bs_read( p_sei_data->p_bs, 4);
+ }
+ return false;
+ }
+
+ return true;
+}
+
+static bool ParseH264NAL(decoder_sys_t *p_sys,
+ const uint8_t *p_buffer, size_t i_buffer,
+ uint8_t i_nal_length_size, frame_info_t *p_info)
+{
+ hxxx_iterator_ctx_t itctx;
+ hxxx_iterator_init(&itctx, p_buffer, i_buffer, 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;
+ while(hxxx_iterate_next(&itctx, &p_nal, &i_nal))
+ {
+ if(i_nal < 2)
+ continue;
+
+ const enum h264_nal_unit_type_e i_nal_type = p_nal[0] & 0x1F;
+
+ 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))
+ 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);
+ if(p_sps)
+ {
+ unsigned dummy;
+ uint8_t i_reorder;
+ h264_get_dpb_values(p_sps, &i_reorder, &dummy);
+ vlc_mutex_lock(&p_sys->lock);
+ p_sys->i_pic_reorder_max = i_reorder;
+ vlc_mutex_unlock(&p_sys->lock);
+
+ int bFOC;
+ h264_compute_poc(p_sps, &slice, &p_sys->pocctx,
+ &p_info->i_poc, &p_info->i_foc, &bFOC);
+
+ p_info->b_flush = (slice.type == H264_SLICE_TYPE_I) || slice.has_mmco5;
+ p_info->b_field = slice.i_field_pic_flag;
+ p_info->b_progressive = !p_sps->mb_adaptive_frame_field_flag &&
+ !slice.i_field_pic_flag;
+
+ struct sei_callback_s sei;
+ sei.p_sps = p_sps;
+ sei.i_pic_struct = UINT8_MAX;
+
+ if(p_sei_nal)
+ HxxxParseSEI(p_sei_nal, i_sei_nal, 1, ParseH264SEI, &sei);
+
+ p_info->i_num_ts = h264_get_num_ts(p_sps, &slice, sei.i_pic_struct,
+ p_info->i_foc, bFOC);
+ }
+
+ return true; /* No need to parse further NAL */
+ }
+ else if(i_nal_type == H264_NAL_SEI)
+ {
+ p_sei_nal = p_nal;
+ i_sei_nal = i_nal;
+ }
+ }
+
+ return false;
+}
+
+static void InsertIntoDPB(decoder_sys_t *p_sys, frame_info_t *p_info)
+{
+ frame_info_t **pp_lead_in = &p_sys->p_pic_reorder;
+
+ for( ;; pp_lead_in = & ((*pp_lead_in)->p_next))
+ {
+ bool b_insert;
+ if(*pp_lead_in == NULL)
+ b_insert = true;
+ else if(p_sys->b_poc_based_reorder)
+ b_insert = ((*pp_lead_in)->i_foc > p_info->i_foc);
+ else
+ b_insert = ((*pp_lead_in)->p_picture->date >= p_info->p_picture->date);
+
+ if(b_insert)
+ {
+ p_info->p_next = *pp_lead_in;
+ *pp_lead_in = p_info;
+ p_sys->i_pic_reorder += (p_info->b_field) ? 1 : 2;
+ break;
+ }
+ }
+#if 0
+ for(frame_info_t *p_in=p_sys->p_pic_reorder; p_in; p_in = p_in->p_next)
+ printf(" %d", p_in->i_foc);
+ printf("\n");
+#endif
+}
+
+static picture_t * RemoveOneFrameFromDPB(decoder_sys_t *p_sys)
+{
+ frame_info_t *p_info = p_sys->p_pic_reorder;
+ if(p_info == NULL)
+ return NULL;
+
+ const int i_framepoc = p_info->i_poc;
+
+ picture_t *p_ret = NULL;
+ picture_t **pp_ret_last = &p_ret;
+ bool b_dequeue;
+
+ do
+ {
+ picture_t *p_field = p_info->p_picture;
+
+ /* Compute time if missing */
+ if (p_field->date == VLC_TS_INVALID)
+ p_field->date = date_Get(&p_sys->pts);
+ else
+ date_Set(&p_sys->pts, p_field->date);
+
+ /* Set next picture time, in case it is missing */
+ if (p_info->i_length)
+ date_Set(&p_sys->pts, p_field->date + p_info->i_length);
+ else
+ date_Increment(&p_sys->pts, p_info->i_num_ts);
+
+ *pp_ret_last = p_field;
+ pp_ret_last = &p_field->p_next;
+
+ p_sys->i_pic_reorder -= (p_info->b_field) ? 1 : 2;
+
+ p_sys->p_pic_reorder = p_info->p_next;
+ free(p_info);
+ p_info = p_sys->p_pic_reorder;
+
+ if (p_info)
+ {
+ if (p_sys->b_poc_based_reorder)
+ b_dequeue = (p_info->i_poc == i_framepoc);
+ else
+ b_dequeue = (p_field->date == p_info->p_picture->date);
+ }
+ else b_dequeue = false;
+
+ } while(b_dequeue);
+
+ return p_ret;
+}
+
+static void FlushDPB(decoder_t *p_dec)
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ for( ;; )
+ {
+ picture_t *p_fields = RemoveOneFrameFromDPB(p_sys);
+ if (p_fields == NULL)
+ break;
+ do
+ {
+ picture_t *p_next = p_fields->p_next;
+ p_fields->p_next = NULL;
+ decoder_QueueVideo(p_dec, p_fields);
+ p_fields = p_next;
+ } while(p_fields != NULL);
+ }
+}
+
+static frame_info_t * CreateReorderInfo(decoder_sys_t *p_sys, const block_t *p_block)
+{
+ frame_info_t *p_info = calloc(1, sizeof(*p_info));
+ if (!p_info)
+ return NULL;
+
+ if (p_sys->b_poc_based_reorder)
+ {
+ if(p_sys->codec != kCMVideoCodecType_H264 ||
+ !ParseH264NAL(p_sys, p_block->p_buffer, p_block->i_buffer, 4, p_info))
+ {
+ assert(p_sys->codec == kCMVideoCodecType_H264);
+ free(p_info);
+ return NULL;
+ }
+ }
+ else
+ {
+ p_info->i_num_ts = 2;
+ p_info->b_progressive = true;
+ p_info->b_field = false;
+ }
+
+ p_info->i_length = p_block->i_length;
+
+ if (date_Get(&p_sys->pts) == VLC_TS_INVALID)
+ date_Set(&p_sys->pts, p_block->i_dts);
+
+ return p_info;
+}
+
+static void OnDecodedFrame(decoder_t *p_dec, frame_info_t *p_info)
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ assert(p_info->p_picture);
+ while(p_info->b_flush || p_sys->i_pic_reorder == (p_sys->i_pic_reorder_max * 2))
+ {
+ picture_t *p_fields = RemoveOneFrameFromDPB(p_sys);
+ if (p_fields == NULL)
+ break;
+ do
+ {
+ picture_t *p_next = p_fields->p_next;
+ p_fields->p_next = NULL;
+ decoder_QueueVideo(p_dec, p_fields);
+ p_fields = p_next;
+ } while(p_fields != NULL);
+ }
+
+ InsertIntoDPB(p_sys, p_info);
+}
+
static CMVideoCodecType CodecPrecheck(decoder_t *p_dec)
{
uint8_t i_profile = 0xFF, i_level = 0xFF;
@@ -310,6 +589,9 @@ static int StartVideoToolbox(decoder_t *p_dec)
const unsigned i_sar_num = p_dec->fmt_out.video.i_sar_num;
const unsigned i_sar_den = p_dec->fmt_out.video.i_sar_den;
+
+ date_Init( &p_sys->pts, p_dec->fmt_in.video.i_frame_rate * 2, p_dec->fmt_in.video.i_frame_rate_base );
+
VTDictionarySetInt32(pixelaspectratio,
kCVImageBufferPixelAspectRatioHorizontalSpacingKey,
i_sar_num);
@@ -418,8 +700,7 @@ static void StopVideoToolbox(decoder_t *p_dec, bool b_reset_format)
p_sys->b_format_propagated = false;
p_dec->fmt_out.i_codec = 0;
}
-
- PicReorder_flush(p_dec);
+ FlushDPB( p_dec );
}
if (p_sys->videoFormatDescription != nil) {
@@ -471,8 +752,6 @@ static int SetupDecoderExtradata(decoder_t *p_dec)
p_dec->fmt_in.i_extra);
if (i_ret != VLC_SUCCESS)
return i_ret;
-
- PicReorder_setup(p_dec);
}
/* else: AnnexB case, we'll get extradata from first input blocks */
}
@@ -535,10 +814,12 @@ static int OpenDecoder(vlc_object_t *p_this)
p_sys->extradataInfo = nil;
p_sys->p_pic_reorder = NULL;
p_sys->i_pic_reorder = 0;
- p_sys->i_pic_reorder_max = 1; /* 1 == no reordering */
+ p_sys->i_pic_reorder_max = 4;
+ p_sys->b_poc_based_reorder = false;
p_sys->b_format_propagated = false;
p_sys->b_abort = false;
p_sys->b_enable_temporal_processing = false;
+ h264_poc_context_init( &p_sys->pocctx );
vlc_mutex_init(&p_sys->lock);
/* return our proper VLC internal state */
@@ -563,6 +844,9 @@ static int OpenDecoder(vlc_object_t *p_this)
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;
@@ -715,7 +999,6 @@ static int avcCFromAnnexBCreate(decoder_t *p_dec)
i_ret = h264_helper_get_current_sar(&p_sys->hh, &i_sar_num, &i_sar_den);
if (i_ret != VLC_SUCCESS)
return i_ret;
- PicReorder_setup(p_dec);
p_dec->fmt_out.video.i_visible_width =
p_dec->fmt_out.video.i_width = i_video_width;
@@ -768,10 +1051,15 @@ static CMSampleBufferRef VTSampleBufferCreate(decoder_t *p_dec,
OSStatus status;
CMBlockBufferRef block_buf = NULL;
CMSampleBufferRef sample_buf = NULL;
+ CMTime pts;
+ if(!p_dec->p_sys->b_poc_based_reorder && p_block->i_pts == VLC_TS_INVALID)
+ pts = CMTimeMake(p_block->i_dts, CLOCK_FREQ);
+ else
+ pts = CMTimeMake(p_block->i_pts, CLOCK_FREQ);
CMSampleTimingInfo timeInfoArray[1] = { {
.duration = CMTimeMake(p_block->i_length, 1),
- .presentationTimeStamp = CMTimeMake(p_block->i_pts > 0 ? p_block->i_pts : p_block->i_dts, CLOCK_FREQ),
+ .presentationTimeStamp = pts,
.decodeTimeStamp = CMTimeMake(p_block->i_dts, CLOCK_FREQ),
} };
@@ -891,72 +1179,6 @@ static int HandleVTStatus(decoder_t *p_dec, OSStatus status)
#pragma mark - actual decoding
-static void PicReorder_pushSorted(decoder_t *p_dec, picture_t *p_pic)
-{
- decoder_sys_t *p_sys = p_dec->p_sys;
-
- assert(p_pic->p_next == NULL);
- p_sys->i_pic_reorder++;
- if (p_sys->p_pic_reorder == NULL)
- {
- p_sys->p_pic_reorder = p_pic;
- return;
- }
-
- picture_t **pp_last = &p_sys->p_pic_reorder;
- for (picture_t *p_cur = *pp_last; p_cur != NULL;
- pp_last = &p_cur->p_next, p_cur = *pp_last)
- {
- if (p_pic->date < p_cur->date)
- {
- p_pic->p_next = p_cur;
- *pp_last = p_pic;
- return;
- }
- }
- *pp_last = p_pic;
-}
-
-static picture_t *PicReorder_pop(decoder_t *p_dec, bool force)
-{
- decoder_sys_t *p_sys = p_dec->p_sys;
-
- if (p_sys->i_pic_reorder == 0
- || (!force && p_sys->i_pic_reorder < p_sys->i_pic_reorder_max))
- return NULL;
-
- picture_t *p_pic = p_sys->p_pic_reorder;
- p_sys->p_pic_reorder = p_pic->p_next;
- p_pic->p_next = NULL;
- p_sys->i_pic_reorder--;
- return p_pic;
-}
-
-static void PicReorder_flush(decoder_t *p_dec)
-{
- decoder_sys_t *p_sys = p_dec->p_sys;
-
- for (picture_t *p_cur = p_sys->p_pic_reorder, *p_next;
- p_cur != NULL; p_cur = p_next)
- {
- p_next = p_cur->p_next;
- picture_Release(p_cur);
- }
- p_sys->i_pic_reorder = 0;
- p_sys->p_pic_reorder = NULL;
-}
-
-static void PicReorder_setup(decoder_t *p_dec)
-{
- decoder_sys_t *p_sys = p_dec->p_sys;
- uint8_t i_depth;
- unsigned i_delay;
- if (h264_helper_get_current_dpb_values(&p_sys->hh, &i_depth, &i_delay)
- != VLC_SUCCESS)
- i_depth = 4;
- p_sys->i_pic_reorder_max = i_depth + 1;
-}
-
static void Flush(decoder_t *p_dec)
{
decoder_sys_t *p_sys = p_dec->p_sys;
@@ -974,29 +1196,23 @@ static void Drain(decoder_t *p_dec)
/* draining: return last pictures of the reordered queue */
if (p_sys->session)
VTDecompressionSessionWaitForAsynchronousFrames(p_sys->session);
- for (;;)
- {
- vlc_mutex_lock(&p_sys->lock);
- picture_t *p_pic = PicReorder_pop(p_dec, true);
- vlc_mutex_unlock(&p_sys->lock);
- if (p_pic)
- decoder_QueueVideo(p_dec, p_pic);
- else
- break;
- }
+ vlc_mutex_lock(&p_sys->lock);
+ FlushDPB( p_dec );
+ vlc_mutex_unlock(&p_sys->lock);
}
static int DecodeBlock(decoder_t *p_dec, block_t *p_block)
{
decoder_sys_t *p_sys = p_dec->p_sys;
+ frame_info_t *p_info = NULL;
if (p_sys->b_vt_flush) {
RestartVideoToolbox(p_dec, false);
p_sys->b_vt_flush = false;
}
- if (!p_block)
+ if (p_block == NULL)
{
Drain(p_dec);
return VLCDEC_SUCCESS;
@@ -1055,14 +1271,10 @@ static int DecodeBlock(decoder_t *p_dec, block_t *p_block)
goto skip;
}
- if (p_block->i_pts == VLC_TS_INVALID && p_block->i_dts != VLC_TS_INVALID &&
- p_sys->i_pic_reorder_max > 1)
- {
- /* VideoToolbox won't reorder output frames and there is no way to know
- * the right order. Abort and use an other decoder. */
- msg_Warn(p_dec, "unable to reorder output frames, abort");
- goto reload;
- }
+
+ p_info = CreateReorderInfo(p_sys, p_block);
+ if(unlikely(!p_info))
+ goto skip;
CMSampleBufferRef sampleBuffer =
VTSampleBufferCreate(p_dec, p_sys->videoFormatDescription, p_block);
@@ -1076,9 +1288,12 @@ static int DecodeBlock(decoder_t *p_dec, block_t *p_block)
OSStatus status =
VTDecompressionSessionDecodeFrame(p_sys->session, sampleBuffer,
- decoderFlags, NULL, &flagOut);
+ decoderFlags, p_info, &flagOut);
if (HandleVTStatus(p_dec, status) == VLC_SUCCESS)
+ {
p_sys->b_vt_feed = true;
+ p_info = NULL;
+ }
else
{
switch (status)
@@ -1096,10 +1311,13 @@ static int DecodeBlock(decoder_t *p_dec, block_t *p_block)
if (RestartVideoToolbox(p_dec, true) == VLC_SUCCESS)
{
status = VTDecompressionSessionDecodeFrame(p_sys->session,
- sampleBuffer, decoderFlags, NULL, &flagOut);
+ sampleBuffer, decoderFlags, p_info, &flagOut);
if (status != 0)
+ {
+ free( p_info );
StopVideoToolbox(p_dec, true);
+ }
}
break;
case -8960 /* codecErr */:
@@ -1108,10 +1326,12 @@ static int DecodeBlock(decoder_t *p_dec, block_t *p_block)
RestartVideoToolbox(p_dec, true);
break;
}
+ p_info = NULL;
}
CFRelease(sampleBuffer);
skip:
+ free(p_info);
block_Release(p_block);
return VLCDEC_SUCCESS;
@@ -1224,13 +1444,15 @@ static void DecoderCallback(void *decompressionOutputRefCon,
CMTime pts,
CMTime duration)
{
- VLC_UNUSED(sourceFrameRefCon);
VLC_UNUSED(duration);
decoder_t *p_dec = (decoder_t *)decompressionOutputRefCon;
decoder_sys_t *p_sys = p_dec->p_sys;
+ frame_info_t *p_info = (frame_info_t *) sourceFrameRefCon;
if (status != noErr) {
msg_Warn(p_dec, "decoding of a frame failed (%i, %u)", (int)status, (unsigned int) infoFlags);
+ if( status != kVTVideoDecoderBadDataErr && status != -8969 )
+ free(p_info);
return;
}
assert(imageBuffer);
@@ -1242,49 +1464,67 @@ static void DecoderCallback(void *decompressionOutputRefCon,
vlc_mutex_unlock(&p_sys->lock);
if (!p_sys->b_format_propagated)
+ {
+ free(p_info);
return;
+ }
assert(p_dec->fmt_out.i_codec != 0);
}
if (infoFlags & kVTDecodeInfo_FrameDropped)
{
+ printf("OUT %ld\n", pts.value);
msg_Dbg(p_dec, "decoder dropped frame");
+ free(p_info);
return;
}
if (!CMTIME_IS_VALID(pts))
+ {
+ free(p_info);
return;
+ }
if (CVPixelBufferGetDataSize(imageBuffer) == 0)
- return;
-
- picture_t *p_pic = decoder_NewPicture(p_dec);
- if (!p_pic)
- return;
- if (!p_pic->p_sys) {
- vlc_mutex_lock(&p_sys->lock);
- p_dec->p_sys->b_abort = true;
- vlc_mutex_unlock(&p_sys->lock);
- picture_Release(p_pic);
+ {
+ free(p_info);
return;
}
- /* Can happen if the pic was discarded */
- if (p_pic->p_sys->pixelBuffer != nil)
- CFRelease(p_pic->p_sys->pixelBuffer);
+ if(likely(p_info))
+ {
+ picture_t *p_pic = decoder_NewPicture(p_dec);
+ if (!p_pic)
+ {
+ free(p_info);
+ return;
+ }
+
+ if (unlikely(!p_pic->p_sys)) {
+ vlc_mutex_lock(&p_sys->lock);
+ p_dec->p_sys->b_abort = true;
+ vlc_mutex_unlock(&p_sys->lock);
+ picture_Release(p_pic);
+ free(p_info);
+ return;
+ }
- /* will be freed by the vout */
- p_pic->p_sys->pixelBuffer = CVPixelBufferRetain(imageBuffer);
+ /* Can happen if the pic was discarded */
+ if (p_pic->p_sys->pixelBuffer != nil)
+ CFRelease(p_pic->p_sys->pixelBuffer);
- p_pic->date = pts.value;
- p_pic->b_progressive = true;
+ /* will be freed by the vout */
+ p_pic->p_sys->pixelBuffer = CVPixelBufferRetain(imageBuffer);
- vlc_mutex_lock(&p_sys->lock);
- PicReorder_pushSorted(p_dec, p_pic);
- p_pic = PicReorder_pop(p_dec, false);
- vlc_mutex_unlock(&p_sys->lock);
+ p_info->p_picture = p_pic;
+
+ p_pic->date = pts.value;
+ p_pic->b_progressive = p_info->b_progressive;
+
+ vlc_mutex_lock(&p_sys->lock);
+ OnDecodedFrame( p_dec, p_info );
+ vlc_mutex_unlock(&p_sys->lock);
+ }
- if (p_pic != NULL)
- decoder_QueueVideo(p_dec, p_pic);
return;
}
More information about the vlc-commits
mailing list