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
*
{
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);
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;
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:
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;
}
#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)
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);
+}