Add ability to parse whole frames (without the reassembly stuff)
This commit is contained in:
parent
4226af5abb
commit
e873fc7677
2 changed files with 125 additions and 32 deletions
155
parsers.c
155
parsers.c
|
@ -465,6 +465,62 @@ const static unsigned int mpeg2video_framedurations[16] = {
|
|||
1500,
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse mpeg2video picture start
|
||||
*/
|
||||
static int
|
||||
parse_mpeg2video_pic_start(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt,
|
||||
bitstream_t *bs)
|
||||
{
|
||||
int v, pct;
|
||||
|
||||
if(bs->len < 6 * 8)
|
||||
return 1;
|
||||
|
||||
skip_bits(bs, 10); /* temporal reference */
|
||||
|
||||
pct = read_bits(bs, 3);
|
||||
if(pct < PKT_I_FRAME || pct > PKT_B_FRAME)
|
||||
return 1; /* Illegal picture_coding_type */
|
||||
|
||||
/* If this is the first I-frame seen, set dts_start as a reference
|
||||
offset */
|
||||
if(pct == PKT_I_FRAME && t->tht_dts_start == AV_NOPTS_VALUE)
|
||||
t->tht_dts_start = st->st_curdts;
|
||||
|
||||
v = read_bits(bs, 16); /* vbv_delay */
|
||||
if(v == 0xffff)
|
||||
st->st_vbv_delay = -1;
|
||||
else
|
||||
st->st_vbv_delay = av_rescale_q(v, st->st_tb, AV_TIME_BASE_Q);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse mpeg2video sequence start
|
||||
*/
|
||||
static int
|
||||
parse_mpeg2video_seq_start(th_transport_t *t, th_stream_t *st,
|
||||
bitstream_t *bs)
|
||||
{
|
||||
int v;
|
||||
|
||||
if(bs->len < 11 * 8)
|
||||
return 1;
|
||||
|
||||
skip_bits(bs, 12);
|
||||
skip_bits(bs, 12);
|
||||
skip_bits(bs, 4);
|
||||
st->st_frame_duration = mpeg2video_framedurations[read_bits(bs, 4)];
|
||||
v = read_bits(bs, 18) * 400;
|
||||
skip_bits(bs, 1);
|
||||
|
||||
v = read_bits(bs, 10) * 16 * 1024 / 8;
|
||||
st->st_vbv_size = v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* MPEG2VIDEO specific reassembly
|
||||
*
|
||||
|
@ -481,7 +537,7 @@ parse_mpeg2video(th_transport_t *t, th_stream_t *st, size_t len,
|
|||
{
|
||||
uint8_t *buf = st->st_buffer + sc_offset;
|
||||
bitstream_t bs;
|
||||
int v, pct;
|
||||
th_pkt_t pkt0; /* Fake temporary packet */
|
||||
|
||||
init_bits(&bs, buf + 4, (len - 4) * 8);
|
||||
|
||||
|
@ -497,31 +553,14 @@ parse_mpeg2video(th_transport_t *t, th_stream_t *st, size_t len,
|
|||
if(st->st_frame_duration == 0 || st->st_curdts == AV_NOPTS_VALUE)
|
||||
return 1;
|
||||
|
||||
if(len < 6)
|
||||
if(parse_mpeg2video_pic_start(t, st, &pkt0, &bs))
|
||||
return 1;
|
||||
|
||||
skip_bits(&bs, 10); /* temporal reference */
|
||||
|
||||
pct = read_bits(&bs, 3);
|
||||
if(pct < PKT_I_FRAME || pct > PKT_B_FRAME)
|
||||
return 1; /* Illegal picture_coding_type */
|
||||
|
||||
/* If this is the first I-frame seen, set dts_start as a reference
|
||||
offset */
|
||||
if(pct == PKT_I_FRAME && t->tht_dts_start == AV_NOPTS_VALUE)
|
||||
t->tht_dts_start = st->st_curdts;
|
||||
|
||||
v = read_bits(&bs, 16); /* vbv_delay */
|
||||
if(v == 0xffff)
|
||||
st->st_vbv_delay = -1;
|
||||
else
|
||||
st->st_vbv_delay = av_rescale_q(v, st->st_tb, AV_TIME_BASE_Q);
|
||||
|
||||
if(st->st_curpkt != NULL)
|
||||
pkt_deref(st->st_curpkt);
|
||||
|
||||
st->st_curpkt = pkt_alloc(NULL, 0, st->st_curpts, st->st_curdts);
|
||||
st->st_curpkt->pkt_frametype = pct;
|
||||
st->st_curpkt->pkt_frametype = pkt0.pkt_frametype;
|
||||
st->st_curpkt->pkt_duration = st->st_frame_duration;
|
||||
st->st_curpkt->pkt_commercial = t->tht_tt_commercial_advice;
|
||||
|
||||
|
@ -529,18 +568,9 @@ parse_mpeg2video(th_transport_t *t, th_stream_t *st, size_t len,
|
|||
|
||||
case 0x000001b3:
|
||||
/* Sequence start code */
|
||||
if(len < 11)
|
||||
if(parse_mpeg2video_seq_start(t, st, &bs))
|
||||
return 1;
|
||||
|
||||
skip_bits(&bs, 12);
|
||||
skip_bits(&bs, 12);
|
||||
skip_bits(&bs, 4);
|
||||
st->st_frame_duration = mpeg2video_framedurations[read_bits(&bs, 4)];
|
||||
v = read_bits(&bs, 18) * 400;
|
||||
skip_bits(&bs, 1);
|
||||
|
||||
v = read_bits(&bs, 10) * 16 * 1024 / 8;
|
||||
st->st_vbv_size = v;
|
||||
break;
|
||||
|
||||
case 0x000001b5:
|
||||
|
@ -747,8 +777,6 @@ parser_compute_duration(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt)
|
|||
d = next->pkt_dts - pkt->pkt_dts;
|
||||
TAILQ_REMOVE(&st->st_durationq, pkt, pkt_queue_link);
|
||||
if(d < 10) {
|
||||
printf("%s: duration is %lld, pkt dropped\n",
|
||||
htstvstreamtype2txt(st->st_type), d);
|
||||
pkt_deref(pkt);
|
||||
return;
|
||||
}
|
||||
|
@ -817,6 +845,8 @@ parser_deliver(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt)
|
|||
#endif
|
||||
pkt->pkt_stream = st;
|
||||
|
||||
avgstat_add(&st->st_rate, pkt->pkt_payloadlen, dispatch_clock);
|
||||
|
||||
/* Alert all muxers tied to us that a new packet has arrived */
|
||||
|
||||
LIST_FOREACH(tm, &t->tht_muxers, tm_transport_link)
|
||||
|
@ -827,3 +857,64 @@ parser_deliver(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt)
|
|||
|
||||
pkt_deref(pkt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive whole frames
|
||||
*
|
||||
* Analyze them as much as we need to and patch up PTS and duration
|
||||
* if needed
|
||||
*/
|
||||
void
|
||||
parser_enqueue_packet(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt)
|
||||
{
|
||||
uint8_t *buf = pkt->pkt_payload;
|
||||
uint32_t sc = 0xffffffff;
|
||||
int i, err = 0, rem;
|
||||
bitstream_t bs;
|
||||
|
||||
assert(pkt->pkt_dts != AV_NOPTS_VALUE); /* We require DTS to be set */
|
||||
pkt->pkt_duration = 0;
|
||||
|
||||
/* Per stream type analysis */
|
||||
|
||||
switch(st->st_type) {
|
||||
case HTSTV_MPEG2VIDEO:
|
||||
for(i = 0; i < pkt->pkt_payloadlen && err == 0; i++) {
|
||||
sc = (sc << 8) | buf[i];
|
||||
|
||||
if((sc & 0xffffff00) != 0x00000100)
|
||||
continue;
|
||||
|
||||
if(sc >= 0x101 && sc <= 0x1af)
|
||||
break; /* slices, dont scan further */
|
||||
|
||||
rem = pkt->pkt_payloadlen - i - 1;
|
||||
init_bits(&bs, buf + i + 1, rem);
|
||||
|
||||
switch(sc) {
|
||||
case 0x00000100: /* Picture start code */
|
||||
err = parse_mpeg2video_pic_start(t, st, pkt, &bs);
|
||||
break;
|
||||
|
||||
case 0x000001b3: /* Sequence start code */
|
||||
if(t->tht_dts_start == AV_NOPTS_VALUE)
|
||||
t->tht_dts_start = pkt->pkt_dts;
|
||||
err = parse_mpeg2video_seq_start(t, st, &bs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
pkt->pkt_pts = pkt->pkt_dts;
|
||||
break;
|
||||
}
|
||||
|
||||
if(err) {
|
||||
pkt_deref(pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
parse_compute_pts(t, st, pkt);
|
||||
}
|
||||
|
|
|
@ -27,4 +27,6 @@ void parser_compute_duration(th_transport_t *t, th_stream_t *st,
|
|||
|
||||
void parse_compute_pts(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt);
|
||||
|
||||
void parser_enqueue_packet(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt);
|
||||
|
||||
#endif /* PARSERS_H */
|
||||
|
|
Loading…
Add table
Reference in a new issue