diff --git a/modules/codec/hxxx_helper.c b/modules/codec/hxxx_helper.c index aa2d57e32617837cea76e31d75da8562c3a36dfb..4287fa708d03e0b3968693b8ec9bdd571ada5544 100644 --- a/modules/codec/hxxx_helper.c +++ b/modules/codec/hxxx_helper.c @@ -879,6 +879,28 @@ hxxx_helper_get_current_profile_level(const struct hxxx_helper *hh, return VLC_EGENERIC; } +int +hxxx_helper_get_current_frame_rate(const struct hxxx_helper *hh, + unsigned *num, unsigned *den) +{ + if (hh->i_codec == VLC_CODEC_H264) + { + const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh); + if (hsps && hsps->h264_sps && + h264_get_frame_rate(hsps->h264_sps, num, den)) + return VLC_SUCCESS; + } + else if (hh->i_codec == VLC_CODEC_HEVC) + { + const struct hxxx_helper_nal *hsps = &hh->hevc.sps_list[hh->hevc.i_current_sps]; + const struct hxxx_helper_nal *hvps = &hh->hevc.vps_list[hh->hevc.i_current_vps]; + if (hsps && hsps->hevc_sps && hvps && hvps->hevc_vps && + hevc_get_frame_rate(hsps->hevc_sps, hvps->hevc_vps, num, den)) + return VLC_SUCCESS; + } + return VLC_EGENERIC; +} + int hxxx_helper_get_chroma_chroma(const struct hxxx_helper *hh, uint8_t *pi_chroma_format, uint8_t *pi_depth_luma, uint8_t *pi_depth_chroma) diff --git a/modules/codec/hxxx_helper.h b/modules/codec/hxxx_helper.h index 730f40419084fc9cd496acbc34cdfc3cba8ca40b..a7e1944c054a0c22e7e5b817beefe05addd1d4c8 100644 --- a/modules/codec/hxxx_helper.h +++ b/modules/codec/hxxx_helper.h @@ -121,6 +121,9 @@ int hxxx_helper_get_current_sar(const struct hxxx_helper *hh, int *p_num, int *p int hxxx_helper_get_current_profile_level(const struct hxxx_helper *hh, uint8_t *p_profile, uint8_t *p_level); +int hxxx_helper_get_current_frame_rate(const struct hxxx_helper *hh, + unsigned *num, unsigned *den); + int hxxx_helper_get_chroma_chroma(const struct hxxx_helper *hh, uint8_t *pi_chroma_format, uint8_t *pi_depth_luma, uint8_t *pi_depth_chroma); diff --git a/modules/codec/omxil/mediacodec.c b/modules/codec/omxil/mediacodec.c index ba44431809890b6758bbf53ad214c6b08901cfb7..eff23807d3d01db6220cbd39136646110287dd7c 100644 --- a/modules/codec/omxil/mediacodec.c +++ b/modules/codec/omxil/mediacodec.c @@ -36,7 +36,6 @@ #include <vlc_plugin.h> #include <vlc_codec.h> #include <vlc_block_helper.h> -#include <vlc_timestamp_helper.h> #include <vlc_threads.h> #include <vlc_bits.h> @@ -137,9 +136,10 @@ typedef struct decoder_sys_t unsigned int i_stride, i_slice_height; int i_pixel_format; struct hxxx_helper hh; - timestamp_fifo_t *timestamp_fifo; int i_mpeg_dar_num, i_mpeg_dar_den; struct vlc_asurfacetexture *surfacetexture; + date_t pts; + bool pts_warned; } video; struct { date_t i_end_date; @@ -266,10 +266,24 @@ static int CSDDup(decoder_sys_t *p_sys, const void *p_buf, size_t i_buf) static void HXXXInitSize(decoder_t *p_dec, bool *p_size_changed) { + decoder_sys_t *p_sys = p_dec->p_sys; + struct hxxx_helper *hh = &p_sys->video.hh; + + unsigned frame_rate, frame_rate_base; + int ret = hxxx_helper_get_current_frame_rate(hh, &frame_rate, &frame_rate_base); + if (ret == VLC_SUCCESS) + { + frame_rate_base *= 2; + p_dec->fmt_out.video.i_frame_rate = frame_rate; + p_dec->fmt_out.video.i_frame_rate_base = frame_rate_base; + + date_Change(&p_sys->video.pts, frame_rate, frame_rate_base); + } + else + msg_Warn(p_dec, "could not parse video frame_rate"); + if (p_size_changed) { - decoder_sys_t *p_sys = p_dec->p_sys; - struct hxxx_helper *hh = &p_sys->video.hh; unsigned i_ox, i_oy, i_w, i_h, i_vw, i_vh; if(hxxx_helper_get_current_picture_size(hh, &i_ox, &i_oy, &i_w, &i_h, &i_vw, &i_vh) == VLC_SUCCESS) @@ -960,10 +974,6 @@ static int OpenDecoder(vlc_object_t *p_this, pf_MediaCodecApi_init pf_init) p_sys->pf_on_flush = Video_OnFlush; p_sys->pf_process_output = Video_ProcessOutput; - p_sys->video.timestamp_fifo = timestamp_FifoNew(32); - if (!p_sys->video.timestamp_fifo) - goto bailout; - if (var_InheritBool(p_dec, CFG_PREFIX "dr")) { /* Direct rendering: Request a valid OPAQUE Vout in order to get @@ -1019,6 +1029,8 @@ static int OpenDecoder(vlc_object_t *p_this, pf_MediaCodecApi_init pf_init) p_dec->fmt_out.video.i_height = p_dec->fmt_in->video.i_height; } p_sys->cat = VIDEO_ES; + date_Init(&p_sys->video.pts, 1, 0); + p_sys->video.pts_warned = false; } else { @@ -1111,9 +1123,6 @@ static void CleanDecoder(decoder_sys_t *p_sys) if (p_sys->video.surfacetexture) vlc_asurfacetexture_Delete(p_sys->video.surfacetexture); - if (p_sys->video.timestamp_fifo) - timestamp_FifoRelease(p_sys->video.timestamp_fifo); - free(p_sys); } @@ -1164,13 +1173,6 @@ static int Video_ProcessOutput(decoder_t *p_dec, mc_api_out *p_out, { picture_t *p_pic = NULL; - /* If the oldest input block had no PTS, the timestamp of - * the frame returned by MediaCodec might be wrong so we - * overwrite it with the corresponding dts. Call FifoGet - * first in order to avoid a gap if buffers are released - * due to an invalid format or a preroll */ - int64_t forced_ts = timestamp_FifoGet(p_sys->video.timestamp_fifo); - if (!p_sys->b_has_format) { msg_Warn(p_dec, "Buffers returned before output format is set, dropping frame"); return p_sys->api.release_out(&p_sys->api, p_out->buf.i_index, false); @@ -1192,10 +1194,7 @@ static int Video_ProcessOutput(decoder_t *p_dec, mc_api_out *p_out, return p_sys->api.release_out(&p_sys->api, p_out->buf.i_index, false); } - if (forced_ts == VLC_TICK_INVALID) - p_pic->date = p_out->buf.i_ts; - else - p_pic->date = forced_ts; + p_pic->date = p_out->buf.i_ts; p_pic->b_progressive = true; if (p_sys->api.b_direct_rendering) @@ -1615,11 +1614,7 @@ static int QueueBlockLocked(decoder_t *p_dec, block_t *p_in_block, { b_config = (p_block->i_flags & BLOCK_FLAG_CSD); if (!b_config) - { i_ts = p_block->i_pts; - if (!i_ts && p_block->i_dts) - i_ts = p_block->i_dts; - } p_buf = p_block->p_buffer; i_size = p_block->i_buffer; } @@ -1796,9 +1791,37 @@ static int Video_OnNewBlock(decoder_t *p_dec, block_t **pp_block) decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block = *pp_block; - timestamp_FifoPut(p_sys->video.timestamp_fifo, - p_block->i_pts ? VLC_TICK_INVALID : p_block->i_dts); + if (p_block->i_pts != VLC_TICK_INVALID) + return 1; + + /* PTS fallback: calculate it from first_dts + frame_rate */ + if (p_sys->video.pts.i_divider_den == 0) + { + p_block->i_pts = p_block->i_dts; + goto nopts; + } + + p_block->i_pts = date_Get(&p_sys->video.pts); + + if (p_block->i_pts == VLC_TICK_INVALID) + { + date_Set(&p_sys->video.pts, p_block->i_dts); + p_block->i_pts = p_block->i_dts; + } + + if (p_block->i_pts == VLC_TICK_INVALID) + goto nopts; + date_Increment(&p_sys->video.pts, 1); + + return 1; + +nopts: + if (!p_sys->video.pts_warned) + { + msg_Warn(p_dec, "no valid PTS, video timing might be bogus"); + p_sys->video.pts_warned = true; + } return 1; } @@ -1898,7 +1921,7 @@ static int VideoVC1_OnNewBlock(decoder_t *p_dec, block_t **pp_block) static void Video_OnFlush(decoder_sys_t *p_sys) { - timestamp_FifoEmpty(p_sys->video.timestamp_fifo); + date_Set(&p_sys->video.pts, VLC_TICK_INVALID); /* Invalidate all pictures that are currently in flight * since flushing make all previous indices returned by * MediaCodec invalid. */