Extract h264 frame duration from bitstream instead of measuring intra packet time
This commit is contained in:
parent
478fa53b1c
commit
5b56688ebe
5 changed files with 65 additions and 57 deletions
|
@ -90,10 +90,15 @@ static const int h264_lev2cpbsize[][2] = {
|
|||
typedef struct h264_private {
|
||||
|
||||
struct {
|
||||
int frame_duration;
|
||||
int cbpsize;
|
||||
int16_t width;
|
||||
int16_t height;
|
||||
int16_t max_frame_num_bits;
|
||||
char mbs_only_flag;
|
||||
char aff;
|
||||
char fixed_rate;
|
||||
int units_in_tick;
|
||||
int time_scale;
|
||||
} sps[256];
|
||||
|
||||
struct {
|
||||
|
@ -106,13 +111,8 @@ typedef struct h264_private {
|
|||
|
||||
|
||||
static int
|
||||
decode_vui(th_stream_t *st, bitstream_t *bs, int spsid)
|
||||
decode_vui(h264_private_t *p, bitstream_t *bs, int sps_id)
|
||||
{
|
||||
int units_in_tick;
|
||||
int time_scale;
|
||||
int fixed_rate;
|
||||
return 0;
|
||||
|
||||
if(read_bits1(bs)) {
|
||||
if(read_bits(bs, 8) == 255) {
|
||||
read_bits(bs, 16);
|
||||
|
@ -140,16 +140,12 @@ decode_vui(th_stream_t *st, bitstream_t *bs, int spsid)
|
|||
}
|
||||
|
||||
if(!read_bits1(bs)) /* We need timing info */
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
units_in_tick = read_bits(bs, 32);
|
||||
time_scale = read_bits(bs, 32);
|
||||
fixed_rate = read_bits1(bs);
|
||||
#if 0
|
||||
printf("units_in_tick = %d\n", units_in_tick);
|
||||
printf("time_scale = %d\n", time_scale);
|
||||
printf("fixed_rate = %d\n", fixed_rate);
|
||||
#endif
|
||||
|
||||
p->sps[sps_id].units_in_tick = read_bits(bs, 32);
|
||||
p->sps[sps_id].time_scale = read_bits(bs, 32);
|
||||
p->sps[sps_id].fixed_rate = read_bits1(bs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -229,7 +225,7 @@ h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs)
|
|||
}
|
||||
}
|
||||
|
||||
tmp = read_golomb_ue(bs); /* max frame num */
|
||||
p->sps[sps_id].max_frame_num_bits = read_golomb_ue(bs) + 4;
|
||||
poc_type= read_golomb_ue(bs);
|
||||
|
||||
if(poc_type == 0){ //FIXME #define
|
||||
|
@ -257,8 +253,9 @@ h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs)
|
|||
p->sps[sps_id].width = width * 16;
|
||||
p->sps[sps_id].height = height * 16;
|
||||
|
||||
if(!read_bits1(bs))
|
||||
read_bits1(bs);
|
||||
p->sps[sps_id].mbs_only_flag = read_bits1(bs);
|
||||
if(!p->sps[sps_id].mbs_only_flag)
|
||||
p->sps[sps_id].aff = read_bits1(bs);
|
||||
|
||||
read_bits1(bs);
|
||||
|
||||
|
@ -271,7 +268,7 @@ h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs)
|
|||
}
|
||||
|
||||
if(read_bits1(bs)) {
|
||||
decode_vui(st, bs, sps_id);
|
||||
decode_vui(p, bs, sps_id);
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
|
@ -296,10 +293,11 @@ h264_decode_pic_parameter_set(th_stream_t *st, bitstream_t *bs)
|
|||
|
||||
|
||||
int
|
||||
h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype)
|
||||
h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype,
|
||||
int *duration)
|
||||
{
|
||||
h264_private_t *p;
|
||||
int slice_type, pps_id, sps_id;
|
||||
int slice_type, pps_id, sps_id, fnum;
|
||||
|
||||
if((p = st->st_priv) == NULL)
|
||||
return -1;
|
||||
|
@ -326,11 +324,39 @@ h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype)
|
|||
|
||||
pps_id = read_golomb_ue(bs);
|
||||
sps_id = p->pps[pps_id].sps;
|
||||
if(p->sps[sps_id].cbpsize == 0)
|
||||
if(p->sps[sps_id].max_frame_num_bits == 0)
|
||||
return -1;
|
||||
|
||||
st->st_vbv_size = p->sps[sps_id].cbpsize;
|
||||
fnum = read_bits(bs, p->sps[sps_id].max_frame_num_bits);
|
||||
|
||||
int structure;
|
||||
|
||||
int timebase = 180000;
|
||||
|
||||
if(p->sps[sps_id].mbs_only_flag) {
|
||||
structure = 0;
|
||||
} else {
|
||||
if(read_bits1(bs)) {
|
||||
read_bits1(bs); // bottom field
|
||||
structure = 1;
|
||||
} else {
|
||||
structure = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if(p->sps[sps_id].time_scale != 0) {
|
||||
int d = timebase * p->sps[sps_id].units_in_tick / p->sps[sps_id].time_scale;
|
||||
*duration = d;
|
||||
} else {
|
||||
*duration = 0;
|
||||
}
|
||||
|
||||
if(p->sps[sps_id].cbpsize != 0)
|
||||
st->st_vbv_size = p->sps[sps_id].cbpsize;
|
||||
|
||||
st->st_vbv_delay = -1;
|
||||
parser_set_stream_meta(st, p->sps[sps_id].width, p->sps[sps_id].height, 0);
|
||||
|
||||
if(p->sps[sps_id].width && p->sps[sps_id].height)
|
||||
parser_set_stream_vsize(st, p->sps[sps_id].width, p->sps[sps_id].height);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ int h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs);
|
|||
|
||||
int h264_decode_pic_parameter_set(th_stream_t *st, bitstream_t *bs);
|
||||
|
||||
int h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype);
|
||||
int h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype,
|
||||
int *duration);
|
||||
|
||||
#endif /* PARSER_H264_H_ */
|
||||
|
|
|
@ -630,17 +630,15 @@ parse_mpeg2video_pic_start(th_transport_t *t, th_stream_t *st, int *frametype,
|
|||
*
|
||||
*/
|
||||
void
|
||||
parser_set_stream_meta(th_stream_t *st, int width, int height, int d)
|
||||
parser_set_stream_vsize(th_stream_t *st, int width, int height)
|
||||
{
|
||||
int need_save = 0;
|
||||
|
||||
if(st->st_frame_duration == 0 && st->st_width == 0 && st->st_height == 0) {
|
||||
if(st->st_width == 0 && st->st_height == 0) {
|
||||
need_save = 1;
|
||||
st->st_meta_change = 0;
|
||||
|
||||
} else if((d && st->st_frame_duration != d) ||
|
||||
st->st_width != width ||
|
||||
st->st_height != height) {
|
||||
} else if(st->st_width != width || st->st_height != height) {
|
||||
|
||||
st->st_meta_change++;
|
||||
if(st->st_meta_change == 2)
|
||||
|
@ -651,8 +649,6 @@ parser_set_stream_meta(th_stream_t *st, int width, int height, int d)
|
|||
}
|
||||
|
||||
if(need_save) {
|
||||
if(d)
|
||||
st->st_frame_duration = d;
|
||||
st->st_width = width;
|
||||
st->st_height = height;
|
||||
transport_request_save(st->st_transport, 1);
|
||||
|
@ -667,7 +663,7 @@ static int
|
|||
parse_mpeg2video_seq_start(th_transport_t *t, th_stream_t *st,
|
||||
bitstream_t *bs)
|
||||
{
|
||||
int v, width, height, d;
|
||||
int v, width, height;
|
||||
|
||||
if(bs->len < 61)
|
||||
return 1;
|
||||
|
@ -675,7 +671,7 @@ parse_mpeg2video_seq_start(th_transport_t *t, th_stream_t *st,
|
|||
width = read_bits(bs, 12);
|
||||
height = read_bits(bs, 12);
|
||||
skip_bits(bs, 4);
|
||||
d = mpeg2video_framedurations[read_bits(bs, 4)];
|
||||
st->st_frame_duration = mpeg2video_framedurations[read_bits(bs, 4)];
|
||||
|
||||
v = read_bits(bs, 18) * 400;
|
||||
skip_bits(bs, 1);
|
||||
|
@ -683,7 +679,7 @@ parse_mpeg2video_seq_start(th_transport_t *t, th_stream_t *st,
|
|||
v = read_bits(bs, 10) * 16 * 1024 / 8;
|
||||
st->st_vbv_size = v;
|
||||
|
||||
parser_set_stream_meta(st, width, height, d);
|
||||
parser_set_stream_vsize(st, width, height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -835,7 +831,7 @@ parse_h264(th_transport_t *t, th_stream_t *st, size_t len,
|
|||
uint8_t *buf = st->st_buffer + sc_offset;
|
||||
uint32_t sc = st->st_startcode;
|
||||
int64_t d;
|
||||
int l2, pkttype;
|
||||
int l2, pkttype, duration;
|
||||
bitstream_t bs;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -892,14 +888,16 @@ parse_h264(th_transport_t *t, th_stream_t *st, size_t len,
|
|||
|
||||
l2 = len - 3 > 64 ? 64 : len - 3;
|
||||
h264_nal_deescape(&bs, buf + 3, l2); /* we just want the first stuff */
|
||||
if(h264_decode_slice_header(st, &bs, &pkttype)) {
|
||||
duration = 0;
|
||||
|
||||
if(h264_decode_slice_header(st, &bs, &pkttype, &duration)) {
|
||||
free(bs.data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
st->st_curpkt = pkt_alloc(NULL, 0, st->st_curpts, st->st_curdts);
|
||||
st->st_curpkt->pkt_frametype = pkttype;
|
||||
st->st_curpkt->pkt_duration = st->st_frame_duration;
|
||||
st->st_curpkt->pkt_duration = duration ?: st->st_frame_duration;
|
||||
st->st_curpkt->pkt_commercial = t->tht_tt_commercial_advice;
|
||||
break;
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ void parse_mpeg_ps(th_transport_t *t, th_stream_t *st, uint8_t *data, int len);
|
|||
|
||||
void parser_enqueue_packet(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt);
|
||||
|
||||
void parser_set_stream_meta(th_stream_t *st, int width, int height, int d);
|
||||
void parser_set_stream_vsize(th_stream_t *st, int width, int height);
|
||||
|
||||
extern const unsigned int mpeg2video_framedurations[16];
|
||||
|
||||
|
|
17
src/psi.c
17
src/psi.c
|
@ -422,7 +422,6 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
streaming_component_type_t hts_stream_type;
|
||||
th_stream_t *st, *next;
|
||||
char lang[4];
|
||||
int frameduration;
|
||||
int update = 0;
|
||||
int had_components;
|
||||
int composition_id;
|
||||
|
@ -502,7 +501,6 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
ptr += 5;
|
||||
len -= 5;
|
||||
|
||||
frameduration = 0;
|
||||
hts_stream_type = SCT_UNKNOWN;
|
||||
memset(lang, 0, 4);
|
||||
composition_id = -1;
|
||||
|
@ -551,10 +549,6 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
hts_stream_type = SCT_AC3;
|
||||
break;
|
||||
|
||||
case DVB_DESC_VIDEO_STREAM:
|
||||
frameduration = mpeg2video_framedurations[(ptr[0] >> 3) & 0xf];
|
||||
break;
|
||||
|
||||
case DVB_DESC_LANGUAGE:
|
||||
memcpy(lang, ptr, 3);
|
||||
break;
|
||||
|
@ -618,11 +612,6 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
memcpy(st->st_lang, lang, 4);
|
||||
}
|
||||
|
||||
if(st->st_frame_duration == 0 && frameduration != 0) {
|
||||
st->st_frame_duration = frameduration;
|
||||
update |= PMT_UPDATE_FRAME_DURATION;
|
||||
}
|
||||
|
||||
if(composition_id != -1 && st->st_composition_id != composition_id) {
|
||||
st->st_composition_id = composition_id;
|
||||
update |= PMT_UPDATE_COMPOSITION_ID;
|
||||
|
@ -980,9 +969,6 @@ psi_save_transport_settings(htsmsg_t *m, th_transport_t *t)
|
|||
if(st->st_type == SCT_TEXTSUB)
|
||||
htsmsg_add_u32(sub, "parentpid", st->st_parent_pid);
|
||||
|
||||
if(st->st_frame_duration)
|
||||
htsmsg_add_u32(sub, "frameduration", st->st_frame_duration);
|
||||
|
||||
if(st->st_type == SCT_MPEG2VIDEO || st->st_type == SCT_H264) {
|
||||
if(st->st_width && st->st_height) {
|
||||
htsmsg_add_u32(sub, "width", st->st_width);
|
||||
|
@ -1106,9 +1092,6 @@ psi_load_transport_settings(htsmsg_t *m, th_transport_t *t)
|
|||
if((v = htsmsg_get_str(c, "language")) != NULL)
|
||||
av_strlcpy(st->st_lang, v, 4);
|
||||
|
||||
if(!htsmsg_get_u32(c, "frameduration", &u32))
|
||||
st->st_frame_duration = u32;
|
||||
|
||||
if(!htsmsg_get_u32(c, "position", &u32))
|
||||
st->st_position = u32;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue