add ff_parse_mpeg2_descriptor; make MPEG2 descriptor parsing routines available to other modules.
Originally committed as revision 26125 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
0af1671e53
commit
cc9038e95c
@ -893,16 +893,101 @@ static int mp4_read_iods(AVFormatContext *s, const uint8_t *buf, unsigned size,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type,
|
||||||
|
const uint8_t **pp, const uint8_t *desc_list_end,
|
||||||
|
int mp4_dec_config_descr_len, int mp4_es_id, int pid,
|
||||||
|
uint8_t *mp4_dec_config_descr)
|
||||||
|
{
|
||||||
|
const uint8_t *desc_end;
|
||||||
|
int desc_len, desc_tag;
|
||||||
|
char language[4];
|
||||||
|
|
||||||
|
desc_tag = get8(pp, desc_list_end);
|
||||||
|
if (desc_tag < 0)
|
||||||
|
return -1;
|
||||||
|
desc_len = get8(pp, desc_list_end);
|
||||||
|
if (desc_len < 0)
|
||||||
|
return -1;
|
||||||
|
desc_end = *pp + desc_len;
|
||||||
|
if (desc_end > desc_list_end)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
dprintf(fc, "tag: 0x%02x len=%d\n", desc_tag, desc_len);
|
||||||
|
|
||||||
|
if (st->codec->codec_id == CODEC_ID_NONE &&
|
||||||
|
stream_type == STREAM_TYPE_PRIVATE_DATA)
|
||||||
|
mpegts_find_stream_type(st, desc_tag, DESC_types);
|
||||||
|
|
||||||
|
switch(desc_tag) {
|
||||||
|
case 0x1F: /* FMC descriptor */
|
||||||
|
get16(pp, desc_end);
|
||||||
|
if (st->codec->codec_id == CODEC_ID_AAC_LATM &&
|
||||||
|
mp4_dec_config_descr_len && mp4_es_id == pid) {
|
||||||
|
ByteIOContext pb;
|
||||||
|
init_put_byte(&pb, mp4_dec_config_descr,
|
||||||
|
mp4_dec_config_descr_len, 0, NULL, NULL, NULL, NULL);
|
||||||
|
ff_mp4_read_dec_config_descr(fc, st, &pb);
|
||||||
|
if (st->codec->codec_id == CODEC_ID_AAC &&
|
||||||
|
st->codec->extradata_size > 0)
|
||||||
|
st->need_parsing = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x56: /* DVB teletext descriptor */
|
||||||
|
language[0] = get8(pp, desc_end);
|
||||||
|
language[1] = get8(pp, desc_end);
|
||||||
|
language[2] = get8(pp, desc_end);
|
||||||
|
language[3] = 0;
|
||||||
|
av_metadata_set2(&st->metadata, "language", language, 0);
|
||||||
|
break;
|
||||||
|
case 0x59: /* subtitling descriptor */
|
||||||
|
language[0] = get8(pp, desc_end);
|
||||||
|
language[1] = get8(pp, desc_end);
|
||||||
|
language[2] = get8(pp, desc_end);
|
||||||
|
language[3] = 0;
|
||||||
|
get8(pp, desc_end);
|
||||||
|
if (st->codec->extradata) {
|
||||||
|
if (st->codec->extradata_size == 4 && memcmp(st->codec->extradata, *pp, 4))
|
||||||
|
av_log_ask_for_sample(fc, "DVB sub with multiple IDs\n");
|
||||||
|
} else {
|
||||||
|
st->codec->extradata = av_malloc(4 + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
if (st->codec->extradata) {
|
||||||
|
st->codec->extradata_size = 4;
|
||||||
|
memcpy(st->codec->extradata, *pp, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*pp += 4;
|
||||||
|
av_metadata_set2(&st->metadata, "language", language, 0);
|
||||||
|
break;
|
||||||
|
case 0x0a: /* ISO 639 language descriptor */
|
||||||
|
language[0] = get8(pp, desc_end);
|
||||||
|
language[1] = get8(pp, desc_end);
|
||||||
|
language[2] = get8(pp, desc_end);
|
||||||
|
language[3] = 0;
|
||||||
|
av_metadata_set2(&st->metadata, "language", language, 0);
|
||||||
|
break;
|
||||||
|
case 0x05: /* registration descriptor */
|
||||||
|
st->codec->codec_tag = bytestream_get_le32(pp);
|
||||||
|
dprintf(fc, "reg_desc=%.4s\n", (char*)&st->codec->codec_tag);
|
||||||
|
if (st->codec->codec_id == CODEC_ID_NONE &&
|
||||||
|
stream_type == STREAM_TYPE_PRIVATE_DATA)
|
||||||
|
mpegts_find_stream_type(st, st->codec->codec_tag, REGD_types);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*pp = desc_end;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
|
static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
|
||||||
{
|
{
|
||||||
MpegTSContext *ts = filter->u.section_filter.opaque;
|
MpegTSContext *ts = filter->u.section_filter.opaque;
|
||||||
SectionHeader h1, *h = &h1;
|
SectionHeader h1, *h = &h1;
|
||||||
PESContext *pes;
|
PESContext *pes;
|
||||||
AVStream *st;
|
AVStream *st;
|
||||||
const uint8_t *p, *p_end, *desc_list_end, *desc_end;
|
const uint8_t *p, *p_end, *desc_list_end;
|
||||||
int program_info_length, pcr_pid, pid, stream_type;
|
int program_info_length, pcr_pid, pid, stream_type;
|
||||||
int desc_list_len, desc_len, desc_tag;
|
int desc_list_len;
|
||||||
char language[4];
|
|
||||||
uint32_t prog_reg_desc = 0; /* registration descriptor */
|
uint32_t prog_reg_desc = 0; /* registration descriptor */
|
||||||
uint8_t *mp4_dec_config_descr = NULL;
|
uint8_t *mp4_dec_config_descr = NULL;
|
||||||
int mp4_dec_config_descr_len = 0;
|
int mp4_dec_config_descr_len = 0;
|
||||||
@ -1005,81 +1090,9 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
|
|||||||
if (desc_list_end > p_end)
|
if (desc_list_end > p_end)
|
||||||
break;
|
break;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
desc_tag = get8(&p, desc_list_end);
|
if (ff_parse_mpeg2_descriptor(ts->stream, st, stream_type, &p, desc_list_end,
|
||||||
if (desc_tag < 0)
|
mp4_dec_config_descr_len, mp4_es_id, pid, mp4_dec_config_descr) < 0)
|
||||||
break;
|
break;
|
||||||
desc_len = get8(&p, desc_list_end);
|
|
||||||
if (desc_len < 0)
|
|
||||||
break;
|
|
||||||
desc_end = p + desc_len;
|
|
||||||
if (desc_end > desc_list_end)
|
|
||||||
break;
|
|
||||||
|
|
||||||
dprintf(ts->stream, "tag: 0x%02x len=%d\n",
|
|
||||||
desc_tag, desc_len);
|
|
||||||
|
|
||||||
if (st->codec->codec_id == CODEC_ID_NONE &&
|
|
||||||
stream_type == STREAM_TYPE_PRIVATE_DATA)
|
|
||||||
mpegts_find_stream_type(st, desc_tag, DESC_types);
|
|
||||||
|
|
||||||
switch(desc_tag) {
|
|
||||||
case 0x1F: /* FMC descriptor */
|
|
||||||
get16(&p, desc_end);
|
|
||||||
if (st->codec->codec_id == CODEC_ID_AAC_LATM &&
|
|
||||||
mp4_dec_config_descr_len && mp4_es_id == pid) {
|
|
||||||
ByteIOContext pb;
|
|
||||||
init_put_byte(&pb, mp4_dec_config_descr,
|
|
||||||
mp4_dec_config_descr_len, 0, NULL, NULL, NULL, NULL);
|
|
||||||
ff_mp4_read_dec_config_descr(ts->stream, st, &pb);
|
|
||||||
if (st->codec->codec_id == CODEC_ID_AAC &&
|
|
||||||
st->codec->extradata_size > 0)
|
|
||||||
st->need_parsing = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x56: /* DVB teletext descriptor */
|
|
||||||
language[0] = get8(&p, desc_end);
|
|
||||||
language[1] = get8(&p, desc_end);
|
|
||||||
language[2] = get8(&p, desc_end);
|
|
||||||
language[3] = 0;
|
|
||||||
av_metadata_set2(&st->metadata, "language", language, 0);
|
|
||||||
break;
|
|
||||||
case 0x59: /* subtitling descriptor */
|
|
||||||
language[0] = get8(&p, desc_end);
|
|
||||||
language[1] = get8(&p, desc_end);
|
|
||||||
language[2] = get8(&p, desc_end);
|
|
||||||
language[3] = 0;
|
|
||||||
get8(&p, desc_end);
|
|
||||||
if (st->codec->extradata) {
|
|
||||||
if (st->codec->extradata_size == 4 && memcmp(st->codec->extradata, p, 4))
|
|
||||||
av_log_ask_for_sample(ts->stream, "DVB sub with multiple IDs\n");
|
|
||||||
} else {
|
|
||||||
st->codec->extradata = av_malloc(4 + FF_INPUT_BUFFER_PADDING_SIZE);
|
|
||||||
if (st->codec->extradata) {
|
|
||||||
st->codec->extradata_size = 4;
|
|
||||||
memcpy(st->codec->extradata, p, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p += 4;
|
|
||||||
av_metadata_set2(&st->metadata, "language", language, 0);
|
|
||||||
break;
|
|
||||||
case 0x0a: /* ISO 639 language descriptor */
|
|
||||||
language[0] = get8(&p, desc_end);
|
|
||||||
language[1] = get8(&p, desc_end);
|
|
||||||
language[2] = get8(&p, desc_end);
|
|
||||||
language[3] = 0;
|
|
||||||
av_metadata_set2(&st->metadata, "language", language, 0);
|
|
||||||
break;
|
|
||||||
case 0x05: /* registration descriptor */
|
|
||||||
st->codec->codec_tag = bytestream_get_le32(&p);
|
|
||||||
dprintf(ts->stream, "reg_desc=%.4s\n", (char*)&st->codec->codec_tag);
|
|
||||||
if (st->codec->codec_id == CODEC_ID_NONE &&
|
|
||||||
stream_type == STREAM_TYPE_PRIVATE_DATA)
|
|
||||||
mpegts_find_stream_type(st, st->codec->codec_tag, REGD_types);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p = desc_end;
|
|
||||||
|
|
||||||
if (prog_reg_desc == AV_RL32("HDMV") && stream_type == 0x83 && pes->sub_st) {
|
if (prog_reg_desc == AV_RL32("HDMV") && stream_type == 0x83 && pes->sub_st) {
|
||||||
ff_program_add_stream_index(ts->stream, h->id, pes->sub_st->index);
|
ff_program_add_stream_index(ts->stream, h->id, pes->sub_st->index);
|
||||||
|
@ -63,4 +63,22 @@ int ff_mpegts_parse_packet(MpegTSContext *ts, AVPacket *pkt,
|
|||||||
const uint8_t *buf, int len);
|
const uint8_t *buf, int len);
|
||||||
void ff_mpegts_parse_close(MpegTSContext *ts);
|
void ff_mpegts_parse_close(MpegTSContext *ts);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse an MPEG-2 descriptor
|
||||||
|
* @param[in] fc Format context (used for logging only)
|
||||||
|
* @param st Stream
|
||||||
|
* @param stream_type STREAM_TYPE_xxx
|
||||||
|
* @param pp Descriptor buffer pointer
|
||||||
|
* @param desc_list_end End of buffer
|
||||||
|
* @param mp4_dec_config_descr_len Length of 'mp4_dec_config_descr', or zero if not present
|
||||||
|
* @param mp4_es_id
|
||||||
|
* @param pid
|
||||||
|
* @param mp4_dec_config_descr
|
||||||
|
* @return <0 to stop processing
|
||||||
|
*/
|
||||||
|
int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type,
|
||||||
|
const uint8_t **pp, const uint8_t *desc_list_end,
|
||||||
|
int mp4_dec_config_descr_len, int mp4_es_id, int pid,
|
||||||
|
uint8_t *mp4_dec_config_descr);
|
||||||
|
|
||||||
#endif /* AVFORMAT_MPEGTS_H */
|
#endif /* AVFORMAT_MPEGTS_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user