00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "avformat.h"
00022 #include "crc.h"
00023 #include "mpegts.h"
00024
00025
00026
00027
00028
00029 #define MAX_SCAN_PACKETS 32000
00030
00031
00032
00033 #define MAX_RESYNC_SIZE 4096
00034
00035 typedef struct PESContext PESContext;
00036
00037 static PESContext* add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid, int stream_type);
00038 static AVStream* new_pes_av_stream(PESContext *pes, uint32_t code);
00039 extern void av_set_program_name(AVProgram *program, char *provider_name, char *name);
00040 extern void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx);
00041
00042 enum MpegTSFilterType {
00043 MPEGTS_PES,
00044 MPEGTS_SECTION,
00045 };
00046
00047 typedef struct MpegTSFilter MpegTSFilter;
00048
00049 typedef void PESCallback(MpegTSFilter *f, const uint8_t *buf, int len, int is_start);
00050
00051 typedef struct MpegTSPESFilter {
00052 PESCallback *pes_cb;
00053 void *opaque;
00054 } MpegTSPESFilter;
00055
00056 typedef void SectionCallback(MpegTSFilter *f, const uint8_t *buf, int len);
00057
00058 typedef void SetServiceCallback(void *opaque, int ret);
00059
00060 typedef struct MpegTSSectionFilter {
00061 int section_index;
00062 int section_h_size;
00063 uint8_t *section_buf;
00064 int check_crc:1;
00065 int end_of_section_reached:1;
00066 SectionCallback *section_cb;
00067 void *opaque;
00068 } MpegTSSectionFilter;
00069
00070 struct MpegTSFilter {
00071 int pid;
00072 int last_cc;
00073 enum MpegTSFilterType type;
00074 union {
00075 MpegTSPESFilter pes_filter;
00076 MpegTSSectionFilter section_filter;
00077 } u;
00078 };
00079
00080 #define MAX_PIDS_PER_PROGRAM 64
00081 typedef struct {
00082 unsigned int id;
00083 unsigned int nb_pids;
00084 unsigned int pids[MAX_PIDS_PER_PROGRAM];
00085 } Program_t;
00086
00087 struct MpegTSContext {
00088
00089 AVFormatContext *stream;
00091 int raw_packet_size;
00093 int auto_guess;
00094
00096 int mpeg2ts_compute_pcr;
00097
00098 int64_t cur_pcr;
00099 int pcr_incr;
00101
00103 int stop_parse;
00105 AVPacket *pkt;
00106
00107
00108
00109
00111 unsigned int nb_prg;
00112 Program_t *prg;
00113
00114
00116 MpegTSFilter *pids[NB_PID_MAX];
00117 };
00118
00119
00120
00121 enum MpegTSState {
00122 MPEGTS_HEADER = 0,
00123 MPEGTS_PESHEADER_FILL,
00124 MPEGTS_PAYLOAD,
00125 MPEGTS_SKIP,
00126 };
00127
00128
00129 #define PES_START_SIZE 9
00130 #define MAX_PES_HEADER_SIZE (9 + 255)
00131
00132 struct PESContext {
00133 int pid;
00134 int pcr_pid;
00135 int stream_type;
00136 MpegTSContext *ts;
00137 AVFormatContext *stream;
00138 AVStream *st;
00139 enum MpegTSState state;
00140
00141 int data_index;
00142 int total_size;
00143 int pes_header_size;
00144 int64_t pts, dts;
00145 uint8_t header[MAX_PES_HEADER_SIZE];
00146 };
00147
00148 extern AVInputFormat mpegts_demuxer;
00149
00150 static void clear_program(MpegTSContext *ts, unsigned int programid)
00151 {
00152 int i;
00153
00154 for(i=0; i<ts->nb_prg; i++)
00155 if(ts->prg[i].id == programid)
00156 ts->prg[i].nb_pids = 0;
00157 }
00158
00159 static void clear_programs(MpegTSContext *ts)
00160 {
00161 av_freep(&ts->prg);
00162 ts->nb_prg=0;
00163 }
00164
00165 static void add_pat_entry(MpegTSContext *ts, unsigned int programid)
00166 {
00167 Program_t *p;
00168 void *tmp = av_realloc(ts->prg, (ts->nb_prg+1)*sizeof(Program_t));
00169 if(!tmp)
00170 return;
00171 ts->prg = tmp;
00172 p = &ts->prg[ts->nb_prg];
00173 p->id = programid;
00174 p->nb_pids = 0;
00175 ts->nb_prg++;
00176 }
00177
00178 static void add_pid_to_pmt(MpegTSContext *ts, unsigned int programid, unsigned int pid)
00179 {
00180 int i;
00181 Program_t *p = NULL;
00182 for(i=0; i<ts->nb_prg; i++) {
00183 if(ts->prg[i].id == programid) {
00184 p = &ts->prg[i];
00185 break;
00186 }
00187 }
00188 if(!p)
00189 return;
00190
00191 if(p->nb_pids >= MAX_PIDS_PER_PROGRAM)
00192 return;
00193 p->pids[p->nb_pids++] = pid;
00194 }
00195
00204 static int discard_pid(MpegTSContext *ts, unsigned int pid)
00205 {
00206 int i, j, k;
00207 int used = 0, discarded = 0;
00208 Program_t *p;
00209 for(i=0; i<ts->nb_prg; i++) {
00210 p = &ts->prg[i];
00211 for(j=0; j<p->nb_pids; j++) {
00212 if(p->pids[j] != pid)
00213 continue;
00214
00215 for(k=0; k<ts->stream->nb_programs; k++) {
00216 if(ts->stream->programs[k]->id == p->id) {
00217 if(ts->stream->programs[k]->discard == AVDISCARD_ALL)
00218 discarded++;
00219 else
00220 used++;
00221 }
00222 }
00223 }
00224 }
00225
00226 return (!used && discarded);
00227 }
00228
00233 static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1,
00234 const uint8_t *buf, int buf_size, int is_start)
00235 {
00236 MpegTSSectionFilter *tss = &tss1->u.section_filter;
00237 int len;
00238
00239 if (is_start) {
00240 memcpy(tss->section_buf, buf, buf_size);
00241 tss->section_index = buf_size;
00242 tss->section_h_size = -1;
00243 tss->end_of_section_reached = 0;
00244 } else {
00245 if (tss->end_of_section_reached)
00246 return;
00247 len = 4096 - tss->section_index;
00248 if (buf_size < len)
00249 len = buf_size;
00250 memcpy(tss->section_buf + tss->section_index, buf, len);
00251 tss->section_index += len;
00252 }
00253
00254
00255 if (tss->section_h_size == -1 && tss->section_index >= 3) {
00256 len = (AV_RB16(tss->section_buf + 1) & 0xfff) + 3;
00257 if (len > 4096)
00258 return;
00259 tss->section_h_size = len;
00260 }
00261
00262 if (tss->section_h_size != -1 && tss->section_index >= tss->section_h_size) {
00263 tss->end_of_section_reached = 1;
00264 if (!tss->check_crc ||
00265 av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1,
00266 tss->section_buf, tss->section_h_size) == 0)
00267 tss->section_cb(tss1, tss->section_buf, tss->section_h_size);
00268 }
00269 }
00270
00271 static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, unsigned int pid,
00272 SectionCallback *section_cb, void *opaque,
00273 int check_crc)
00274
00275 {
00276 MpegTSFilter *filter;
00277 MpegTSSectionFilter *sec;
00278
00279 #ifdef DEBUG_SI
00280 av_log(ts->stream, AV_LOG_DEBUG, "Filter: pid=0x%x\n", pid);
00281 #endif
00282 if (pid >= NB_PID_MAX || ts->pids[pid])
00283 return NULL;
00284 filter = av_mallocz(sizeof(MpegTSFilter));
00285 if (!filter)
00286 return NULL;
00287 ts->pids[pid] = filter;
00288 filter->type = MPEGTS_SECTION;
00289 filter->pid = pid;
00290 filter->last_cc = -1;
00291 sec = &filter->u.section_filter;
00292 sec->section_cb = section_cb;
00293 sec->opaque = opaque;
00294 sec->section_buf = av_malloc(MAX_SECTION_SIZE);
00295 sec->check_crc = check_crc;
00296 if (!sec->section_buf) {
00297 av_free(filter);
00298 return NULL;
00299 }
00300 return filter;
00301 }
00302
00303 static MpegTSFilter *mpegts_open_pes_filter(MpegTSContext *ts, unsigned int pid,
00304 PESCallback *pes_cb,
00305 void *opaque)
00306 {
00307 MpegTSFilter *filter;
00308 MpegTSPESFilter *pes;
00309
00310 if (pid >= NB_PID_MAX || ts->pids[pid])
00311 return NULL;
00312 filter = av_mallocz(sizeof(MpegTSFilter));
00313 if (!filter)
00314 return NULL;
00315 ts->pids[pid] = filter;
00316 filter->type = MPEGTS_PES;
00317 filter->pid = pid;
00318 filter->last_cc = -1;
00319 pes = &filter->u.pes_filter;
00320 pes->pes_cb = pes_cb;
00321 pes->opaque = opaque;
00322 return filter;
00323 }
00324
00325 static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter)
00326 {
00327 int pid;
00328
00329 pid = filter->pid;
00330 if (filter->type == MPEGTS_SECTION)
00331 av_freep(&filter->u.section_filter.section_buf);
00332 else if (filter->type == MPEGTS_PES)
00333 av_freep(&filter->u.pes_filter.opaque);
00334
00335 av_free(filter);
00336 ts->pids[pid] = NULL;
00337 }
00338
00339 static int analyze(const uint8_t *buf, int size, int packet_size, int *index){
00340 int stat[packet_size];
00341 int i;
00342 int x=0;
00343 int best_score=0;
00344
00345 memset(stat, 0, packet_size*sizeof(int));
00346
00347 for(x=i=0; i<size; i++){
00348 if(buf[i] == 0x47){
00349 stat[x]++;
00350 if(stat[x] > best_score){
00351 best_score= stat[x];
00352 if(index) *index= x;
00353 }
00354 }
00355
00356 x++;
00357 if(x == packet_size) x= 0;
00358 }
00359
00360 return best_score;
00361 }
00362
00363
00364 static int get_packet_size(const uint8_t *buf, int size)
00365 {
00366 int score, fec_score, dvhs_score;
00367
00368 if (size < (TS_FEC_PACKET_SIZE * 5 + 1))
00369 return -1;
00370
00371 score = analyze(buf, size, TS_PACKET_SIZE, NULL);
00372 dvhs_score = analyze(buf, size, TS_DVHS_PACKET_SIZE, NULL);
00373 fec_score= analyze(buf, size, TS_FEC_PACKET_SIZE, NULL);
00374
00375
00376 if (score > fec_score && score > dvhs_score) return TS_PACKET_SIZE;
00377 else if(dvhs_score > score && dvhs_score > fec_score) return TS_DVHS_PACKET_SIZE;
00378 else if(score < fec_score && dvhs_score < fec_score) return TS_FEC_PACKET_SIZE;
00379 else return -1;
00380 }
00381
00382 typedef struct SectionHeader {
00383 uint8_t tid;
00384 uint16_t id;
00385 uint8_t version;
00386 uint8_t sec_num;
00387 uint8_t last_sec_num;
00388 } SectionHeader;
00389
00390 static inline int get8(const uint8_t **pp, const uint8_t *p_end)
00391 {
00392 const uint8_t *p;
00393 int c;
00394
00395 p = *pp;
00396 if (p >= p_end)
00397 return -1;
00398 c = *p++;
00399 *pp = p;
00400 return c;
00401 }
00402
00403 static inline int get16(const uint8_t **pp, const uint8_t *p_end)
00404 {
00405 const uint8_t *p;
00406 int c;
00407
00408 p = *pp;
00409 if ((p + 1) >= p_end)
00410 return -1;
00411 c = AV_RB16(p);
00412 p += 2;
00413 *pp = p;
00414 return c;
00415 }
00416
00417
00418 static char *getstr8(const uint8_t **pp, const uint8_t *p_end)
00419 {
00420 int len;
00421 const uint8_t *p;
00422 char *str;
00423
00424 p = *pp;
00425 len = get8(&p, p_end);
00426 if (len < 0)
00427 return NULL;
00428 if ((p + len) > p_end)
00429 return NULL;
00430 str = av_malloc(len + 1);
00431 if (!str)
00432 return NULL;
00433 memcpy(str, p, len);
00434 str[len] = '\0';
00435 p += len;
00436 *pp = p;
00437 return str;
00438 }
00439
00440 static int parse_section_header(SectionHeader *h,
00441 const uint8_t **pp, const uint8_t *p_end)
00442 {
00443 int val;
00444
00445 val = get8(pp, p_end);
00446 if (val < 0)
00447 return -1;
00448 h->tid = val;
00449 *pp += 2;
00450 val = get16(pp, p_end);
00451 if (val < 0)
00452 return -1;
00453 h->id = val;
00454 val = get8(pp, p_end);
00455 if (val < 0)
00456 return -1;
00457 h->version = (val >> 1) & 0x1f;
00458 val = get8(pp, p_end);
00459 if (val < 0)
00460 return -1;
00461 h->sec_num = val;
00462 val = get8(pp, p_end);
00463 if (val < 0)
00464 return -1;
00465 h->last_sec_num = val;
00466 return 0;
00467 }
00468
00469
00470 static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
00471 {
00472 MpegTSContext *ts = filter->u.section_filter.opaque;
00473 SectionHeader h1, *h = &h1;
00474 PESContext *pes;
00475 AVStream *st;
00476 const uint8_t *p, *p_end, *desc_list_end, *desc_end;
00477 int program_info_length, pcr_pid, pid, stream_type;
00478 int desc_list_len, desc_len, desc_tag;
00479 int comp_page = 0, anc_page = 0;
00480 char language[4] = {0};
00481
00482 #ifdef DEBUG_SI
00483 av_log(ts->stream, AV_LOG_DEBUG, "PMT: len %i\n", section_len);
00484 av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len);
00485 #endif
00486 p_end = section + section_len - 4;
00487 p = section;
00488 if (parse_section_header(h, &p, p_end) < 0)
00489 return;
00490 #ifdef DEBUG_SI
00491 av_log(ts->stream, AV_LOG_DEBUG, "sid=0x%x sec_num=%d/%d\n",
00492 h->id, h->sec_num, h->last_sec_num);
00493 #endif
00494 if (h->tid != PMT_TID)
00495 return;
00496
00497 clear_program(ts, h->id);
00498 pcr_pid = get16(&p, p_end) & 0x1fff;
00499 if (pcr_pid < 0)
00500 return;
00501 add_pid_to_pmt(ts, h->id, pcr_pid);
00502 #ifdef DEBUG_SI
00503 av_log(ts->stream, AV_LOG_DEBUG, "pcr_pid=0x%x\n", pcr_pid);
00504 #endif
00505 program_info_length = get16(&p, p_end) & 0xfff;
00506 if (program_info_length < 0)
00507 return;
00508 p += program_info_length;
00509 if (p >= p_end)
00510 return;
00511 for(;;) {
00512 language[0] = 0;
00513 st = 0;
00514 stream_type = get8(&p, p_end);
00515 if (stream_type < 0)
00516 break;
00517 pid = get16(&p, p_end) & 0x1fff;
00518 if (pid < 0)
00519 break;
00520 desc_list_len = get16(&p, p_end) & 0xfff;
00521 if (desc_list_len < 0)
00522 break;
00523 desc_list_end = p + desc_list_len;
00524 if (desc_list_end > p_end)
00525 break;
00526 for(;;) {
00527 desc_tag = get8(&p, desc_list_end);
00528 if (desc_tag < 0)
00529 break;
00530 if (stream_type == STREAM_TYPE_PRIVATE_DATA) {
00531 if((desc_tag == 0x6A) || (desc_tag == 0x7A)) {
00532
00533 stream_type = STREAM_TYPE_AUDIO_AC3;
00534 } else if(desc_tag == 0x7B) {
00535
00536 stream_type = STREAM_TYPE_AUDIO_DTS;
00537 }
00538 }
00539 desc_len = get8(&p, desc_list_end);
00540 desc_end = p + desc_len;
00541 if (desc_end > desc_list_end)
00542 break;
00543 #ifdef DEBUG_SI
00544 av_log(ts->stream, AV_LOG_DEBUG, "tag: 0x%02x len=%d\n",
00545 desc_tag, desc_len);
00546 #endif
00547 switch(desc_tag) {
00548 case DVB_SUBT_DESCID:
00549 if (stream_type == STREAM_TYPE_PRIVATE_DATA)
00550 stream_type = STREAM_TYPE_SUBTITLE_DVB;
00551
00552 language[0] = get8(&p, desc_end);
00553 language[1] = get8(&p, desc_end);
00554 language[2] = get8(&p, desc_end);
00555 language[3] = 0;
00556 get8(&p, desc_end);
00557 comp_page = get16(&p, desc_end);
00558 anc_page = get16(&p, desc_end);
00559
00560 break;
00561 case 0x0a:
00562 language[0] = get8(&p, desc_end);
00563 language[1] = get8(&p, desc_end);
00564 language[2] = get8(&p, desc_end);
00565 language[3] = 0;
00566 break;
00567 default:
00568 break;
00569 }
00570 p = desc_end;
00571 }
00572 p = desc_list_end;
00573
00574 #ifdef DEBUG_SI
00575 av_log(ts->stream, AV_LOG_DEBUG, "stream_type=%d pid=0x%x\n",
00576 stream_type, pid);
00577 #endif
00578
00579
00580 switch(stream_type) {
00581 case STREAM_TYPE_AUDIO_MPEG1:
00582 case STREAM_TYPE_AUDIO_MPEG2:
00583 case STREAM_TYPE_VIDEO_MPEG1:
00584 case STREAM_TYPE_VIDEO_MPEG2:
00585 case STREAM_TYPE_VIDEO_MPEG4:
00586 case STREAM_TYPE_VIDEO_H264:
00587 case STREAM_TYPE_VIDEO_VC1:
00588 case STREAM_TYPE_AUDIO_AAC:
00589 case STREAM_TYPE_AUDIO_AC3:
00590 case STREAM_TYPE_AUDIO_DTS:
00591 case STREAM_TYPE_SUBTITLE_DVB:
00592 if(ts->pids[pid] && ts->pids[pid]->type == MPEGTS_PES){
00593 pes= ts->pids[pid]->u.pes_filter.opaque;
00594 st= pes->st;
00595 }else{
00596 if (ts->pids[pid]) mpegts_close_filter(ts, ts->pids[pid]);
00597 pes = add_pes_stream(ts, pid, pcr_pid, stream_type);
00598 if (pes)
00599 st = new_pes_av_stream(pes, 0);
00600 }
00601 add_pid_to_pmt(ts, h->id, pid);
00602 if(st)
00603 av_program_add_stream_index(ts->stream, h->id, st->index);
00604 break;
00605 default:
00606
00607 break;
00608 }
00609
00610 if (st) {
00611 if (language[0] != 0) {
00612 memcpy(st->language, language, 4);
00613 }
00614
00615 if (stream_type == STREAM_TYPE_SUBTITLE_DVB) {
00616 st->codec->sub_id = (anc_page << 16) | comp_page;
00617 }
00618 }
00619 }
00620
00621 ts->stop_parse++;
00622 mpegts_close_filter(ts, filter);
00623 }
00624
00625 static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
00626 {
00627 MpegTSContext *ts = filter->u.section_filter.opaque;
00628 SectionHeader h1, *h = &h1;
00629 const uint8_t *p, *p_end;
00630 int sid, pmt_pid;
00631
00632 #ifdef DEBUG_SI
00633 av_log(ts->stream, AV_LOG_DEBUG, "PAT:\n");
00634 av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len);
00635 #endif
00636 p_end = section + section_len - 4;
00637 p = section;
00638 if (parse_section_header(h, &p, p_end) < 0)
00639 return;
00640 if (h->tid != PAT_TID)
00641 return;
00642
00643 clear_programs(ts);
00644 for(;;) {
00645 sid = get16(&p, p_end);
00646 if (sid < 0)
00647 break;
00648 pmt_pid = get16(&p, p_end) & 0x1fff;
00649 if (pmt_pid < 0)
00650 break;
00651 #ifdef DEBUG_SI
00652 av_log(ts->stream, AV_LOG_DEBUG, "sid=0x%x pid=0x%x\n", sid, pmt_pid);
00653 #endif
00654 if (sid == 0x0000) {
00655
00656 } else {
00657 av_new_program(ts->stream, sid);
00658 ts->stop_parse--;
00659 mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1);
00660 add_pat_entry(ts, sid);
00661 add_pid_to_pmt(ts, sid, 0);
00662 add_pid_to_pmt(ts, sid, pmt_pid);
00663 }
00664 }
00665
00666 ts->stop_parse++;
00667
00668 mpegts_close_filter(ts, filter);
00669 }
00670
00671 static void mpegts_set_service(MpegTSContext *ts)
00672 {
00673 mpegts_open_section_filter(ts, PAT_PID,
00674 pat_cb, ts, 1);
00675 }
00676
00677 static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
00678 {
00679 MpegTSContext *ts = filter->u.section_filter.opaque;
00680 SectionHeader h1, *h = &h1;
00681 const uint8_t *p, *p_end, *desc_list_end, *desc_end;
00682 int onid, val, sid, desc_list_len, desc_tag, desc_len, service_type;
00683 char *name, *provider_name;
00684
00685 #ifdef DEBUG_SI
00686 av_log(ts->stream, AV_LOG_DEBUG, "SDT:\n");
00687 av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len);
00688 #endif
00689
00690 p_end = section + section_len - 4;
00691 p = section;
00692 if (parse_section_header(h, &p, p_end) < 0)
00693 return;
00694 if (h->tid != SDT_TID)
00695 return;
00696 onid = get16(&p, p_end);
00697 if (onid < 0)
00698 return;
00699 val = get8(&p, p_end);
00700 if (val < 0)
00701 return;
00702 for(;;) {
00703 sid = get16(&p, p_end);
00704 if (sid < 0)
00705 break;
00706 val = get8(&p, p_end);
00707 if (val < 0)
00708 break;
00709 desc_list_len = get16(&p, p_end) & 0xfff;
00710 if (desc_list_len < 0)
00711 break;
00712 desc_list_end = p + desc_list_len;
00713 if (desc_list_end > p_end)
00714 break;
00715 for(;;) {
00716 desc_tag = get8(&p, desc_list_end);
00717 if (desc_tag < 0)
00718 break;
00719 desc_len = get8(&p, desc_list_end);
00720 desc_end = p + desc_len;
00721 if (desc_end > desc_list_end)
00722 break;
00723 #ifdef DEBUG_SI
00724 av_log(ts->stream, AV_LOG_DEBUG, "tag: 0x%02x len=%d\n",
00725 desc_tag, desc_len);
00726 #endif
00727 switch(desc_tag) {
00728 case 0x48:
00729 service_type = get8(&p, p_end);
00730 if (service_type < 0)
00731 break;
00732 provider_name = getstr8(&p, p_end);
00733 if (!provider_name)
00734 break;
00735 name = getstr8(&p, p_end);
00736 if (name) {
00737 AVProgram *program = av_new_program(ts->stream, sid);
00738 if(program)
00739 av_set_program_name(program, provider_name, name);
00740 }
00741 break;
00742 default:
00743 break;
00744 }
00745 p = desc_end;
00746 }
00747 p = desc_list_end;
00748 }
00749 }
00750
00751
00752 static void mpegts_scan_sdt(MpegTSContext *ts)
00753 {
00754 mpegts_open_section_filter(ts, SDT_PID,
00755 sdt_cb, ts, 1);
00756 }
00757
00758 static int64_t get_pts(const uint8_t *p)
00759 {
00760 int64_t pts = (int64_t)((p[0] >> 1) & 0x07) << 30;
00761 pts |= (AV_RB16(p + 1) >> 1) << 15;
00762 pts |= AV_RB16(p + 3) >> 1;
00763 return pts;
00764 }
00765
00766
00767 static void mpegts_push_data(MpegTSFilter *filter,
00768 const uint8_t *buf, int buf_size, int is_start)
00769 {
00770 PESContext *pes = filter->u.pes_filter.opaque;
00771 MpegTSContext *ts = pes->ts;
00772 const uint8_t *p;
00773 int len, code;
00774
00775 if(!ts->pkt)
00776 return;
00777
00778 if (is_start) {
00779 pes->state = MPEGTS_HEADER;
00780 pes->data_index = 0;
00781 }
00782 p = buf;
00783 while (buf_size > 0) {
00784 switch(pes->state) {
00785 case MPEGTS_HEADER:
00786 len = PES_START_SIZE - pes->data_index;
00787 if (len > buf_size)
00788 len = buf_size;
00789 memcpy(pes->header + pes->data_index, p, len);
00790 pes->data_index += len;
00791 p += len;
00792 buf_size -= len;
00793 if (pes->data_index == PES_START_SIZE) {
00794
00795
00796 #if 0
00797 av_hex_dump_log(pes->stream, AV_LOG_DEBUG, pes->header, pes->data_index);
00798 #endif
00799 if (pes->header[0] == 0x00 && pes->header[1] == 0x00 &&
00800 pes->header[2] == 0x01) {
00801
00802 code = pes->header[3] | 0x100;
00803 if (!((code >= 0x1c0 && code <= 0x1df) ||
00804 (code >= 0x1e0 && code <= 0x1ef) ||
00805 (code == 0x1bd) || (code == 0x1fd)))
00806 goto skip;
00807 if (!pes->st) {
00808
00809 new_pes_av_stream(pes, code);
00810 }
00811 pes->state = MPEGTS_PESHEADER_FILL;
00812 pes->total_size = AV_RB16(pes->header + 4);
00813
00814
00815 if (pes->total_size)
00816 pes->total_size += 6;
00817 pes->pes_header_size = pes->header[8] + 9;
00818 } else {
00819
00820
00821 skip:
00822 pes->state = MPEGTS_SKIP;
00823 continue;
00824 }
00825 }
00826 break;
00827
00828
00829 case MPEGTS_PESHEADER_FILL:
00830 len = pes->pes_header_size - pes->data_index;
00831 if (len > buf_size)
00832 len = buf_size;
00833 memcpy(pes->header + pes->data_index, p, len);
00834 pes->data_index += len;
00835 p += len;
00836 buf_size -= len;
00837 if (pes->data_index == pes->pes_header_size) {
00838 const uint8_t *r;
00839 unsigned int flags;
00840
00841 flags = pes->header[7];
00842 r = pes->header + 9;
00843 pes->pts = AV_NOPTS_VALUE;
00844 pes->dts = AV_NOPTS_VALUE;
00845 if ((flags & 0xc0) == 0x80) {
00846 pes->pts = get_pts(r);
00847 r += 5;
00848 } else if ((flags & 0xc0) == 0xc0) {
00849 pes->pts = get_pts(r);
00850 r += 5;
00851 pes->dts = get_pts(r);
00852 r += 5;
00853 }
00854
00855 pes->state = MPEGTS_PAYLOAD;
00856 }
00857 break;
00858 case MPEGTS_PAYLOAD:
00859 if (pes->total_size) {
00860 len = pes->total_size - pes->data_index;
00861 if (len > buf_size)
00862 len = buf_size;
00863 } else {
00864 len = buf_size;
00865 }
00866 if (len > 0) {
00867 AVPacket *pkt = ts->pkt;
00868 if (pes->st && av_new_packet(pkt, len) == 0) {
00869 memcpy(pkt->data, p, len);
00870 pkt->stream_index = pes->st->index;
00871 pkt->pts = pes->pts;
00872 pkt->dts = pes->dts;
00873
00874 pes->pts = AV_NOPTS_VALUE;
00875 pes->dts = AV_NOPTS_VALUE;
00876 ts->stop_parse = 1;
00877 return;
00878 }
00879 }
00880 buf_size = 0;
00881 break;
00882 case MPEGTS_SKIP:
00883 buf_size = 0;
00884 break;
00885 }
00886 }
00887 }
00888
00889 static AVStream* new_pes_av_stream(PESContext *pes, uint32_t code)
00890 {
00891 AVStream *st;
00892 int codec_type, codec_id;
00893
00894 switch(pes->stream_type){
00895 case STREAM_TYPE_AUDIO_MPEG1:
00896 case STREAM_TYPE_AUDIO_MPEG2:
00897 codec_type = CODEC_TYPE_AUDIO;
00898 codec_id = CODEC_ID_MP3;
00899 break;
00900 case STREAM_TYPE_VIDEO_MPEG1:
00901 case STREAM_TYPE_VIDEO_MPEG2:
00902 codec_type = CODEC_TYPE_VIDEO;
00903 codec_id = CODEC_ID_MPEG2VIDEO;
00904 break;
00905 case STREAM_TYPE_VIDEO_MPEG4:
00906 codec_type = CODEC_TYPE_VIDEO;
00907 codec_id = CODEC_ID_MPEG4;
00908 break;
00909 case STREAM_TYPE_VIDEO_H264:
00910 codec_type = CODEC_TYPE_VIDEO;
00911 codec_id = CODEC_ID_H264;
00912 break;
00913 case STREAM_TYPE_VIDEO_VC1:
00914 codec_type = CODEC_TYPE_VIDEO;
00915 codec_id = CODEC_ID_VC1;
00916 break;
00917 case STREAM_TYPE_AUDIO_AAC:
00918 codec_type = CODEC_TYPE_AUDIO;
00919 codec_id = CODEC_ID_AAC;
00920 break;
00921 case STREAM_TYPE_AUDIO_AC3:
00922 codec_type = CODEC_TYPE_AUDIO;
00923 codec_id = CODEC_ID_AC3;
00924 break;
00925 case STREAM_TYPE_AUDIO_DTS:
00926 codec_type = CODEC_TYPE_AUDIO;
00927 codec_id = CODEC_ID_DTS;
00928 break;
00929 case STREAM_TYPE_SUBTITLE_DVB:
00930 codec_type = CODEC_TYPE_SUBTITLE;
00931 codec_id = CODEC_ID_DVB_SUBTITLE;
00932 break;
00933 default:
00934 if (code >= 0x1c0 && code <= 0x1df) {
00935 codec_type = CODEC_TYPE_AUDIO;
00936 codec_id = CODEC_ID_MP2;
00937 } else if (code == 0x1bd) {
00938 codec_type = CODEC_TYPE_AUDIO;
00939 codec_id = CODEC_ID_AC3;
00940 } else {
00941 codec_type = CODEC_TYPE_VIDEO;
00942 codec_id = CODEC_ID_MPEG1VIDEO;
00943 }
00944 break;
00945 }
00946 st = av_new_stream(pes->stream, pes->pid);
00947 if (st) {
00948 av_set_pts_info(st, 33, 1, 90000);
00949 st->priv_data = pes;
00950 st->codec->codec_type = codec_type;
00951 st->codec->codec_id = codec_id;
00952 st->need_parsing = AVSTREAM_PARSE_FULL;
00953 pes->st = st;
00954 }
00955 return st;
00956 }
00957
00958
00959 static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid, int stream_type)
00960 {
00961 MpegTSFilter *tss;
00962 PESContext *pes;
00963
00964
00965 pes = av_mallocz(sizeof(PESContext));
00966 if (!pes)
00967 return 0;
00968 pes->ts = ts;
00969 pes->stream = ts->stream;
00970 pes->pid = pid;
00971 pes->pcr_pid = pcr_pid;
00972 pes->stream_type = stream_type;
00973 tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes);
00974 if (!tss) {
00975 av_free(pes);
00976 return 0;
00977 }
00978 return pes;
00979 }
00980
00981
00982 static void handle_packet(MpegTSContext *ts, const uint8_t *packet)
00983 {
00984 AVFormatContext *s = ts->stream;
00985 MpegTSFilter *tss;
00986 int len, pid, cc, cc_ok, afc, is_start;
00987 const uint8_t *p, *p_end;
00988
00989 pid = AV_RB16(packet + 1) & 0x1fff;
00990 if(pid && discard_pid(ts, pid))
00991 return;
00992 is_start = packet[1] & 0x40;
00993 tss = ts->pids[pid];
00994 if (ts->auto_guess && tss == NULL && is_start) {
00995 add_pes_stream(ts, pid, -1, 0);
00996 tss = ts->pids[pid];
00997 }
00998 if (!tss)
00999 return;
01000
01001
01002 cc = (packet[3] & 0xf);
01003 cc_ok = (tss->last_cc < 0) || ((((tss->last_cc + 1) & 0x0f) == cc));
01004 tss->last_cc = cc;
01005
01006
01007 afc = (packet[3] >> 4) & 3;
01008 p = packet + 4;
01009 if (afc == 0)
01010 return;
01011 if (afc == 2)
01012 return;
01013 if (afc == 3) {
01014
01015 p += p[0] + 1;
01016 }
01017
01018 p_end = packet + TS_PACKET_SIZE;
01019 if (p >= p_end)
01020 return;
01021
01022 if (tss->type == MPEGTS_SECTION) {
01023 if (is_start) {
01024
01025 len = *p++;
01026 if (p + len > p_end)
01027 return;
01028 if (len && cc_ok) {
01029
01030 write_section_data(s, tss,
01031 p, len, 0);
01032
01033 if (!ts->pids[pid])
01034 return;
01035 }
01036 p += len;
01037 if (p < p_end) {
01038 write_section_data(s, tss,
01039 p, p_end - p, 1);
01040 }
01041 } else {
01042 if (cc_ok) {
01043 write_section_data(s, tss,
01044 p, p_end - p, 0);
01045 }
01046 }
01047 } else {
01048 tss->u.pes_filter.pes_cb(tss,
01049 p, p_end - p, is_start);
01050 }
01051 }
01052
01053
01054
01055 static int mpegts_resync(ByteIOContext *pb)
01056 {
01057 int c, i;
01058
01059 for(i = 0;i < MAX_RESYNC_SIZE; i++) {
01060 c = url_fgetc(pb);
01061 if (c < 0)
01062 return -1;
01063 if (c == 0x47) {
01064 url_fseek(pb, -1, SEEK_CUR);
01065 return 0;
01066 }
01067 }
01068
01069 return -1;
01070 }
01071
01072
01073 static int read_packet(ByteIOContext *pb, uint8_t *buf, int raw_packet_size)
01074 {
01075 int skip, len;
01076
01077 for(;;) {
01078 len = get_buffer(pb, buf, TS_PACKET_SIZE);
01079 if (len != TS_PACKET_SIZE)
01080 return AVERROR(EIO);
01081
01082 if (buf[0] != 0x47) {
01083
01084 url_fseek(pb, -TS_PACKET_SIZE, SEEK_CUR);
01085 if (mpegts_resync(pb) < 0)
01086 return AVERROR_INVALIDDATA;
01087 else
01088 continue;
01089 } else {
01090 skip = raw_packet_size - TS_PACKET_SIZE;
01091 if (skip > 0)
01092 url_fskip(pb, skip);
01093 break;
01094 }
01095 }
01096 return 0;
01097 }
01098
01099 static int handle_packets(MpegTSContext *ts, int nb_packets)
01100 {
01101 AVFormatContext *s = ts->stream;
01102 ByteIOContext *pb = s->pb;
01103 uint8_t packet[TS_PACKET_SIZE];
01104 int packet_num, ret;
01105
01106 ts->stop_parse = 0;
01107 packet_num = 0;
01108 for(;;) {
01109 if (ts->stop_parse>0)
01110 break;
01111 packet_num++;
01112 if (nb_packets != 0 && packet_num >= nb_packets)
01113 break;
01114 ret = read_packet(pb, packet, ts->raw_packet_size);
01115 if (ret != 0)
01116 return ret;
01117 handle_packet(ts, packet);
01118 }
01119 return 0;
01120 }
01121
01122 static int mpegts_probe(AVProbeData *p)
01123 {
01124 #if 1
01125 const int size= p->buf_size;
01126 int score, fec_score, dvhs_score;
01127 #define CHECK_COUNT 10
01128
01129 if (size < (TS_FEC_PACKET_SIZE * CHECK_COUNT))
01130 return -1;
01131
01132 score = analyze(p->buf, TS_PACKET_SIZE *CHECK_COUNT, TS_PACKET_SIZE, NULL);
01133 dvhs_score = analyze(p->buf, TS_DVHS_PACKET_SIZE *CHECK_COUNT, TS_DVHS_PACKET_SIZE, NULL);
01134 fec_score= analyze(p->buf, TS_FEC_PACKET_SIZE*CHECK_COUNT, TS_FEC_PACKET_SIZE, NULL);
01135
01136
01137
01138 if (score > fec_score && score > dvhs_score && score > 6) return AVPROBE_SCORE_MAX + score - CHECK_COUNT;
01139 else if(dvhs_score > score && dvhs_score > fec_score && dvhs_score > 6) return AVPROBE_SCORE_MAX + dvhs_score - CHECK_COUNT;
01140 else if( fec_score > 6) return AVPROBE_SCORE_MAX + fec_score - CHECK_COUNT;
01141 else return -1;
01142 #else
01143
01144 if (match_ext(p->filename, "ts"))
01145 return AVPROBE_SCORE_MAX;
01146 else
01147 return 0;
01148 #endif
01149 }
01150
01151
01152
01153 static int parse_pcr(int64_t *ppcr_high, int *ppcr_low,
01154 const uint8_t *packet)
01155 {
01156 int afc, len, flags;
01157 const uint8_t *p;
01158 unsigned int v;
01159
01160 afc = (packet[3] >> 4) & 3;
01161 if (afc <= 1)
01162 return -1;
01163 p = packet + 4;
01164 len = p[0];
01165 p++;
01166 if (len == 0)
01167 return -1;
01168 flags = *p++;
01169 len--;
01170 if (!(flags & 0x10))
01171 return -1;
01172 if (len < 6)
01173 return -1;
01174 v = AV_RB32(p);
01175 *ppcr_high = ((int64_t)v << 1) | (p[4] >> 7);
01176 *ppcr_low = ((p[4] & 1) << 8) | p[5];
01177 return 0;
01178 }
01179
01180 static int mpegts_read_header(AVFormatContext *s,
01181 AVFormatParameters *ap)
01182 {
01183 MpegTSContext *ts = s->priv_data;
01184 ByteIOContext *pb = s->pb;
01185 uint8_t buf[1024];
01186 int len;
01187 int64_t pos;
01188
01189 if (ap) {
01190 ts->mpeg2ts_compute_pcr = ap->mpeg2ts_compute_pcr;
01191 if(ap->mpeg2ts_raw){
01192 av_log(s, AV_LOG_ERROR, "use mpegtsraw_demuxer!\n");
01193 return -1;
01194 }
01195 }
01196
01197
01198 pos = url_ftell(pb);
01199 len = get_buffer(pb, buf, sizeof(buf));
01200 if (len != sizeof(buf))
01201 goto fail;
01202 ts->raw_packet_size = get_packet_size(buf, sizeof(buf));
01203 if (ts->raw_packet_size <= 0)
01204 goto fail;
01205 ts->stream = s;
01206 ts->auto_guess = 0;
01207
01208 if (s->iformat == &mpegts_demuxer) {
01209
01210
01211
01212 url_fseek(pb, pos, SEEK_SET);
01213 mpegts_scan_sdt(ts);
01214
01215 mpegts_set_service(ts);
01216
01217 handle_packets(ts, s->probesize);
01218
01219
01220 ts->auto_guess = 1;
01221
01222 #ifdef DEBUG_SI
01223 av_log(ts->stream, AV_LOG_DEBUG, "tuning done\n");
01224 #endif
01225 s->ctx_flags |= AVFMTCTX_NOHEADER;
01226 } else {
01227 AVStream *st;
01228 int pcr_pid, pid, nb_packets, nb_pcrs, ret, pcr_l;
01229 int64_t pcrs[2], pcr_h;
01230 int packet_count[2];
01231 uint8_t packet[TS_PACKET_SIZE];
01232
01233
01234
01235 st = av_new_stream(s, 0);
01236 if (!st)
01237 goto fail;
01238 av_set_pts_info(st, 60, 1, 27000000);
01239 st->codec->codec_type = CODEC_TYPE_DATA;
01240 st->codec->codec_id = CODEC_ID_MPEG2TS;
01241
01242
01243 pcr_pid = -1;
01244 nb_pcrs = 0;
01245 nb_packets = 0;
01246 for(;;) {
01247 ret = read_packet(s->pb, packet, ts->raw_packet_size);
01248 if (ret < 0)
01249 return -1;
01250 pid = AV_RB16(packet + 1) & 0x1fff;
01251 if ((pcr_pid == -1 || pcr_pid == pid) &&
01252 parse_pcr(&pcr_h, &pcr_l, packet) == 0) {
01253 pcr_pid = pid;
01254 packet_count[nb_pcrs] = nb_packets;
01255 pcrs[nb_pcrs] = pcr_h * 300 + pcr_l;
01256 nb_pcrs++;
01257 if (nb_pcrs >= 2)
01258 break;
01259 }
01260 nb_packets++;
01261 }
01262
01263
01264
01265 ts->pcr_incr = (pcrs[1] - pcrs[0]) / (packet_count[1] - packet_count[0]);
01266 ts->cur_pcr = pcrs[0] - ts->pcr_incr * packet_count[0];
01267 s->bit_rate = (TS_PACKET_SIZE * 8) * 27e6 / ts->pcr_incr;
01268 st->codec->bit_rate = s->bit_rate;
01269 st->start_time = ts->cur_pcr;
01270 #if 0
01271 av_log(ts->stream, AV_LOG_DEBUG, "start=%0.3f pcr=%0.3f incr=%d\n",
01272 st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr);
01273 #endif
01274 }
01275
01276 url_fseek(pb, pos, SEEK_SET);
01277 return 0;
01278 fail:
01279 return -1;
01280 }
01281
01282 #define MAX_PACKET_READAHEAD ((128 * 1024) / 188)
01283
01284 static int mpegts_raw_read_packet(AVFormatContext *s,
01285 AVPacket *pkt)
01286 {
01287 MpegTSContext *ts = s->priv_data;
01288 int ret, i;
01289 int64_t pcr_h, next_pcr_h, pos;
01290 int pcr_l, next_pcr_l;
01291 uint8_t pcr_buf[12];
01292
01293 if (av_new_packet(pkt, TS_PACKET_SIZE) < 0)
01294 return AVERROR(ENOMEM);
01295 pkt->pos= url_ftell(s->pb);
01296 ret = read_packet(s->pb, pkt->data, ts->raw_packet_size);
01297 if (ret < 0) {
01298 av_free_packet(pkt);
01299 return ret;
01300 }
01301 if (ts->mpeg2ts_compute_pcr) {
01302
01303 if (parse_pcr(&pcr_h, &pcr_l, pkt->data) == 0) {
01304
01305 pos = url_ftell(s->pb);
01306 for(i = 0; i < MAX_PACKET_READAHEAD; i++) {
01307 url_fseek(s->pb, pos + i * ts->raw_packet_size, SEEK_SET);
01308 get_buffer(s->pb, pcr_buf, 12);
01309 if (parse_pcr(&next_pcr_h, &next_pcr_l, pcr_buf) == 0) {
01310
01311 ts->pcr_incr = ((next_pcr_h - pcr_h) * 300 + (next_pcr_l - pcr_l)) /
01312 (i + 1);
01313 break;
01314 }
01315 }
01316 url_fseek(s->pb, pos, SEEK_SET);
01317
01318 ts->cur_pcr = pcr_h * 300 + pcr_l;
01319 }
01320 pkt->pts = ts->cur_pcr;
01321 pkt->duration = ts->pcr_incr;
01322 ts->cur_pcr += ts->pcr_incr;
01323 }
01324 pkt->stream_index = 0;
01325 return 0;
01326 }
01327
01328 static int mpegts_read_packet(AVFormatContext *s,
01329 AVPacket *pkt)
01330 {
01331 MpegTSContext *ts = s->priv_data;
01332
01333 ts->pkt = pkt;
01334 return handle_packets(ts, 0);
01335 }
01336
01337 static int mpegts_read_close(AVFormatContext *s)
01338 {
01339 MpegTSContext *ts = s->priv_data;
01340 int i;
01341 for(i=0;i<NB_PID_MAX;i++)
01342 if (ts->pids[i]) mpegts_close_filter(ts, ts->pids[i]);
01343
01344 return 0;
01345 }
01346
01347 static int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index,
01348 int64_t *ppos, int64_t pos_limit)
01349 {
01350 MpegTSContext *ts = s->priv_data;
01351 int64_t pos, timestamp;
01352 uint8_t buf[TS_PACKET_SIZE];
01353 int pcr_l, pcr_pid = ((PESContext*)s->streams[stream_index]->priv_data)->pcr_pid;
01354 const int find_next= 1;
01355 pos = ((*ppos + ts->raw_packet_size - 1) / ts->raw_packet_size) * ts->raw_packet_size;
01356 if (find_next) {
01357 for(;;) {
01358 url_fseek(s->pb, pos, SEEK_SET);
01359 if (get_buffer(s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
01360 return AV_NOPTS_VALUE;
01361 if ((pcr_pid < 0 || (AV_RB16(buf + 1) & 0x1fff) == pcr_pid) &&
01362 parse_pcr(×tamp, &pcr_l, buf) == 0) {
01363 break;
01364 }
01365 pos += ts->raw_packet_size;
01366 }
01367 } else {
01368 for(;;) {
01369 pos -= ts->raw_packet_size;
01370 if (pos < 0)
01371 return AV_NOPTS_VALUE;
01372 url_fseek(s->pb, pos, SEEK_SET);
01373 if (get_buffer(s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
01374 return AV_NOPTS_VALUE;
01375 if ((pcr_pid < 0 || (AV_RB16(buf + 1) & 0x1fff) == pcr_pid) &&
01376 parse_pcr(×tamp, &pcr_l, buf) == 0) {
01377 break;
01378 }
01379 }
01380 }
01381 *ppos = pos;
01382
01383 return timestamp;
01384 }
01385
01386 static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){
01387 MpegTSContext *ts = s->priv_data;
01388 uint8_t buf[TS_PACKET_SIZE];
01389 int64_t pos;
01390
01391 if(av_seek_frame_binary(s, stream_index, target_ts, flags) < 0)
01392 return -1;
01393
01394 pos= url_ftell(s->pb);
01395
01396 for(;;) {
01397 url_fseek(s->pb, pos, SEEK_SET);
01398 if (get_buffer(s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
01399 return -1;
01400
01401 if(buf[1] & 0x40) break;
01402 pos += ts->raw_packet_size;
01403 }
01404 url_fseek(s->pb, pos, SEEK_SET);
01405
01406 return 0;
01407 }
01408
01409
01410
01411
01412 MpegTSContext *mpegts_parse_open(AVFormatContext *s)
01413 {
01414 MpegTSContext *ts;
01415
01416 ts = av_mallocz(sizeof(MpegTSContext));
01417 if (!ts)
01418 return NULL;
01419
01420 ts->raw_packet_size = TS_PACKET_SIZE;
01421 ts->stream = s;
01422 ts->auto_guess = 1;
01423 return ts;
01424 }
01425
01426
01427
01428 int mpegts_parse_packet(MpegTSContext *ts, AVPacket *pkt,
01429 const uint8_t *buf, int len)
01430 {
01431 int len1;
01432
01433 len1 = len;
01434 ts->pkt = pkt;
01435 ts->stop_parse = 0;
01436 for(;;) {
01437 if (ts->stop_parse>0)
01438 break;
01439 if (len < TS_PACKET_SIZE)
01440 return -1;
01441 if (buf[0] != 0x47) {
01442 buf++;
01443 len--;
01444 } else {
01445 handle_packet(ts, buf);
01446 buf += TS_PACKET_SIZE;
01447 len -= TS_PACKET_SIZE;
01448 }
01449 }
01450 return len1 - len;
01451 }
01452
01453 void mpegts_parse_close(MpegTSContext *ts)
01454 {
01455 int i;
01456
01457 for(i=0;i<NB_PID_MAX;i++)
01458 av_free(ts->pids[i]);
01459 av_free(ts);
01460 }
01461
01462 AVInputFormat mpegts_demuxer = {
01463 "mpegts",
01464 "MPEG2 transport stream format",
01465 sizeof(MpegTSContext),
01466 mpegts_probe,
01467 mpegts_read_header,
01468 mpegts_read_packet,
01469 mpegts_read_close,
01470 read_seek,
01471 mpegts_get_pcr,
01472 .flags = AVFMT_SHOW_IDS,
01473 };
01474
01475 AVInputFormat mpegtsraw_demuxer = {
01476 "mpegtsraw",
01477 "MPEG2 raw transport stream format",
01478 sizeof(MpegTSContext),
01479 mpegts_probe,
01480 mpegts_read_header,
01481 mpegts_raw_read_packet,
01482 mpegts_read_close,
01483 read_seek,
01484 mpegts_get_pcr,
01485 .flags = AVFMT_SHOW_IDS,
01486 };