move code to avoid forward declaration
Originally committed as revision 20475 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
b3f9f7a333
commit
609d864611
@ -42,8 +42,6 @@
|
||||
|
||||
typedef struct PESContext PESContext;
|
||||
|
||||
static PESContext* add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid);
|
||||
|
||||
enum MpegTSFilterType {
|
||||
MPEGTS_PES,
|
||||
MPEGTS_SECTION,
|
||||
@ -604,6 +602,244 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int64_t get_pts(const uint8_t *p)
|
||||
{
|
||||
int64_t pts = (int64_t)((p[0] >> 1) & 0x07) << 30;
|
||||
pts |= (AV_RB16(p + 1) >> 1) << 15;
|
||||
pts |= AV_RB16(p + 3) >> 1;
|
||||
return pts;
|
||||
}
|
||||
|
||||
static void new_pes_packet(PESContext *pes, AVPacket *pkt)
|
||||
{
|
||||
av_init_packet(pkt);
|
||||
|
||||
pkt->destruct = av_destruct_packet;
|
||||
pkt->data = pes->buffer;
|
||||
pkt->size = pes->data_index;
|
||||
memset(pkt->data+pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
|
||||
// Separate out the AC3 substream from an HDMV combined TrueHD/AC3 PID
|
||||
if (pes->sub_st && pes->stream_type == 0x83 && pes->extended_stream_id == 0x76)
|
||||
pkt->stream_index = pes->sub_st->index;
|
||||
else
|
||||
pkt->stream_index = pes->st->index;
|
||||
pkt->pts = pes->pts;
|
||||
pkt->dts = pes->dts;
|
||||
/* store position of first TS packet of this PES packet */
|
||||
pkt->pos = pes->ts_packet_pos;
|
||||
|
||||
/* reset pts values */
|
||||
pes->pts = AV_NOPTS_VALUE;
|
||||
pes->dts = AV_NOPTS_VALUE;
|
||||
pes->buffer = NULL;
|
||||
pes->data_index = 0;
|
||||
}
|
||||
|
||||
/* return non zero if a packet could be constructed */
|
||||
static int mpegts_push_data(MpegTSFilter *filter,
|
||||
const uint8_t *buf, int buf_size, int is_start,
|
||||
int64_t pos)
|
||||
{
|
||||
PESContext *pes = filter->u.pes_filter.opaque;
|
||||
MpegTSContext *ts = pes->ts;
|
||||
const uint8_t *p;
|
||||
int len, code;
|
||||
|
||||
if(!ts->pkt)
|
||||
return 0;
|
||||
|
||||
if (is_start) {
|
||||
if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) {
|
||||
new_pes_packet(pes, ts->pkt);
|
||||
ts->stop_parse = 1;
|
||||
}
|
||||
pes->state = MPEGTS_HEADER;
|
||||
pes->data_index = 0;
|
||||
pes->ts_packet_pos = pos;
|
||||
}
|
||||
p = buf;
|
||||
while (buf_size > 0) {
|
||||
switch(pes->state) {
|
||||
case MPEGTS_HEADER:
|
||||
len = PES_START_SIZE - pes->data_index;
|
||||
if (len > buf_size)
|
||||
len = buf_size;
|
||||
memcpy(pes->header + pes->data_index, p, len);
|
||||
pes->data_index += len;
|
||||
p += len;
|
||||
buf_size -= len;
|
||||
if (pes->data_index == PES_START_SIZE) {
|
||||
/* we got all the PES or section header. We can now
|
||||
decide */
|
||||
#if 0
|
||||
av_hex_dump_log(pes->stream, AV_LOG_DEBUG, pes->header, pes->data_index);
|
||||
#endif
|
||||
if (pes->header[0] == 0x00 && pes->header[1] == 0x00 &&
|
||||
pes->header[2] == 0x01) {
|
||||
/* it must be an mpeg2 PES stream */
|
||||
code = pes->header[3] | 0x100;
|
||||
dprintf(pes->stream, "pid=%x pes_code=%#x\n", pes->pid, code);
|
||||
|
||||
if ((!pes->st && pes->stream->nb_streams == MAX_STREAMS) ||
|
||||
(pes->st && pes->st->discard == AVDISCARD_ALL) ||
|
||||
code == 0x1be) /* padding_stream */
|
||||
goto skip;
|
||||
|
||||
/* stream not present in PMT */
|
||||
if (!pes->st) {
|
||||
pes->st = av_new_stream(ts->stream, pes->pid);
|
||||
if (!pes->st)
|
||||
return AVERROR(ENOMEM);
|
||||
mpegts_set_stream_info(pes->st, pes, 0, 0);
|
||||
}
|
||||
|
||||
pes->total_size = AV_RB16(pes->header + 4);
|
||||
/* NOTE: a zero total size means the PES size is
|
||||
unbounded */
|
||||
if (!pes->total_size)
|
||||
pes->total_size = MAX_PES_PAYLOAD;
|
||||
|
||||
/* allocate pes buffer */
|
||||
pes->buffer = av_malloc(pes->total_size+FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
if (!pes->buffer)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
if (code != 0x1bc && code != 0x1bf && /* program_stream_map, private_stream_2 */
|
||||
code != 0x1f0 && code != 0x1f1 && /* ECM, EMM */
|
||||
code != 0x1ff && code != 0x1f2 && /* program_stream_directory, DSMCC_stream */
|
||||
code != 0x1f8) { /* ITU-T Rec. H.222.1 type E stream */
|
||||
pes->state = MPEGTS_PESHEADER;
|
||||
if (pes->st->codec->codec_id == CODEC_ID_NONE) {
|
||||
dprintf(pes->stream, "pid=%x stream_type=%x probing\n",
|
||||
pes->pid, pes->stream_type);
|
||||
pes->st->codec->codec_id = CODEC_ID_PROBE;
|
||||
}
|
||||
} else {
|
||||
pes->state = MPEGTS_PAYLOAD;
|
||||
pes->data_index = 0;
|
||||
}
|
||||
} else {
|
||||
/* otherwise, it should be a table */
|
||||
/* skip packet */
|
||||
skip:
|
||||
pes->state = MPEGTS_SKIP;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
/**********************************************/
|
||||
/* PES packing parsing */
|
||||
case MPEGTS_PESHEADER:
|
||||
len = PES_HEADER_SIZE - pes->data_index;
|
||||
if (len < 0)
|
||||
return -1;
|
||||
if (len > buf_size)
|
||||
len = buf_size;
|
||||
memcpy(pes->header + pes->data_index, p, len);
|
||||
pes->data_index += len;
|
||||
p += len;
|
||||
buf_size -= len;
|
||||
if (pes->data_index == PES_HEADER_SIZE) {
|
||||
pes->pes_header_size = pes->header[8] + 9;
|
||||
pes->state = MPEGTS_PESHEADER_FILL;
|
||||
}
|
||||
break;
|
||||
case MPEGTS_PESHEADER_FILL:
|
||||
len = pes->pes_header_size - pes->data_index;
|
||||
if (len < 0)
|
||||
return -1;
|
||||
if (len > buf_size)
|
||||
len = buf_size;
|
||||
memcpy(pes->header + pes->data_index, p, len);
|
||||
pes->data_index += len;
|
||||
p += len;
|
||||
buf_size -= len;
|
||||
if (pes->data_index == pes->pes_header_size) {
|
||||
const uint8_t *r;
|
||||
unsigned int flags, pes_ext, skip;
|
||||
|
||||
flags = pes->header[7];
|
||||
r = pes->header + 9;
|
||||
pes->pts = AV_NOPTS_VALUE;
|
||||
pes->dts = AV_NOPTS_VALUE;
|
||||
if ((flags & 0xc0) == 0x80) {
|
||||
pes->dts = pes->pts = get_pts(r);
|
||||
r += 5;
|
||||
} else if ((flags & 0xc0) == 0xc0) {
|
||||
pes->pts = get_pts(r);
|
||||
r += 5;
|
||||
pes->dts = get_pts(r);
|
||||
r += 5;
|
||||
}
|
||||
pes->extended_stream_id = -1;
|
||||
if (flags & 0x01) { /* PES extension */
|
||||
pes_ext = *r++;
|
||||
/* Skip PES private data, program packet sequence counter and P-STD buffer */
|
||||
skip = (pes_ext >> 4) & 0xb;
|
||||
skip += skip & 0x9;
|
||||
r += skip;
|
||||
if ((pes_ext & 0x41) == 0x01 &&
|
||||
(r + 2) <= (pes->header + pes->pes_header_size)) {
|
||||
/* PES extension 2 */
|
||||
if ((r[0] & 0x7f) > 0 && (r[1] & 0x80) == 0)
|
||||
pes->extended_stream_id = r[1];
|
||||
}
|
||||
}
|
||||
|
||||
/* we got the full header. We parse it and get the payload */
|
||||
pes->state = MPEGTS_PAYLOAD;
|
||||
pes->data_index = 0;
|
||||
}
|
||||
break;
|
||||
case MPEGTS_PAYLOAD:
|
||||
if (buf_size > 0 && pes->buffer) {
|
||||
if (pes->data_index+buf_size > pes->total_size) {
|
||||
new_pes_packet(pes, ts->pkt);
|
||||
pes->total_size = MAX_PES_PAYLOAD;
|
||||
pes->buffer = av_malloc(pes->total_size+FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
if (!pes->buffer)
|
||||
return AVERROR(ENOMEM);
|
||||
ts->stop_parse = 1;
|
||||
}
|
||||
memcpy(pes->buffer+pes->data_index, p, buf_size);
|
||||
pes->data_index += buf_size;
|
||||
}
|
||||
buf_size = 0;
|
||||
break;
|
||||
case MPEGTS_SKIP:
|
||||
buf_size = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid)
|
||||
{
|
||||
MpegTSFilter *tss;
|
||||
PESContext *pes;
|
||||
|
||||
/* if no pid found, then add a pid context */
|
||||
pes = av_mallocz(sizeof(PESContext));
|
||||
if (!pes)
|
||||
return 0;
|
||||
pes->ts = ts;
|
||||
pes->stream = ts->stream;
|
||||
pes->pid = pid;
|
||||
pes->pcr_pid = pcr_pid;
|
||||
pes->state = MPEGTS_SKIP;
|
||||
pes->pts = AV_NOPTS_VALUE;
|
||||
pes->dts = AV_NOPTS_VALUE;
|
||||
tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes);
|
||||
if (!tss) {
|
||||
av_free(pes);
|
||||
return 0;
|
||||
}
|
||||
return pes;
|
||||
}
|
||||
|
||||
static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
|
||||
{
|
||||
MpegTSContext *ts = filter->u.section_filter.opaque;
|
||||
@ -888,244 +1124,6 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t get_pts(const uint8_t *p)
|
||||
{
|
||||
int64_t pts = (int64_t)((p[0] >> 1) & 0x07) << 30;
|
||||
pts |= (AV_RB16(p + 1) >> 1) << 15;
|
||||
pts |= AV_RB16(p + 3) >> 1;
|
||||
return pts;
|
||||
}
|
||||
|
||||
static void new_pes_packet(PESContext *pes, AVPacket *pkt)
|
||||
{
|
||||
av_init_packet(pkt);
|
||||
|
||||
pkt->destruct = av_destruct_packet;
|
||||
pkt->data = pes->buffer;
|
||||
pkt->size = pes->data_index;
|
||||
memset(pkt->data+pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
|
||||
// Separate out the AC3 substream from an HDMV combined TrueHD/AC3 PID
|
||||
if (pes->sub_st && pes->stream_type == 0x83 && pes->extended_stream_id == 0x76)
|
||||
pkt->stream_index = pes->sub_st->index;
|
||||
else
|
||||
pkt->stream_index = pes->st->index;
|
||||
pkt->pts = pes->pts;
|
||||
pkt->dts = pes->dts;
|
||||
/* store position of first TS packet of this PES packet */
|
||||
pkt->pos = pes->ts_packet_pos;
|
||||
|
||||
/* reset pts values */
|
||||
pes->pts = AV_NOPTS_VALUE;
|
||||
pes->dts = AV_NOPTS_VALUE;
|
||||
pes->buffer = NULL;
|
||||
pes->data_index = 0;
|
||||
}
|
||||
|
||||
/* return non zero if a packet could be constructed */
|
||||
static int mpegts_push_data(MpegTSFilter *filter,
|
||||
const uint8_t *buf, int buf_size, int is_start,
|
||||
int64_t pos)
|
||||
{
|
||||
PESContext *pes = filter->u.pes_filter.opaque;
|
||||
MpegTSContext *ts = pes->ts;
|
||||
const uint8_t *p;
|
||||
int len, code;
|
||||
|
||||
if(!ts->pkt)
|
||||
return 0;
|
||||
|
||||
if (is_start) {
|
||||
if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) {
|
||||
new_pes_packet(pes, ts->pkt);
|
||||
ts->stop_parse = 1;
|
||||
}
|
||||
pes->state = MPEGTS_HEADER;
|
||||
pes->data_index = 0;
|
||||
pes->ts_packet_pos = pos;
|
||||
}
|
||||
p = buf;
|
||||
while (buf_size > 0) {
|
||||
switch(pes->state) {
|
||||
case MPEGTS_HEADER:
|
||||
len = PES_START_SIZE - pes->data_index;
|
||||
if (len > buf_size)
|
||||
len = buf_size;
|
||||
memcpy(pes->header + pes->data_index, p, len);
|
||||
pes->data_index += len;
|
||||
p += len;
|
||||
buf_size -= len;
|
||||
if (pes->data_index == PES_START_SIZE) {
|
||||
/* we got all the PES or section header. We can now
|
||||
decide */
|
||||
#if 0
|
||||
av_hex_dump_log(pes->stream, AV_LOG_DEBUG, pes->header, pes->data_index);
|
||||
#endif
|
||||
if (pes->header[0] == 0x00 && pes->header[1] == 0x00 &&
|
||||
pes->header[2] == 0x01) {
|
||||
/* it must be an mpeg2 PES stream */
|
||||
code = pes->header[3] | 0x100;
|
||||
dprintf(pes->stream, "pid=%x pes_code=%#x\n", pes->pid, code);
|
||||
|
||||
if ((!pes->st && pes->stream->nb_streams == MAX_STREAMS) ||
|
||||
(pes->st && pes->st->discard == AVDISCARD_ALL) ||
|
||||
code == 0x1be) /* padding_stream */
|
||||
goto skip;
|
||||
|
||||
/* stream not present in PMT */
|
||||
if (!pes->st) {
|
||||
pes->st = av_new_stream(ts->stream, pes->pid);
|
||||
if (!pes->st)
|
||||
return AVERROR(ENOMEM);
|
||||
mpegts_set_stream_info(pes->st, pes, 0, 0);
|
||||
}
|
||||
|
||||
pes->total_size = AV_RB16(pes->header + 4);
|
||||
/* NOTE: a zero total size means the PES size is
|
||||
unbounded */
|
||||
if (!pes->total_size)
|
||||
pes->total_size = MAX_PES_PAYLOAD;
|
||||
|
||||
/* allocate pes buffer */
|
||||
pes->buffer = av_malloc(pes->total_size+FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
if (!pes->buffer)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
if (code != 0x1bc && code != 0x1bf && /* program_stream_map, private_stream_2 */
|
||||
code != 0x1f0 && code != 0x1f1 && /* ECM, EMM */
|
||||
code != 0x1ff && code != 0x1f2 && /* program_stream_directory, DSMCC_stream */
|
||||
code != 0x1f8) { /* ITU-T Rec. H.222.1 type E stream */
|
||||
pes->state = MPEGTS_PESHEADER;
|
||||
if (pes->st->codec->codec_id == CODEC_ID_NONE) {
|
||||
dprintf(pes->stream, "pid=%x stream_type=%x probing\n",
|
||||
pes->pid, pes->stream_type);
|
||||
pes->st->codec->codec_id = CODEC_ID_PROBE;
|
||||
}
|
||||
} else {
|
||||
pes->state = MPEGTS_PAYLOAD;
|
||||
pes->data_index = 0;
|
||||
}
|
||||
} else {
|
||||
/* otherwise, it should be a table */
|
||||
/* skip packet */
|
||||
skip:
|
||||
pes->state = MPEGTS_SKIP;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
/**********************************************/
|
||||
/* PES packing parsing */
|
||||
case MPEGTS_PESHEADER:
|
||||
len = PES_HEADER_SIZE - pes->data_index;
|
||||
if (len < 0)
|
||||
return -1;
|
||||
if (len > buf_size)
|
||||
len = buf_size;
|
||||
memcpy(pes->header + pes->data_index, p, len);
|
||||
pes->data_index += len;
|
||||
p += len;
|
||||
buf_size -= len;
|
||||
if (pes->data_index == PES_HEADER_SIZE) {
|
||||
pes->pes_header_size = pes->header[8] + 9;
|
||||
pes->state = MPEGTS_PESHEADER_FILL;
|
||||
}
|
||||
break;
|
||||
case MPEGTS_PESHEADER_FILL:
|
||||
len = pes->pes_header_size - pes->data_index;
|
||||
if (len < 0)
|
||||
return -1;
|
||||
if (len > buf_size)
|
||||
len = buf_size;
|
||||
memcpy(pes->header + pes->data_index, p, len);
|
||||
pes->data_index += len;
|
||||
p += len;
|
||||
buf_size -= len;
|
||||
if (pes->data_index == pes->pes_header_size) {
|
||||
const uint8_t *r;
|
||||
unsigned int flags, pes_ext, skip;
|
||||
|
||||
flags = pes->header[7];
|
||||
r = pes->header + 9;
|
||||
pes->pts = AV_NOPTS_VALUE;
|
||||
pes->dts = AV_NOPTS_VALUE;
|
||||
if ((flags & 0xc0) == 0x80) {
|
||||
pes->dts = pes->pts = get_pts(r);
|
||||
r += 5;
|
||||
} else if ((flags & 0xc0) == 0xc0) {
|
||||
pes->pts = get_pts(r);
|
||||
r += 5;
|
||||
pes->dts = get_pts(r);
|
||||
r += 5;
|
||||
}
|
||||
pes->extended_stream_id = -1;
|
||||
if (flags & 0x01) { /* PES extension */
|
||||
pes_ext = *r++;
|
||||
/* Skip PES private data, program packet sequence counter and P-STD buffer */
|
||||
skip = (pes_ext >> 4) & 0xb;
|
||||
skip += skip & 0x9;
|
||||
r += skip;
|
||||
if ((pes_ext & 0x41) == 0x01 &&
|
||||
(r + 2) <= (pes->header + pes->pes_header_size)) {
|
||||
/* PES extension 2 */
|
||||
if ((r[0] & 0x7f) > 0 && (r[1] & 0x80) == 0)
|
||||
pes->extended_stream_id = r[1];
|
||||
}
|
||||
}
|
||||
|
||||
/* we got the full header. We parse it and get the payload */
|
||||
pes->state = MPEGTS_PAYLOAD;
|
||||
pes->data_index = 0;
|
||||
}
|
||||
break;
|
||||
case MPEGTS_PAYLOAD:
|
||||
if (buf_size > 0 && pes->buffer) {
|
||||
if (pes->data_index+buf_size > pes->total_size) {
|
||||
new_pes_packet(pes, ts->pkt);
|
||||
pes->total_size = MAX_PES_PAYLOAD;
|
||||
pes->buffer = av_malloc(pes->total_size+FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
if (!pes->buffer)
|
||||
return AVERROR(ENOMEM);
|
||||
ts->stop_parse = 1;
|
||||
}
|
||||
memcpy(pes->buffer+pes->data_index, p, buf_size);
|
||||
pes->data_index += buf_size;
|
||||
}
|
||||
buf_size = 0;
|
||||
break;
|
||||
case MPEGTS_SKIP:
|
||||
buf_size = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid)
|
||||
{
|
||||
MpegTSFilter *tss;
|
||||
PESContext *pes;
|
||||
|
||||
/* if no pid found, then add a pid context */
|
||||
pes = av_mallocz(sizeof(PESContext));
|
||||
if (!pes)
|
||||
return 0;
|
||||
pes->ts = ts;
|
||||
pes->stream = ts->stream;
|
||||
pes->pid = pid;
|
||||
pes->pcr_pid = pcr_pid;
|
||||
pes->state = MPEGTS_SKIP;
|
||||
pes->pts = AV_NOPTS_VALUE;
|
||||
pes->dts = AV_NOPTS_VALUE;
|
||||
tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes);
|
||||
if (!tss) {
|
||||
av_free(pes);
|
||||
return 0;
|
||||
}
|
||||
return pes;
|
||||
}
|
||||
|
||||
/* handle one TS packet */
|
||||
static int handle_packet(MpegTSContext *ts, const uint8_t *packet)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user