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); | ||||
} | } | ||||
} | } | ||||