X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmpegts.c;h=c466710eee974065a114ffb075e353b77b70aed0;hb=65a00bd65a3619faf5c5fabbdb4029b36c045483;hp=cce6e7545a146b433cb13f611f105b2f107c6ec2;hpb=ff70e60176056daf646109b8e42654a3036fa02b;p=ffmpeg diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index cce6e7545a1..c466710eee9 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -1,19 +1,21 @@ /* - * MPEG2 transport stream (aka DVB) demux + * MPEG2 transport stream (aka DVB) demuxer * Copyright (c) 2002-2003 Fabrice Bellard. * - * This library is free software; you can redistribute it and/or + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "avformat.h" @@ -73,47 +75,62 @@ typedef struct MpegTSFilter { typedef struct MpegTSService { int running:1; - int sid; - char *provider_name; - char *name; + int sid; /**< MPEG Program Number of stream */ + char *provider_name; /**< DVB Network name, "" if not DVB stream */ + char *name; /**< DVB Service name, "MPEG Program [sid]" if not DVB stream*/ } MpegTSService; struct MpegTSContext { /* user data */ AVFormatContext *stream; - int raw_packet_size; /* raw packet size, including FEC if present */ - int auto_guess; /* if true, all pids are analized to find streams */ + /** raw packet size, including FEC if present */ + int raw_packet_size; + /** if true, all pids are analyzed to find streams */ + int auto_guess; int set_service_ret; - int mpeg2ts_raw; /* force raw MPEG2 transport stream output, if possible */ - int mpeg2ts_compute_pcr; /* compute exact PCR for each transport stream packet */ + /** force raw MPEG2 transport stream output, if possible */ + int mpeg2ts_raw; + /** compute exact PCR for each transport stream packet */ + int mpeg2ts_compute_pcr; - /* used to estimate the exact PCR */ - int64_t cur_pcr; - int pcr_incr; - int pcr_pid; + int64_t cur_pcr; /**< used to estimate the exact PCR */ + int pcr_incr; /**< used to estimate the exact PCR */ + int pcr_pid; /**< used to estimate the exact PCR */ /* data needed to handle file based ts */ - int stop_parse; /* stop parsing loop */ - AVPacket *pkt; /* packet containing av data */ + /** stop parsing loop */ + int stop_parse; + /** packet containing Audio/Video data */ + AVPacket *pkt; /******************************************/ /* private mpegts data */ /* scan context */ MpegTSFilter *sdt_filter; + /** number of PMTs in the last PAT seen */ int nb_services; + /** list of PMTs in the last PAT seen */ MpegTSService **services; /* set service context (XXX: allocated it ?) */ SetServiceCallback *set_service_cb; void *set_service_opaque; + /** filter for the PAT */ MpegTSFilter *pat_filter; + /** filter for the PMT for the MPEG program number specified by req_sid */ MpegTSFilter *pmt_filter; + /** MPEG program number of stream we want to decode */ int req_sid; + /** filters for various streams specified by PMT + for the PAT and PMT */ MpegTSFilter *pids[NB_PID_MAX]; }; +/** + * Assembles PES packets out of TS packets, and then calls the "section_cb" + * function when they are complete. + */ static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1, const uint8_t *buf, int buf_size, int is_start) { @@ -160,7 +177,7 @@ static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, unsigned int MpegTSSectionFilter *sec; #ifdef DEBUG_SI - printf("Filter: pid=0x%x\n", pid); + av_log(ts->stream, AV_LOG_DEBUG, "Filter: pid=0x%x\n", pid); #endif if (pid >= NB_PID_MAX || ts->pids[pid]) return NULL; @@ -355,7 +372,8 @@ static MpegTSService *new_service(MpegTSContext *ts, int sid, MpegTSService *service; #ifdef DEBUG_SI - printf("new_service: sid=0x%04x provider='%s' name='%s'\n", + av_log(ts->stream, AV_LOG_DEBUG, "new_service: " + "sid=0x%04x provider='%s' name='%s'\n", sid, provider_name, name); #endif @@ -382,15 +400,16 @@ static void pmt_cb(void *opaque, const uint8_t *section, int section_len) char language[4]; #ifdef DEBUG_SI - printf("PMT:\n"); - av_hex_dump(stdout, (uint8_t *)section, section_len); + av_log(ts->stream, AV_LOG_DEBUG, "PMT: len %i\n", section_len); + av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len); #endif p_end = section + section_len - 4; p = section; if (parse_section_header(h, &p, p_end) < 0) return; #ifdef DEBUG_SI - printf("sid=0x%x sec_num=%d/%d\n", h->id, h->sec_num, h->last_sec_num); + av_log(ts->stream, AV_LOG_DEBUG, "sid=0x%x sec_num=%d/%d\n", + h->id, h->sec_num, h->last_sec_num); #endif if (h->tid != PMT_TID || (ts->req_sid >= 0 && h->id != ts->req_sid) ) return; @@ -400,7 +419,7 @@ static void pmt_cb(void *opaque, const uint8_t *section, int section_len) return; ts->pcr_pid = pcr_pid; #ifdef DEBUG_SI - printf("pcr_pid=0x%x\n", pcr_pid); + av_log(ts->stream, AV_LOG_DEBUG, "pcr_pid=0x%x\n", pcr_pid); #endif program_info_length = get16(&p, p_end) & 0xfff; if (program_info_length < 0) @@ -441,7 +460,8 @@ static void pmt_cb(void *opaque, const uint8_t *section, int section_len) if (desc_end > desc_list_end) break; #ifdef DEBUG_SI - printf("tag: 0x%02x len=%d\n", desc_tag, desc_len); + av_log(ts->stream, AV_LOG_DEBUG, "tag: 0x%02x len=%d\n", + desc_tag, desc_len); #endif switch(desc_tag) { case DVB_SUBT_DESCID: @@ -471,7 +491,8 @@ static void pmt_cb(void *opaque, const uint8_t *section, int section_len) p = desc_list_end; #ifdef DEBUG_SI - printf("stream_type=%d pid=0x%x\n", stream_type, pid); + av_log(ts->stream, AV_LOG_DEBUG, "stream_type=%d pid=0x%x\n", + stream_type, pid); #endif /* now create ffmpeg stream */ @@ -482,6 +503,7 @@ static void pmt_cb(void *opaque, const uint8_t *section, int section_len) case STREAM_TYPE_VIDEO_MPEG2: case STREAM_TYPE_VIDEO_MPEG4: case STREAM_TYPE_VIDEO_H264: + case STREAM_TYPE_VIDEO_VC1: case STREAM_TYPE_AUDIO_AAC: case STREAM_TYPE_AUDIO_AC3: case STREAM_TYPE_AUDIO_DTS: @@ -522,8 +544,8 @@ static void pat_cb(void *opaque, const uint8_t *section, int section_len) int sid, pmt_pid; #ifdef DEBUG_SI - printf("PAT:\n"); - av_hex_dump(stdout, (uint8_t *)section, section_len); + av_log(ts->stream, AV_LOG_DEBUG, "PAT:\n"); + av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len); #endif p_end = section + section_len - 4; p = section; @@ -540,7 +562,7 @@ static void pat_cb(void *opaque, const uint8_t *section, int section_len) if (pmt_pid < 0) break; #ifdef DEBUG_SI - printf("sid=0x%x pid=0x%x\n", sid, pmt_pid); + av_log(ts->stream, AV_LOG_DEBUG, "sid=0x%x pid=0x%x\n", sid, pmt_pid); #endif if (sid == 0x0000) { /* NIT info */ @@ -571,8 +593,8 @@ static void pat_scan_cb(void *opaque, const uint8_t *section, int section_len) char buf[256]; #ifdef DEBUG_SI - printf("PAT:\n"); - av_hex_dump(stdout, (uint8_t *)section, section_len); + av_log(ts->stream, AV_LOG_DEBUG, "PAT:\n"); + av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len); #endif p_end = section + section_len - 4; p = section; @@ -589,7 +611,7 @@ static void pat_scan_cb(void *opaque, const uint8_t *section, int section_len) if (pmt_pid < 0) break; #ifdef DEBUG_SI - printf("sid=0x%x pid=0x%x\n", sid, pmt_pid); + av_log(ts->stream, AV_LOG_DEBUG, "sid=0x%x pid=0x%x\n", sid, pmt_pid); #endif if (sid == 0x0000) { /* NIT info */ @@ -632,8 +654,8 @@ static void sdt_cb(void *opaque, const uint8_t *section, int section_len) char *name, *provider_name; #ifdef DEBUG_SI - printf("SDT:\n"); - av_hex_dump(stdout, (uint8_t *)section, section_len); + av_log(ts->stream, AV_LOG_DEBUG, "SDT:\n"); + av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len); #endif p_end = section + section_len - 4; @@ -670,7 +692,8 @@ static void sdt_cb(void *opaque, const uint8_t *section, int section_len) if (desc_end > desc_list_end) break; #ifdef DEBUG_SI - printf("tag: 0x%02x len=%d\n", desc_tag, desc_len); + av_log(ts->stream, AV_LOG_DEBUG, "tag: 0x%02x len=%d\n", + desc_tag, desc_len); #endif switch(desc_tag) { case 0x48: @@ -783,7 +806,7 @@ static void mpegts_push_data(void *opaque, /* we got all the PES or section header. We can now decide */ #if 0 - av_hex_dump(pes->header, pes->data_index); + 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) { @@ -791,7 +814,7 @@ static void mpegts_push_data(void *opaque, code = pes->header[3] | 0x100; if (!((code >= 0x1c0 && code <= 0x1df) || (code >= 0x1e0 && code <= 0x1ef) || - (code == 0x1bd))) + (code == 0x1bd) || (code == 0x1fd))) goto skip; if (!pes->st) { /* allocate stream */ @@ -899,6 +922,10 @@ static AVStream* new_pes_av_stream(PESContext *pes, uint32_t code) codec_type = CODEC_TYPE_VIDEO; codec_id = CODEC_ID_H264; break; + case STREAM_TYPE_VIDEO_VC1: + codec_type = CODEC_TYPE_VIDEO; + codec_id = CODEC_ID_VC1; + break; case STREAM_TYPE_AUDIO_AAC: codec_type = CODEC_TYPE_AUDIO; codec_id = CODEC_ID_AAC; @@ -1130,7 +1157,7 @@ static int mpegts_probe(AVProbeData *p) #endif } -void set_service_cb(void *opaque, int ret) +static void set_service_cb(void *opaque, int ret) { MpegTSContext *ts = opaque; ts->set_service_ret = ret; @@ -1203,7 +1230,7 @@ goto_auto_guess: url_fseek(pb, pos, SEEK_SET); mpegts_scan_sdt(ts); - handle_packets(ts, MAX_SCAN_PACKETS); + handle_packets(ts, s->probesize); if (ts->nb_services <= 0) { /* no SDT found, we try to look at the PAT */ @@ -1217,7 +1244,7 @@ goto_auto_guess: url_fseek(pb, pos, SEEK_SET); mpegts_scan_pat(ts); - handle_packets(ts, MAX_SCAN_PACKETS); + handle_packets(ts, s->probesize); } if (ts->nb_services <= 0) { @@ -1232,7 +1259,7 @@ goto_auto_guess: service = ts->services[i]; sid = service->sid; #ifdef DEBUG_SI - printf("tuning to '%s'\n", service->name); + av_log(ts->stream, AV_LOG_DEBUG, "tuning to '%s'\n", service->name); #endif /* now find the info for the first service if we found any, @@ -1241,7 +1268,7 @@ goto_auto_guess: url_fseek(pb, pos, SEEK_SET); mpegts_set_service(ts, sid, set_service_cb, ts); - handle_packets(ts, MAX_SCAN_PACKETS); + handle_packets(ts, s->probesize); } /* if could not find service, exit */ @@ -1256,7 +1283,7 @@ goto_auto_guess: } #ifdef DEBUG_SI - printf("tuning done\n"); + av_log(ts->stream, AV_LOG_DEBUG, "tuning done\n"); #endif } s->ctx_flags |= AVFMTCTX_NOHEADER; @@ -1307,7 +1334,7 @@ goto_auto_guess: st->codec->bit_rate = s->bit_rate; st->start_time = ts->cur_pcr; #if 0 - printf("start=%0.3f pcr=%0.3f incr=%d\n", + av_log(ts->stream, AV_LOG_DEBUG, "start=%0.3f pcr=%0.3f incr=%d\n", st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr); #endif } @@ -1330,7 +1357,7 @@ static int mpegts_raw_read_packet(AVFormatContext *s, uint8_t pcr_buf[12]; if (av_new_packet(pkt, TS_PACKET_SIZE) < 0) - return -ENOMEM; + return AVERROR(ENOMEM); pkt->pos= url_ftell(&s->pb); ret = read_packet(&s->pb, pkt->data, ts->raw_packet_size); if (ret < 0) {