#include "libavutil/mem.h"
#include "libavutil/pixfmt.h"
+#include "avcodec.h"
#include "get_bits.h"
#include "golomb.h"
#include "h264.h"
#include "h264_sei.h"
+#include "h264_ps.h"
#include "h264data.h"
#include "internal.h"
#include "mpegutils.h"
uint8_t parse_history[6];
int parse_history_count;
int parse_last_mb;
+ int64_t reference_dts;
+ int last_frame_num, last_picture_structure;
} H264ParseContext;
state >>= 1; // 2->1, 1->0, 0->0
} else if (state <= 5) {
int nalu_type = buf[i] & 0x1F;
- if (nalu_type == NAL_SEI || nalu_type == NAL_SPS ||
- nalu_type == NAL_PPS || nalu_type == NAL_AUD) {
+ if (nalu_type == H264_NAL_SEI || nalu_type == H264_NAL_SPS ||
+ nalu_type == H264_NAL_PPS || nalu_type == H264_NAL_AUD) {
if (pc->frame_start_found) {
i++;
goto found;
}
- } else if (nalu_type == NAL_SLICE || nalu_type == NAL_DPA ||
- nalu_type == NAL_IDR_SLICE) {
+ } else if (nalu_type == H264_NAL_SLICE || nalu_type == H264_NAL_DPA ||
+ nalu_type == H264_NAL_IDR_SLICE) {
state += 8;
continue;
}
return 0;
}
-static inline int get_avc_nalsize(H264ParseContext *p, const uint8_t *buf,
- int buf_size, int *buf_index, void *logctx)
-{
- int i, nalsize = 0;
-
- if (*buf_index >= buf_size - p->nal_length_size) {
- // the end of the buffer is reached, refill it
- return AVERROR(EAGAIN);
- }
-
- for (i = 0; i < p->nal_length_size; i++)
- nalsize = ((unsigned)nalsize << 8) | buf[(*buf_index)++];
- if (nalsize <= 0 || nalsize > buf_size - *buf_index) {
- av_log(logctx, AV_LOG_ERROR,
- "AVC: nal size %d\n", nalsize);
- return AVERROR_INVALIDDATA;
- }
- return nalsize;
-}
-
/**
* Parse NAL units of found picture and decode some basic information.
*
int src_length, consumed, nalsize = 0;
if (buf_index >= next_avc) {
- nalsize = get_avc_nalsize(p, buf, buf_size, &buf_index, avctx);
+ nalsize = get_nalsize(p->nal_length_size, buf, buf_size, &buf_index, avctx);
if (nalsize < 0)
break;
next_avc = buf_index + nalsize;
state = buf[buf_index];
switch (state & 0x1f) {
- case NAL_SLICE:
- case NAL_IDR_SLICE:
+ case H264_NAL_SLICE:
+ case H264_NAL_IDR_SLICE:
// Do not walk the whole buffer just to decode slice header
- if ((state & 0x1f) == NAL_IDR_SLICE || ((state >> 5) & 0x3) == 0) {
+ if ((state & 0x1f) == H264_NAL_IDR_SLICE || ((state >> 5) & 0x3) == 0) {
/* IDR or disposable slice
* No need to decode many bytes because MMCOs shall not be present. */
if (src_length > 60)
}
break;
}
- consumed = ff_h2645_extract_rbsp(buf + buf_index, src_length, &nal);
+ consumed = ff_h2645_extract_rbsp(buf + buf_index, src_length, &nal, 1);
if (consumed < 0)
break;
nal.type = get_bits(&nal.gb, 5);
switch (nal.type) {
- case NAL_SPS:
+ case H264_NAL_SPS:
ff_h264_decode_seq_parameter_set(&nal.gb, avctx, &p->ps, 0);
break;
- case NAL_PPS:
+ case H264_NAL_PPS:
ff_h264_decode_picture_parameter_set(&nal.gb, avctx, &p->ps,
nal.size_bits);
break;
- case NAL_SEI:
+ case H264_NAL_SEI:
ff_h264_sei_decode(&p->sei, &nal.gb, &p->ps, avctx);
break;
- case NAL_IDR_SLICE:
+ case H264_NAL_IDR_SLICE:
s->key_frame = 1;
p->poc.prev_frame_num = 0;
p->poc.prev_poc_msb =
p->poc.prev_poc_lsb = 0;
/* fall through */
- case NAL_SLICE:
+ case H264_NAL_SLICE:
get_ue_golomb_long(&nal.gb); // skip first_mb_in_slice
slice_type = get_ue_golomb_31(&nal.gb);
s->pict_type = ff_h264_golomb_to_pict_type[slice_type % 5];
}
}
- if (nal.type == NAL_IDR_SLICE)
+ if (nal.type == H264_NAL_IDR_SLICE)
get_ue_golomb_long(&nal.gb); /* idr_pic_id */
if (sps->poc_type == 0) {
p->poc.poc_lsb = get_bits(&nal.gb, sps->log2_max_poc_lsb);
* FIXME: MMCO_RESET could appear in non-first slice.
* Maybe, we should parse all undisposable non-IDR slice of this
* picture until encountering MMCO_RESET in a slice of it. */
- if (nal.ref_idc && nal.type != NAL_IDR_SLICE) {
+ if (nal.ref_idc && nal.type != H264_NAL_IDR_SLICE) {
got_reset = scan_mmco_reset(s, &nal.gb, avctx);
if (got_reset < 0)
goto fail;
s->picture_structure = AV_PICTURE_STRUCTURE_TOP_FIELD;
else
s->picture_structure = AV_PICTURE_STRUCTURE_BOTTOM_FIELD;
- s->field_order = AV_FIELD_UNKNOWN;
+ if (p->poc.frame_num == p->last_frame_num &&
+ p->last_picture_structure != AV_PICTURE_STRUCTURE_UNKNOWN &&
+ p->last_picture_structure != AV_PICTURE_STRUCTURE_FRAME &&
+ p->last_picture_structure != s->picture_structure) {
+ if (p->last_picture_structure == AV_PICTURE_STRUCTURE_TOP_FIELD)
+ s->field_order = AV_FIELD_TT;
+ else
+ s->field_order = AV_FIELD_BB;
+ } else {
+ s->field_order = AV_FIELD_UNKNOWN;
+ }
+ p->last_picture_structure = s->picture_structure;
+ p->last_frame_num = p->poc.frame_num;
}
av_freep(&nal.rbsp_buffer);
s->flags &= PARSER_FLAG_COMPLETE_FRAMES;
}
+ if (s->dts_sync_point >= 0) {
+ int64_t den = avctx->time_base.den * (int64_t)avctx->pkt_timebase.num;
+ if (den > 0) {
+ int64_t num = avctx->time_base.num * (int64_t)avctx->pkt_timebase.den;
+ if (s->dts != AV_NOPTS_VALUE) {
+ // got DTS from the stream, update reference timestamp
+ p->reference_dts = s->dts - av_rescale(s->dts_ref_dts_delta, num, den);
+ } else if (p->reference_dts != AV_NOPTS_VALUE) {
+ // compute DTS based on reference timestamp
+ s->dts = p->reference_dts + av_rescale(s->dts_ref_dts_delta, num, den);
+ }
+
+ if (p->reference_dts != AV_NOPTS_VALUE && s->pts == AV_NOPTS_VALUE)
+ s->pts = s->dts + av_rescale(s->pts_dts_delta, num, den);
+
+ if (s->dts_sync_point > 0)
+ p->reference_dts = s->dts; // new reference
+ }
+ }
+
*poutbuf = buf;
*poutbuf_size = buf_size;
return next;
if ((state & 0xFFFFFF00) != 0x100)
break;
nalu_type = state & 0x1F;
- if (nalu_type == NAL_SPS) {
+ if (nalu_type == H264_NAL_SPS) {
has_sps = 1;
- } else if (nalu_type == NAL_PPS)
+ } else if (nalu_type == H264_NAL_PPS)
has_pps = 1;
/* else if (nalu_type == 0x01 ||
* nalu_type == 0x02 ||
* nalu_type == 0x05) {
* }
*/
- else if ((nalu_type != NAL_SEI || has_pps) &&
- nalu_type != NAL_AUD && nalu_type != NAL_SPS_EXT &&
+ else if ((nalu_type != H264_NAL_SEI || has_pps) &&
+ nalu_type != H264_NAL_AUD && nalu_type != H264_NAL_SPS_EXT &&
nalu_type != 0x0f) {
if (has_sps) {
while (ptr - 4 > buf && ptr[-5] == 0)
{
H264ParseContext *p = s->priv_data;
+ p->reference_dts = AV_NOPTS_VALUE;
+ p->last_frame_num = INT_MAX;
ff_h264dsp_init(&p->h264dsp, 8, 1);
return 0;
}