Originally committed as revision 4448 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
| @@ -1423,8 +1423,14 @@ static int output_packet(AVInputStream *ist, int ist_index, | |||||
| av_free(buffer_to_free); | av_free(buffer_to_free); | ||||
| /* XXX: allocate the subtitles in the codec ? */ | /* XXX: allocate the subtitles in the codec ? */ | ||||
| if (subtitle_to_free) { | if (subtitle_to_free) { | ||||
| av_free(subtitle_to_free->bitmap); | |||||
| av_free(subtitle_to_free->rgba_palette); | |||||
| if (subtitle_to_free->rects != NULL) { | |||||
| for (i = 0; i < subtitle_to_free->num_rects; i++) { | |||||
| av_free(subtitle_to_free->rects[i].bitmap); | |||||
| av_free(subtitle_to_free->rects[i].rgba_palette); | |||||
| } | |||||
| av_freep(&subtitle_to_free->rects); | |||||
| } | |||||
| subtitle_to_free->num_rects = 0; | |||||
| subtitle_to_free = NULL; | subtitle_to_free = NULL; | ||||
| } | } | ||||
| } | } | ||||
| @@ -17,7 +17,7 @@ OBJS= bitstream.o utils.o mem.o allcodecs.o \ | |||||
| ratecontrol.o adpcm.o eval.o error_resilience.o \ | ratecontrol.o adpcm.o eval.o error_resilience.o \ | ||||
| fft.o mdct.o raw.o golomb.o cabac.o\ | fft.o mdct.o raw.o golomb.o cabac.o\ | ||||
| dpcm.o adx.o rational.o faandct.o parser.o g726.o \ | dpcm.o adx.o rational.o faandct.o parser.o g726.o \ | ||||
| vp3dsp.o integer.o h264idct.o rangecoder.o pnm.o h263.o msmpeg4.o h263dec.o dvdsub.o dvbsub.o | |||||
| vp3dsp.o integer.o h264idct.o rangecoder.o pnm.o h263.o msmpeg4.o h263dec.o dvdsub.o dvbsub.o dvbsubdec.o | |||||
| ifeq ($(CONFIG_AASC_DECODER),yes) | ifeq ($(CONFIG_AASC_DECODER),yes) | ||||
| OBJS+= aasc.o | OBJS+= aasc.o | ||||
| @@ -555,6 +555,7 @@ PCM_CODEC(CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha); | |||||
| /* subtitles */ | /* subtitles */ | ||||
| register_avcodec(&dvdsub_decoder); | register_avcodec(&dvdsub_decoder); | ||||
| register_avcodec(&dvbsub_encoder); | register_avcodec(&dvbsub_encoder); | ||||
| register_avcodec(&dvbsub_decoder); | |||||
| /* parsers */ | /* parsers */ | ||||
| av_register_codec_parser(&mpegvideo_parser); | av_register_codec_parser(&mpegvideo_parser); | ||||
| @@ -574,5 +575,6 @@ PCM_CODEC(CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha); | |||||
| av_register_codec_parser(&ac3_parser); | av_register_codec_parser(&ac3_parser); | ||||
| #endif | #endif | ||||
| av_register_codec_parser(&dvdsub_parser); | av_register_codec_parser(&dvdsub_parser); | ||||
| av_register_codec_parser(&dvbsub_parser); | |||||
| } | } | ||||
| @@ -1930,18 +1930,23 @@ typedef struct AVPaletteControl { | |||||
| } AVPaletteControl; | } AVPaletteControl; | ||||
| typedef struct AVSubtitle { | |||||
| uint16_t format; /* 0 = graphics */ | |||||
| typedef struct AVSubtitleRect { | |||||
| uint16_t x; | uint16_t x; | ||||
| uint16_t y; | uint16_t y; | ||||
| uint16_t w; | uint16_t w; | ||||
| uint16_t h; | uint16_t h; | ||||
| uint16_t nb_colors; | uint16_t nb_colors; | ||||
| uint32_t start_display_time; /* relative to packet pts, in ms */ | |||||
| uint32_t end_display_time; /* relative to packet pts, in ms */ | |||||
| int linesize; | int linesize; | ||||
| uint32_t *rgba_palette; | uint32_t *rgba_palette; | ||||
| uint8_t *bitmap; | uint8_t *bitmap; | ||||
| } AVSubtitleRect; | |||||
| typedef struct AVSubtitle { | |||||
| uint16_t format; /* 0 = graphics */ | |||||
| uint32_t start_display_time; /* relative to packet pts, in ms */ | |||||
| uint32_t end_display_time; /* relative to packet pts, in ms */ | |||||
| uint32_t num_rects; | |||||
| AVSubtitleRect *rects; | |||||
| } AVSubtitle; | } AVSubtitle; | ||||
| extern AVCodec ac3_encoder; | extern AVCodec ac3_encoder; | ||||
| @@ -2135,6 +2140,7 @@ extern AVCodec dts_decoder; | |||||
| /* subtitles */ | /* subtitles */ | ||||
| extern AVCodec dvdsub_decoder; | extern AVCodec dvdsub_decoder; | ||||
| extern AVCodec dvbsub_encoder; | extern AVCodec dvbsub_encoder; | ||||
| extern AVCodec dvbsub_decoder; | |||||
| /* resample.c */ | /* resample.c */ | ||||
| @@ -2390,6 +2396,7 @@ extern AVCodecParser pnm_parser; | |||||
| extern AVCodecParser mpegaudio_parser; | extern AVCodecParser mpegaudio_parser; | ||||
| extern AVCodecParser ac3_parser; | extern AVCodecParser ac3_parser; | ||||
| extern AVCodecParser dvdsub_parser; | extern AVCodecParser dvdsub_parser; | ||||
| extern AVCodecParser dvbsub_parser; | |||||
| /* memory */ | /* memory */ | ||||
| void *av_malloc(unsigned int size); | void *av_malloc(unsigned int size); | ||||
| @@ -225,18 +225,9 @@ static int encode_dvb_subtitles(DVBSubtitleContext *s, | |||||
| q = outbuf; | q = outbuf; | ||||
| page_id = 1; | page_id = 1; | ||||
| region_id = 0; | |||||
| clut_id = 0; | |||||
| object_id = 0; | |||||
| if (h->nb_colors <= 4) { | |||||
| /* 2 bpp, some decoders do not support it correctly */ | |||||
| bpp_index = 0; | |||||
| } else if (h->nb_colors <= 16) { | |||||
| /* 4 bpp, standard encoding */ | |||||
| bpp_index = 1; | |||||
| } else { | |||||
| if (h->num_rects == 0 || h->rects == NULL) | |||||
| return -1; | return -1; | ||||
| } | |||||
| *q++ = 0x00; /* subtitle_stream_id */ | *q++ = 0x00; /* subtitle_stream_id */ | ||||
| @@ -254,108 +245,153 @@ static int encode_dvb_subtitles(DVBSubtitleContext *s, | |||||
| page_state = 2; /* mode change */ | page_state = 2; /* mode change */ | ||||
| /* page_version = 0 + page_state */ | /* page_version = 0 + page_state */ | ||||
| *q++ = s->object_version | (page_state << 2) | 3; | *q++ = s->object_version | (page_state << 2) | 3; | ||||
| *q++ = region_id; | |||||
| *q++ = 0xff; /* reserved */ | |||||
| putbe16(&q, 0); /* left pos */ | |||||
| putbe16(&q, 0); /* top pos */ | |||||
| for (region_id = 0; region_id < h->num_rects; region_id++) { | |||||
| *q++ = region_id; | |||||
| *q++ = 0xff; /* reserved */ | |||||
| putbe16(&q, h->rects[region_id].x); /* left pos */ | |||||
| putbe16(&q, h->rects[region_id].y); /* top pos */ | |||||
| } | |||||
| putbe16(&pseg_len, q - pseg_len - 2); | putbe16(&pseg_len, q - pseg_len - 2); | ||||
| if (!s->hide_state) { | if (!s->hide_state) { | ||||
| /* CLUT segment */ | |||||
| for (clut_id = 0; clut_id < h->num_rects; clut_id++) { | |||||
| /* CLUT segment */ | |||||
| if (h->rects[clut_id].nb_colors <= 4) { | |||||
| /* 2 bpp, some decoders do not support it correctly */ | |||||
| bpp_index = 0; | |||||
| } else if (h->rects[clut_id].nb_colors <= 16) { | |||||
| /* 4 bpp, standard encoding */ | |||||
| bpp_index = 1; | |||||
| } else { | |||||
| return -1; | |||||
| } | |||||
| *q++ = 0x0f; /* sync byte */ | |||||
| *q++ = 0x12; /* CLUT definition segment */ | |||||
| putbe16(&q, page_id); | |||||
| pseg_len = q; | |||||
| q += 2; /* segment length */ | |||||
| *q++ = clut_id; | |||||
| *q++ = (0 << 4) | 0xf; /* version = 0 */ | |||||
| for(i = 0; i < h->rects[clut_id].nb_colors; i++) { | |||||
| *q++ = i; /* clut_entry_id */ | |||||
| *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */ | |||||
| { | |||||
| int a, r, g, b; | |||||
| a = (h->rects[clut_id].rgba_palette[i] >> 24) & 0xff; | |||||
| r = (h->rects[clut_id].rgba_palette[i] >> 16) & 0xff; | |||||
| g = (h->rects[clut_id].rgba_palette[i] >> 8) & 0xff; | |||||
| b = (h->rects[clut_id].rgba_palette[i] >> 0) & 0xff; | |||||
| *q++ = RGB_TO_Y_CCIR(r, g, b); | |||||
| *q++ = RGB_TO_V_CCIR(r, g, b, 0); | |||||
| *q++ = RGB_TO_U_CCIR(r, g, b, 0); | |||||
| *q++ = 255 - a; | |||||
| } | |||||
| } | |||||
| putbe16(&pseg_len, q - pseg_len - 2); | |||||
| } | |||||
| } | |||||
| for (region_id = 0; region_id < h->num_rects; region_id++) { | |||||
| /* region composition segment */ | |||||
| *q++ = 0x0f; /* sync byte */ | |||||
| *q++ = 0x12; /* CLUT definition segment */ | |||||
| if (h->rects[region_id].nb_colors <= 4) { | |||||
| /* 2 bpp, some decoders do not support it correctly */ | |||||
| bpp_index = 0; | |||||
| } else if (h->rects[region_id].nb_colors <= 16) { | |||||
| /* 4 bpp, standard encoding */ | |||||
| bpp_index = 1; | |||||
| } else { | |||||
| return -1; | |||||
| } | |||||
| *q++ = 0x0f; /* sync_byte */ | |||||
| *q++ = 0x11; /* segment_type */ | |||||
| putbe16(&q, page_id); | putbe16(&q, page_id); | ||||
| pseg_len = q; | pseg_len = q; | ||||
| q += 2; /* segment length */ | q += 2; /* segment length */ | ||||
| *q++ = clut_id; | |||||
| *q++ = (0 << 4) | 0xf; /* version = 0 */ | |||||
| for(i = 0; i < h->nb_colors; i++) { | |||||
| *q++ = i; /* clut_entry_id */ | |||||
| *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */ | |||||
| { | |||||
| int a, r, g, b; | |||||
| a = (h->rgba_palette[i] >> 24) & 0xff; | |||||
| r = (h->rgba_palette[i] >> 16) & 0xff; | |||||
| g = (h->rgba_palette[i] >> 8) & 0xff; | |||||
| b = (h->rgba_palette[i] >> 0) & 0xff; | |||||
| *q++ = RGB_TO_Y_CCIR(r, g, b); | |||||
| *q++ = RGB_TO_V_CCIR(r, g, b, 0); | |||||
| *q++ = RGB_TO_U_CCIR(r, g, b, 0); | |||||
| *q++ = 255 - a; | |||||
| } | |||||
| *q++ = region_id; | |||||
| *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */ | |||||
| putbe16(&q, h->rects[region_id].w); /* region width */ | |||||
| putbe16(&q, h->rects[region_id].h); /* region height */ | |||||
| *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03; | |||||
| *q++ = region_id; /* clut_id == region_id */ | |||||
| *q++ = 0; /* 8 bit fill colors */ | |||||
| *q++ = 0x03; /* 4 bit and 2 bit fill colors */ | |||||
| if (!s->hide_state) { | |||||
| putbe16(&q, region_id); /* object_id == region_id */ | |||||
| *q++ = (0 << 6) | (0 << 4); | |||||
| *q++ = 0; | |||||
| *q++ = 0xf0; | |||||
| *q++ = 0; | |||||
| } | } | ||||
| putbe16(&pseg_len, q - pseg_len - 2); | putbe16(&pseg_len, q - pseg_len - 2); | ||||
| } | } | ||||
| /* region composition segment */ | |||||
| *q++ = 0x0f; /* sync_byte */ | |||||
| *q++ = 0x11; /* segment_type */ | |||||
| putbe16(&q, page_id); | |||||
| pseg_len = q; | |||||
| q += 2; /* segment length */ | |||||
| *q++ = region_id; | |||||
| *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */ | |||||
| putbe16(&q, 720); /* region width */ | |||||
| putbe16(&q, 576); /* region height */ | |||||
| *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03; | |||||
| *q++ = clut_id; | |||||
| *q++ = 0; /* 8 bit fill colors */ | |||||
| *q++ = 0x03; /* 4 bit and 2 bit fill colors */ | |||||
| if (!s->hide_state) { | |||||
| putbe16(&q, object_id); | |||||
| *q++ = (0 << 6) | (0 << 4) | ((h->x >> 8) & 0xf); | |||||
| *q++ = h->x; | |||||
| *q++ = 0xf0 | ((h->y >> 8) & 0xf); | |||||
| *q++ = h->y; | |||||
| } | |||||
| putbe16(&pseg_len, q - pseg_len - 2); | |||||
| if (!s->hide_state) { | if (!s->hide_state) { | ||||
| /* Object Data segment */ | |||||
| for (object_id = 0; object_id < h->num_rects; object_id++) { | |||||
| /* Object Data segment */ | |||||
| if (h->rects[region_id].nb_colors <= 4) { | |||||
| /* 2 bpp, some decoders do not support it correctly */ | |||||
| bpp_index = 0; | |||||
| } else if (h->rects[region_id].nb_colors <= 16) { | |||||
| /* 4 bpp, standard encoding */ | |||||
| bpp_index = 1; | |||||
| } else { | |||||
| return -1; | |||||
| } | |||||
| *q++ = 0x0f; /* sync byte */ | |||||
| *q++ = 0x13; | |||||
| putbe16(&q, page_id); | |||||
| pseg_len = q; | |||||
| q += 2; /* segment length */ | |||||
| putbe16(&q, object_id); | |||||
| *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0, | |||||
| onject_coding_method, | |||||
| non_modifying_color_flag */ | |||||
| { | |||||
| uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr; | |||||
| void (*dvb_encode_rle)(uint8_t **pq, | |||||
| const uint8_t *bitmap, int linesize, | |||||
| int w, int h); | |||||
| ptop_field_len = q; | |||||
| q += 2; | |||||
| pbottom_field_len = q; | |||||
| q += 2; | |||||
| if (bpp_index == 0) | |||||
| dvb_encode_rle = dvb_encode_rle2; | |||||
| else | |||||
| dvb_encode_rle = dvb_encode_rle4; | |||||
| top_ptr = q; | |||||
| dvb_encode_rle(&q, h->bitmap, h->w * 2, h->w, h->h >> 1); | |||||
| bottom_ptr = q; | |||||
| dvb_encode_rle(&q, h->bitmap + h->w, h->w * 2, h->w, h->h >> 1); | |||||
| putbe16(&ptop_field_len, bottom_ptr - top_ptr); | |||||
| putbe16(&pbottom_field_len, q - bottom_ptr); | |||||
| } | |||||
| *q++ = 0x0f; /* sync byte */ | |||||
| *q++ = 0x13; | |||||
| putbe16(&q, page_id); | |||||
| pseg_len = q; | |||||
| q += 2; /* segment length */ | |||||
| putbe16(&pseg_len, q - pseg_len - 2); | |||||
| putbe16(&q, object_id); | |||||
| *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0, | |||||
| onject_coding_method, | |||||
| non_modifying_color_flag */ | |||||
| { | |||||
| uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr; | |||||
| void (*dvb_encode_rle)(uint8_t **pq, | |||||
| const uint8_t *bitmap, int linesize, | |||||
| int w, int h); | |||||
| ptop_field_len = q; | |||||
| q += 2; | |||||
| pbottom_field_len = q; | |||||
| q += 2; | |||||
| if (bpp_index == 0) | |||||
| dvb_encode_rle = dvb_encode_rle2; | |||||
| else | |||||
| dvb_encode_rle = dvb_encode_rle4; | |||||
| top_ptr = q; | |||||
| dvb_encode_rle(&q, h->rects[object_id].bitmap, h->rects[object_id].w * 2, | |||||
| h->rects[object_id].w, h->rects[object_id].h >> 1); | |||||
| bottom_ptr = q; | |||||
| dvb_encode_rle(&q, h->rects[object_id].bitmap + h->rects[object_id].w, | |||||
| h->rects[object_id].w * 2, h->rects[object_id].w, | |||||
| h->rects[object_id].h >> 1); | |||||
| putbe16(&ptop_field_len, bottom_ptr - top_ptr); | |||||
| putbe16(&pbottom_field_len, q - bottom_ptr); | |||||
| } | |||||
| putbe16(&pseg_len, q - pseg_len - 2); | |||||
| } | |||||
| } | } | ||||
| /* end of display set segment */ | /* end of display set segment */ | ||||
| @@ -30,7 +30,10 @@ | |||||
| synchronisation is lost */ | synchronisation is lost */ | ||||
| #define MAX_RESYNC_SIZE 4096 | #define MAX_RESYNC_SIZE 4096 | ||||
| static int add_pes_stream(MpegTSContext *ts, int pid, int stream_type); | |||||
| typedef struct PESContext PESContext; | |||||
| static PESContext* add_pes_stream(MpegTSContext *ts, int pid, int stream_type); | |||||
| static AVStream* new_pes_av_stream(PESContext *pes, uint32_t code); | |||||
| enum MpegTSFilterType { | enum MpegTSFilterType { | ||||
| MPEGTS_PES, | MPEGTS_PES, | ||||
| @@ -368,8 +371,13 @@ static void pmt_cb(void *opaque, const uint8_t *section, int section_len) | |||||
| { | { | ||||
| MpegTSContext *ts = opaque; | MpegTSContext *ts = opaque; | ||||
| SectionHeader h1, *h = &h1; | SectionHeader h1, *h = &h1; | ||||
| const uint8_t *p, *p_end; | |||||
| int program_info_length, pcr_pid, pid, stream_type, desc_length; | |||||
| PESContext *pes; | |||||
| AVStream *st; | |||||
| const uint8_t *p, *p_end, *desc_list_end, *desc_end; | |||||
| int program_info_length, pcr_pid, pid, stream_type; | |||||
| int desc_list_len, desc_len, desc_tag; | |||||
| int comp_page, anc_page; | |||||
| char language[4]; | |||||
| #ifdef DEBUG_SI | #ifdef DEBUG_SI | ||||
| printf("PMT:\n"); | printf("PMT:\n"); | ||||
| @@ -399,18 +407,57 @@ static void pmt_cb(void *opaque, const uint8_t *section, int section_len) | |||||
| if (p >= p_end) | if (p >= p_end) | ||||
| return; | return; | ||||
| for(;;) { | for(;;) { | ||||
| language[0] = 0; | |||||
| st = 0; | |||||
| stream_type = get8(&p, p_end); | stream_type = get8(&p, p_end); | ||||
| if (stream_type < 0) | if (stream_type < 0) | ||||
| break; | break; | ||||
| pid = get16(&p, p_end) & 0x1fff; | pid = get16(&p, p_end) & 0x1fff; | ||||
| if (pid < 0) | if (pid < 0) | ||||
| break; | break; | ||||
| desc_length = get16(&p, p_end) & 0xfff; | |||||
| if (desc_length < 0) | |||||
| desc_list_len = get16(&p, p_end) & 0xfff; | |||||
| if (desc_list_len < 0) | |||||
| break; | |||||
| desc_list_end = p + desc_list_len; | |||||
| if (desc_list_end > p_end) | |||||
| break; | break; | ||||
| p += desc_length; | |||||
| if (p > p_end) | |||||
| return; | |||||
| for(;;) { | |||||
| desc_tag = get8(&p, desc_list_end); | |||||
| if (desc_tag < 0) | |||||
| break; | |||||
| desc_len = get8(&p, desc_list_end); | |||||
| desc_end = p + desc_len; | |||||
| if (desc_end > desc_list_end) | |||||
| break; | |||||
| #ifdef DEBUG_SI | |||||
| printf("tag: 0x%02x len=%d\n", desc_tag, desc_len); | |||||
| #endif | |||||
| switch(desc_tag) { | |||||
| case DVB_SUBT_DESCID: | |||||
| if (stream_type == STREAM_TYPE_PRIVATE_DATA) | |||||
| stream_type = STREAM_TYPE_SUBTITLE_DVB; | |||||
| 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); | |||||
| comp_page = get16(&p, desc_end); | |||||
| anc_page = get16(&p, desc_end); | |||||
| 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; | |||||
| break; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| p = desc_end; | |||||
| } | |||||
| p = desc_list_end; | |||||
| #ifdef DEBUG_SI | #ifdef DEBUG_SI | ||||
| printf("stream_type=%d pid=0x%x\n", stream_type, pid); | printf("stream_type=%d pid=0x%x\n", stream_type, pid); | ||||
| @@ -427,12 +474,28 @@ static void pmt_cb(void *opaque, const uint8_t *section, int section_len) | |||||
| case STREAM_TYPE_AUDIO_AAC: | case STREAM_TYPE_AUDIO_AAC: | ||||
| case STREAM_TYPE_AUDIO_AC3: | case STREAM_TYPE_AUDIO_AC3: | ||||
| case STREAM_TYPE_AUDIO_DTS: | case STREAM_TYPE_AUDIO_DTS: | ||||
| add_pes_stream(ts, pid, stream_type); | |||||
| case STREAM_TYPE_SUBTITLE_DVB: | |||||
| pes = add_pes_stream(ts, pid, stream_type); | |||||
| if (pes) | |||||
| st = new_pes_av_stream(pes, 0); | |||||
| break; | break; | ||||
| default: | default: | ||||
| /* we ignore the other streams */ | /* we ignore the other streams */ | ||||
| break; | break; | ||||
| } | } | ||||
| if (st) { | |||||
| if (language[0] != 0) { | |||||
| st->language[0] = language[0]; | |||||
| st->language[1] = language[1]; | |||||
| st->language[2] = language[2]; | |||||
| st->language[3] = language[3]; | |||||
| } | |||||
| if (stream_type == STREAM_TYPE_SUBTITLE_DVB) { | |||||
| st->codec.sub_id = (anc_page << 16) | comp_page; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| /* all parameters are there */ | /* all parameters are there */ | ||||
| ts->set_service_cb(ts->set_service_opaque, 0); | ts->set_service_cb(ts->set_service_opaque, 0); | ||||
| @@ -653,7 +716,7 @@ enum MpegTSState { | |||||
| #define PES_START_SIZE 9 | #define PES_START_SIZE 9 | ||||
| #define MAX_PES_HEADER_SIZE (9 + 255) | #define MAX_PES_HEADER_SIZE (9 + 255) | ||||
| typedef struct PESContext { | |||||
| struct PESContext { | |||||
| int pid; | int pid; | ||||
| int stream_type; | int stream_type; | ||||
| MpegTSContext *ts; | MpegTSContext *ts; | ||||
| @@ -666,7 +729,7 @@ typedef struct PESContext { | |||||
| int pes_header_size; | int pes_header_size; | ||||
| int64_t pts, dts; | int64_t pts, dts; | ||||
| uint8_t header[MAX_PES_HEADER_SIZE]; | uint8_t header[MAX_PES_HEADER_SIZE]; | ||||
| } PESContext; | |||||
| }; | |||||
| static int64_t get_pts(const uint8_t *p) | static int64_t get_pts(const uint8_t *p) | ||||
| { | { | ||||
| @@ -687,9 +750,8 @@ static void mpegts_push_data(void *opaque, | |||||
| { | { | ||||
| PESContext *pes = opaque; | PESContext *pes = opaque; | ||||
| MpegTSContext *ts = pes->ts; | MpegTSContext *ts = pes->ts; | ||||
| AVStream *st; | |||||
| const uint8_t *p; | const uint8_t *p; | ||||
| int len, code, codec_type, codec_id; | |||||
| int len, code; | |||||
| if (is_start) { | if (is_start) { | ||||
| pes->state = MPEGTS_HEADER; | pes->state = MPEGTS_HEADER; | ||||
| @@ -722,59 +784,7 @@ static void mpegts_push_data(void *opaque, | |||||
| goto skip; | goto skip; | ||||
| if (!pes->st) { | if (!pes->st) { | ||||
| /* allocate stream */ | /* allocate stream */ | ||||
| switch(pes->stream_type){ | |||||
| case STREAM_TYPE_AUDIO_MPEG1: | |||||
| case STREAM_TYPE_AUDIO_MPEG2: | |||||
| codec_type = CODEC_TYPE_AUDIO; | |||||
| codec_id = CODEC_ID_MP3; | |||||
| break; | |||||
| case STREAM_TYPE_VIDEO_MPEG1: | |||||
| case STREAM_TYPE_VIDEO_MPEG2: | |||||
| codec_type = CODEC_TYPE_VIDEO; | |||||
| codec_id = CODEC_ID_MPEG2VIDEO; | |||||
| break; | |||||
| case STREAM_TYPE_VIDEO_MPEG4: | |||||
| codec_type = CODEC_TYPE_VIDEO; | |||||
| codec_id = CODEC_ID_MPEG4; | |||||
| break; | |||||
| case STREAM_TYPE_VIDEO_H264: | |||||
| codec_type = CODEC_TYPE_VIDEO; | |||||
| codec_id = CODEC_ID_H264; | |||||
| break; | |||||
| case STREAM_TYPE_AUDIO_AAC: | |||||
| codec_type = CODEC_TYPE_AUDIO; | |||||
| codec_id = CODEC_ID_AAC; | |||||
| break; | |||||
| case STREAM_TYPE_AUDIO_AC3: | |||||
| codec_type = CODEC_TYPE_AUDIO; | |||||
| codec_id = CODEC_ID_AC3; | |||||
| break; | |||||
| case STREAM_TYPE_AUDIO_DTS: | |||||
| codec_type = CODEC_TYPE_AUDIO; | |||||
| codec_id = CODEC_ID_DTS; | |||||
| break; | |||||
| default: | |||||
| if (code >= 0x1c0 && code <= 0x1df) { | |||||
| codec_type = CODEC_TYPE_AUDIO; | |||||
| codec_id = CODEC_ID_MP2; | |||||
| } else if (code == 0x1bd) { | |||||
| codec_type = CODEC_TYPE_AUDIO; | |||||
| codec_id = CODEC_ID_AC3; | |||||
| } else { | |||||
| codec_type = CODEC_TYPE_VIDEO; | |||||
| codec_id = CODEC_ID_MPEG1VIDEO; | |||||
| } | |||||
| break; | |||||
| } | |||||
| st = av_new_stream(pes->stream, pes->pid); | |||||
| if (st) { | |||||
| av_set_pts_info(st, 33, 1, 90000); | |||||
| st->priv_data = pes; | |||||
| st->codec.codec_type = codec_type; | |||||
| st->codec.codec_id = codec_id; | |||||
| st->need_parsing = 1; | |||||
| pes->st = st; | |||||
| } | |||||
| new_pes_av_stream(pes, code); | |||||
| } | } | ||||
| pes->state = MPEGTS_PESHEADER_FILL; | pes->state = MPEGTS_PESHEADER_FILL; | ||||
| pes->total_size = (pes->header[4] << 8) | pes->header[5]; | pes->total_size = (pes->header[4] << 8) | pes->header[5]; | ||||
| @@ -854,7 +864,73 @@ static void mpegts_push_data(void *opaque, | |||||
| } | } | ||||
| } | } | ||||
| static int add_pes_stream(MpegTSContext *ts, int pid, int stream_type) | |||||
| static AVStream* new_pes_av_stream(PESContext *pes, uint32_t code) | |||||
| { | |||||
| AVStream *st; | |||||
| int codec_type, codec_id; | |||||
| switch(pes->stream_type){ | |||||
| case STREAM_TYPE_AUDIO_MPEG1: | |||||
| case STREAM_TYPE_AUDIO_MPEG2: | |||||
| codec_type = CODEC_TYPE_AUDIO; | |||||
| codec_id = CODEC_ID_MP3; | |||||
| break; | |||||
| case STREAM_TYPE_VIDEO_MPEG1: | |||||
| case STREAM_TYPE_VIDEO_MPEG2: | |||||
| codec_type = CODEC_TYPE_VIDEO; | |||||
| codec_id = CODEC_ID_MPEG2VIDEO; | |||||
| break; | |||||
| case STREAM_TYPE_VIDEO_MPEG4: | |||||
| codec_type = CODEC_TYPE_VIDEO; | |||||
| codec_id = CODEC_ID_MPEG4; | |||||
| break; | |||||
| case STREAM_TYPE_VIDEO_H264: | |||||
| codec_type = CODEC_TYPE_VIDEO; | |||||
| codec_id = CODEC_ID_H264; | |||||
| break; | |||||
| case STREAM_TYPE_AUDIO_AAC: | |||||
| codec_type = CODEC_TYPE_AUDIO; | |||||
| codec_id = CODEC_ID_AAC; | |||||
| break; | |||||
| case STREAM_TYPE_AUDIO_AC3: | |||||
| codec_type = CODEC_TYPE_AUDIO; | |||||
| codec_id = CODEC_ID_AC3; | |||||
| break; | |||||
| case STREAM_TYPE_AUDIO_DTS: | |||||
| codec_type = CODEC_TYPE_AUDIO; | |||||
| codec_id = CODEC_ID_DTS; | |||||
| break; | |||||
| case STREAM_TYPE_SUBTITLE_DVB: | |||||
| codec_type = CODEC_TYPE_SUBTITLE; | |||||
| codec_id = CODEC_ID_DVB_SUBTITLE; | |||||
| break; | |||||
| default: | |||||
| if (code >= 0x1c0 && code <= 0x1df) { | |||||
| codec_type = CODEC_TYPE_AUDIO; | |||||
| codec_id = CODEC_ID_MP2; | |||||
| } else if (code == 0x1bd) { | |||||
| codec_type = CODEC_TYPE_AUDIO; | |||||
| codec_id = CODEC_ID_AC3; | |||||
| } else { | |||||
| codec_type = CODEC_TYPE_VIDEO; | |||||
| codec_id = CODEC_ID_MPEG1VIDEO; | |||||
| } | |||||
| break; | |||||
| } | |||||
| st = av_new_stream(pes->stream, pes->pid); | |||||
| if (st) { | |||||
| av_set_pts_info(st, 33, 1, 90000); | |||||
| st->priv_data = pes; | |||||
| st->codec.codec_type = codec_type; | |||||
| st->codec.codec_id = codec_id; | |||||
| st->need_parsing = 1; | |||||
| pes->st = st; | |||||
| } | |||||
| return st; | |||||
| } | |||||
| static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int stream_type) | |||||
| { | { | ||||
| MpegTSFilter *tss; | MpegTSFilter *tss; | ||||
| PESContext *pes; | PESContext *pes; | ||||
| @@ -862,7 +938,7 @@ static int add_pes_stream(MpegTSContext *ts, int pid, int stream_type) | |||||
| /* if no pid found, then add a pid context */ | /* if no pid found, then add a pid context */ | ||||
| pes = av_mallocz(sizeof(PESContext)); | pes = av_mallocz(sizeof(PESContext)); | ||||
| if (!pes) | if (!pes) | ||||
| return -1; | |||||
| return 0; | |||||
| pes->ts = ts; | pes->ts = ts; | ||||
| pes->stream = ts->stream; | pes->stream = ts->stream; | ||||
| pes->pid = pid; | pes->pid = pid; | ||||
| @@ -870,9 +946,9 @@ static int add_pes_stream(MpegTSContext *ts, int pid, int stream_type) | |||||
| tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes); | tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes); | ||||
| if (!tss) { | if (!tss) { | ||||
| av_free(pes); | av_free(pes); | ||||
| return -1; | |||||
| return 0; | |||||
| } | } | ||||
| return 0; | |||||
| return pes; | |||||
| } | } | ||||
| /* handle one TS packet */ | /* handle one TS packet */ | ||||
| @@ -1131,11 +1207,11 @@ static int mpegts_read_header(AVFormatContext *s, | |||||
| } | } | ||||
| if (ts->nb_services <= 0) { | if (ts->nb_services <= 0) { | ||||
| /* raw transport stream */ | |||||
| ts->auto_guess = 1; | |||||
| s->ctx_flags |= AVFMTCTX_NOHEADER; | |||||
| goto do_pcr; | |||||
| } | |||||
| /* raw transport stream */ | |||||
| ts->auto_guess = 1; | |||||
| s->ctx_flags |= AVFMTCTX_NOHEADER; | |||||
| goto do_pcr; | |||||
| } | |||||
| /* tune to first service found */ | /* tune to first service found */ | ||||
| for(i=0; i<ts->nb_services && ts->set_service_ret; i++){ | for(i=0; i<ts->nb_services && ts->set_service_ret; i++){ | ||||
| @@ -31,6 +31,9 @@ | |||||
| #define PMT_TID 0x02 | #define PMT_TID 0x02 | ||||
| #define SDT_TID 0x42 | #define SDT_TID 0x42 | ||||
| /* descriptor ids */ | |||||
| #define DVB_SUBT_DESCID 0x59 | |||||
| #define STREAM_TYPE_VIDEO_MPEG1 0x01 | #define STREAM_TYPE_VIDEO_MPEG1 0x01 | ||||
| #define STREAM_TYPE_VIDEO_MPEG2 0x02 | #define STREAM_TYPE_VIDEO_MPEG2 0x02 | ||||
| #define STREAM_TYPE_AUDIO_MPEG1 0x03 | #define STREAM_TYPE_AUDIO_MPEG1 0x03 | ||||
| @@ -44,6 +47,8 @@ | |||||
| #define STREAM_TYPE_AUDIO_AC3 0x81 | #define STREAM_TYPE_AUDIO_AC3 0x81 | ||||
| #define STREAM_TYPE_AUDIO_DTS 0x8a | #define STREAM_TYPE_AUDIO_DTS 0x8a | ||||
| #define STREAM_TYPE_SUBTITLE_DVB 0x100 | |||||
| unsigned int mpegts_crc32(const uint8_t *data, int len); | unsigned int mpegts_crc32(const uint8_t *data, int len); | ||||
| extern AVOutputFormat mpegts_mux; | extern AVOutputFormat mpegts_mux; | ||||
| @@ -2508,6 +2508,9 @@ void dump_format(AVFormatContext *ic, | |||||
| if (flags & AVFMT_SHOW_IDS) { | if (flags & AVFMT_SHOW_IDS) { | ||||
| av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id); | av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id); | ||||
| } | } | ||||
| if (strlen(st->language) > 0) { | |||||
| av_log(NULL, AV_LOG_INFO, "(%s)", st->language); | |||||
| } | |||||
| av_log(NULL, AV_LOG_INFO, ": %s\n", buf); | av_log(NULL, AV_LOG_INFO, ": %s\n", buf); | ||||
| } | } | ||||
| } | } | ||||