Index: libs/libavcodec/allcodecs.c =================================================================== --- libs/libavcodec/allcodecs.c (revision 20970) +++ libs/libavcodec/allcodecs.c (working copy) @@ -302,6 +302,7 @@ /* subtitles */ REGISTER_ENCDEC (DVBSUB, dvbsub); REGISTER_ENCDEC (DVDSUB, dvdsub); + REGISTER_DECODER (PGSSUB, pgssub); REGISTER_ENCDEC (XSUB, xsub); /* external libraries */ @@ -340,6 +341,7 @@ REGISTER_PARSER (MPEG4VIDEO, mpeg4video); REGISTER_PARSER (MPEGAUDIO, mpegaudio); REGISTER_PARSER (MPEGVIDEO, mpegvideo); + REGISTER_PARSER (PGSSUB, pgssub); REGISTER_PARSER (PNM, pnm); REGISTER_PARSER (VC1, vc1); REGISTER_PARSER (VP3, vp3); Index: libs/libavcodec/avcodec.h =================================================================== --- libs/libavcodec/avcodec.h (revision 20970) +++ libs/libavcodec/avcodec.h (working copy) @@ -329,6 +329,7 @@ CODEC_ID_XSUB, CODEC_ID_SSA, CODEC_ID_MOV_TEXT, + CODEC_ID_HDMV_PGS_SUBTITLE, /* teletext codecs */ CODEC_ID_MPEG2VBI, Index: libs/libavcodec/libavcodec.pro =================================================================== --- libs/libavcodec/libavcodec.pro (revision 20970) +++ libs/libavcodec/libavcodec.pro (working copy) @@ -222,6 +222,7 @@ contains( CONFIG_PGM_ENCODER, yes ) { SOURCES *= pnmenc.c } contains( CONFIG_PGMYUV_DECODER, yes ) { SOURCES *= pnmenc.c pnm.c } contains( CONFIG_PGMYUV_ENCODER, yes ) { SOURCES *= pnmenc.c } +contains( CONFIG_PGSSUB_DECODER, yes ) { SOURCES *= pgssubdec.c } contains( CONFIG_PNG_DECODER, yes ) { SOURCES *= png.c pngdec.c } contains( CONFIG_PNG_ENCODER, yes ) { SOURCES *= png.c pngenc.c } contains( CONFIG_PPM_DECODER, yes ) { SOURCES *= pnmenc.c pnm.c } @@ -466,6 +467,7 @@ contains( CONFIG_MPEG4VIDEO_PARSER, yes ) { SOURCES *= mpeg4video_parser.c mpeg12data.c mpegvideo.c error_resilience.c } contains( CONFIG_MPEGAUDIO_PARSER, yes ) { SOURCES *= mpegaudio_parser.c mpegaudiodecheader.c } contains( CONFIG_MPEGVIDEO_PARSER, yes ) { SOURCES *= mpegvideo_parser.c mpeg12.c mpeg12data.c mpegvideo.c error_resilience.c } +contains( CONFIG_PGSSUB_PARSER, yes ) { SOURCES *= pgssub_parser.c } contains( CONFIG_PNM_PARSER, yes ) { SOURCES *= pnm_parser.c pnm.c } contains( CONFIG_VC1_PARSER, yes ) { SOURCES *= vc1_parser.c vc1.c vc1data.c msmpeg4data.c h263dec.c h263.c error_resilience.c intrax8.c mpegvideo.c msmpeg4.c } contains( CONFIG_VP3_PARSER, yes ) { SOURCES *= vp3_parser.c } Index: libs/libavcodec/pgssub_parser.c =================================================================== --- libs/libavcodec/pgssub_parser.c (revision 0) +++ libs/libavcodec/pgssub_parser.c (revision 0) @@ -0,0 +1,128 @@ +/* + * PGS subtitle parser for FFmpeg + * Copyright (c) 2009 Stephen Backway + * + * 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.1 of the License, or (at your option) any later version. + * + * 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file libavcodec/pgssubdec.c + * PGS Subtitle Decoder + */ + +#include "avcodec.h" +#include "dsputil.h" +#include "get_bits.h" + +//#define DEBUG +//#define DEBUG_PACKET_CONTENTS + +/* Parser (mostly) copied from dvbsub_parser.c */ + +#define PARSE_BUF_SIZE (65536) + + +/* parser definition */ +typedef struct PGSSubParseContext { + uint8_t *packet; + int packet_len; + int packet_index; +} PGSSubParseContext; + +static av_cold int pgssub_parse_init(AVCodecParserContext *s) +{ + PGSSubParseContext *pc = s->priv_data; + pc->packet = av_malloc(PARSE_BUF_SIZE); + + return 0; +} + +static int pgssub_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + PGSSubParseContext *pc = s->priv_data; + + uint8_t *p, *p_end; + int len, buf_pos = 0; + +#ifdef DEBUG + av_log(avctx, AV_LOG_INFO, "PGS parse packet pts=%"PRIx64", lpts=%"PRIx64", cpts=%"PRIx64", buf_size=%d:\n", + s->pts, s->last_pts, s->cur_frame_pts[s->cur_frame_start_index], buf_size); +#endif + +#ifdef DEBUG_PACKET_CONTENTS + int i; + + for (i=0; i < buf_size; i++) + { + av_log(avctx, AV_LOG_INFO, "%02x ", buf[i]); + if (i % 16 == 15) + av_log(avctx, AV_LOG_INFO, "\n"); + } + + if (i % 16 != 0) + av_log(avctx, AV_LOG_INFO, "\n"); + +#endif + + *poutbuf = NULL; + *poutbuf_size = 0; + + if (buf_size < 3) { +#ifdef DEBUG + av_log(avctx, AV_LOG_INFO, "Bad packet, not enough data \n"); +#endif + return -1; + } + + pc->packet_len = buf_size; + pc->packet_index = 0; + + /* Check we have a large enough buffer */ + if (buf_size > PARSE_BUF_SIZE) + return -1; + + if (pc->packet) + memcpy(pc->packet, buf, buf_size); + else { +#ifdef DEBUG + av_log(avctx, AV_LOG_INFO, "No Buffer Allocated!\n"); +#endif + return -1; + } + + *poutbuf_size = pc->packet_len; + *poutbuf = pc->packet; + + return buf_size; +} + +static av_cold void pgssub_parse_close(AVCodecParserContext *s) +{ + PGSSubParseContext *pc = s->priv_data; + av_freep(&pc->packet); +} + +AVCodecParser pgssub_parser = { + { CODEC_ID_HDMV_PGS_SUBTITLE }, + sizeof(PGSSubParseContext), + pgssub_parse_init, + pgssub_parse, + pgssub_parse_close, +}; Index: libs/libavcodec/pgssubdec.c =================================================================== --- libs/libavcodec/pgssubdec.c (revision 0) +++ libs/libavcodec/pgssubdec.c (revision 0) @@ -0,0 +1,557 @@ +/* + * PGS subtitle decoding for ffmpeg + * Copyright (c) 2009 Stephen Backway + * + * 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.1 of the License, or (at your option) any later version. + * + * 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file libavcodec/pgssubdec.c + * PGS Subtitle Decoder + */ + +#include "avcodec.h" +#include "dsputil.h" +#include "colorspace.h" + +//#define DEBUG +//#define DEBUG_PACKET_CONTENTS +//#define DEBUG_SAVE_IMAGES + +#define PGSSUB_PALETTE_SEGMENT 0x14 +#define PGSSUB_PICTURE_SEGMENT 0x15 +#define PGSSUB_PRESENTATION_SEGMENT 0x16 +#define PGSSUB_WINDOW_SEGMENT 0x17 +#define PGSSUB_DISPLAY_SEGMENT 0x80 + +#define cm (ff_cropTbl + MAX_NEG_CROP) +#define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) + +typedef struct PGSSubPresentation { + int x; + int y; + int video_w; + int video_h; + int id_number; + +} PGSSubPresentation; + +typedef struct PGSSubWindow { + int x; + int y; + int w; + int h; + +} PGSSubWindow; + +typedef struct PGSSubPicture { + int w; + int h; + + uint8_t *bitmap; + +} PGSSubPicture; + +typedef struct PGSSubContext { + PGSSubPresentation *presentation; + PGSSubWindow *window; + uint32_t clut[256]; + PGSSubPicture *picture; + +} PGSSubContext; + +static av_cold int pgssub_init_decoder(AVCodecContext *avctx) +{ + avctx->pix_fmt = PIX_FMT_RGB32; + PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data; + ctx->presentation = av_mallocz(sizeof(PGSSubPresentation)); + ctx->window = av_mallocz(sizeof(PGSSubWindow)); + ctx->picture = av_mallocz(sizeof(PGSSubPicture)); + + return 0; +} + +static av_cold int pgssub_close_decoder(AVCodecContext *avctx) +{ + PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data; + + if (ctx->picture->bitmap) + av_freep(&ctx->picture->bitmap); + + av_freep(&ctx->presentation); + av_freep(&ctx->window); + av_freep(&ctx->picture); + return 0; +} + +static void pgssub_parse_picture_segment(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data; + + uint8_t block; + uint8_t flags; + uint8_t colour; + uint8_t *rle_bitmap_end; + uint8_t sequence_desc; + int rle_bitmap_len, pixel_count, line_count, run, width, height; + + /* skip 3 unknown bytes: Object ID (2 bytes), Version Number */ + buf += 3; + + /* Read the Sequence Description to determine if start of RLE data or Appended to previous RLE */ + sequence_desc = AV_RB8(buf); + buf += 1; + + if (!(sequence_desc & 0x80)) { + av_log(avctx, AV_LOG_ERROR, "Decoder currently does not support object data over multiple packets.\n", rle_bitmap_len); + return; + } + + /* Decode rle bitmap length */ + rle_bitmap_len = AV_RB24(buf); + buf += 3; + + /* Check to ensure we have enough data for rle_bitmap_length if just a single packet*/ + if (rle_bitmap_len > (buf_size - 7)) { + av_log(avctx, AV_LOG_ERROR, "Not enough RLE data for specified length of %d.\n", rle_bitmap_len); + return; + } + + rle_bitmap_end = buf + rle_bitmap_len; + + /* Get bitmap dimensions from data */ + width = AV_RB16(buf); + buf += 2; + + height = AV_RB16(buf); + buf += 2; + + /* Make sure the bitmap is not too large. */ + if (ctx->presentation->video_w < width || ctx->presentation->video_h < height) { + av_log(avctx, AV_LOG_ERROR, "Bitmap dimensions larger then video. Width=%d Height=%d\n", width, height); + return; + } + + ctx->picture->w = width; + ctx->picture->h = height; + + ctx->picture->bitmap = av_malloc(width * height * sizeof(uint8_t)); + + pixel_count = 0; + line_count = 0; + + while (buf < rle_bitmap_end && line_count < height) { + block = AV_RB8(buf); + buf += 1; + + if (block == 0x00) { + block = AV_RB8(buf); + buf += 1; + flags = block & 0xC0; + + switch (flags) { + case 0x00: + run = block & 0x3F; + if (run > 0) + colour = 0; + break; + case 0xC0: + run = (block & 0x3F) << 8 | AV_RB8(buf); + colour = AV_RB8(buf + 1); + buf += 2; + break; + case 0x80: + run = block & 0x3F; + colour = AV_RB8(buf); + buf += 1; + break; + case 0x40: + run = (block & 0x3F) << 8 | AV_RB8(buf); + colour = 0; + buf += 1; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown RLE code.\n"); + run = -1; + break; + } + } + else { + run = 1; + colour = block; + } + + if (run > 0) { + memset(ctx->picture->bitmap + pixel_count, colour, run); + pixel_count += run; + } + else if (run == 0) { + /* New Line. Check if correct pixels decoded, if not display warning and adjust bitmap pointer to correct new line position. */ + if (pixel_count % width == width - 1) { + av_log(avctx, AV_LOG_ERROR, "Decoded %d pixels, when line should be %d pixels\n", pixel_count % width, width); + } + line_count++; + } + } +#ifdef DEBUG + av_log(avctx, AV_LOG_INFO, "Pixel Count = %d, Area = %d\n", pixel_count, width * height); +#endif +} + +static void pgssub_parse_palette_segment(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data; + + const uint8_t *buf_end = buf + buf_size; + int colour_id, max_colour_id; + int y, cb, cr, alpha; + int r, g, b, r_add, g_add, b_add; + +#ifdef DEBUG_PACKET_CONTENTS + int i; + + av_log(avctx, AV_LOG_INFO, "PGS palette packet:\n"); + + for (i=0; i < buf_size; i++) { + av_log(avctx, AV_LOG_INFO, "%02x ", buf[i]); + } + + av_log(avctx, AV_LOG_INFO, "\n"); + +#endif + + max_colour_id = (buf_size - 2) % 5; + + /* Check to ensure that the buffer provided is not larger then the maximum palette */ + if (max_colour_id > 255) { + av_log(avctx, AV_LOG_INFO, "max_colour_id to large at %d\n", max_colour_id); + return; + } + + /* Skip two null bytes */ + buf += 2; + + while (buf < buf_end) { + colour_id = AV_RB8(buf); + buf += 1; + y = AV_RB8(buf); + buf += 1; + cb = AV_RB8(buf); + buf += 1; + cr = AV_RB8(buf); + buf += 1; + alpha = AV_RB8(buf); + buf += 1; + + YUV_TO_RGB1(cb, cr); + YUV_TO_RGB2(r, g, b, y); + +#ifdef DEBUG + av_log(avctx, AV_LOG_INFO, "Colour %d := (%d,%d,%d,%d)\n", colour_id, r, g, b, alpha); +#endif + + /* Store colour in palette */ + if (colour_id < 255) + ctx->clut[colour_id] = RGBA(r,g,b,255 - alpha); + } +} + + +static void pgssub_parse_presentation_segment(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data; + int x, y, video_w, video_h; + uint8_t block; + +#ifdef DEBUG_PACKET_CONTENTS + int i; + + av_log(avctx, AV_LOG_INFO, "PGS presentation packet:\n"); + + for (i=0; i < buf_size; i++) { + av_log(avctx, AV_LOG_INFO, "%02x ", buf[i]); + } + + av_log(avctx, AV_LOG_INFO, "\n"); + +#endif + + video_w = AV_RB16(buf); + buf += 2; + + video_h = AV_RB16(buf); + buf += 2; + + av_log(avctx, AV_LOG_INFO, "Video Dimensions %dx%d\n", video_w, video_h); + + ctx->presentation->video_w = video_w; + ctx->presentation->video_h = video_h; + + /* Skip 1 bytes of unknown, frame rate? */ + buf += 1; + + ctx->presentation->id_number = AV_RB16(buf); + buf += 2; + + /* Next byte is the state. */ + block = AV_RB8(buf); + if (block == 0x80) { + /* Skip 7 bytes (+1 for previous byte) of unknown: + pallete_update_flag (0x80), + pallete_id_to_use, + Object Number (if > 0 determines if more data to process), + object_id_ref (2 bytes), + window_id_ref, + composition_flag (0x80 - object cropped, 0x40 - object forced) */ + buf += 8; + + x = AV_RB16(buf); + buf += 2; + + y = AV_RB16(buf); + buf += 2; + + /* TODO If cropping, cropping_x, cropping_y, cropping_width, cropping Height (all 2 bytes). */ + av_log(avctx, AV_LOG_INFO, "Subtitle Placement x=%d, y=%d\n", x, y); + + if (x > video_w || y > video_h) { + av_log(avctx, AV_LOG_ERROR, "Subtitle Rectangle out of video bounds. x = %d, y = %d, video width = %d, video height = %d.\n", x, y, video_w, video_h); + x = 0; y =0; + } + /* Fill in dimensions */ + ctx->presentation->x = x; + ctx->presentation->y = y; + } + else if (block == 0x00) { + /* No useful information here as the subtitle is about to be blanked. + How do I blank a subtitle??? */ + } +} + +static void pgssub_parse_window_segment(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data; + int x, y, w, h; + +#ifdef DEBUG_PACKET_CONTENTS + int i; + + av_log(avctx, AV_LOG_INFO, "PGS window packet:\n"); + + for (i=0; i < buf_size; i++) { + av_log(avctx, AV_LOG_INFO, "%02x ", buf[i]); + } + + av_log(avctx, AV_LOG_INFO, "\n"); + +#endif + /* Skip 2 bytes of unknown, */ + buf += 2; + + x = AV_RB16(buf); + buf += 2; + + y = AV_RB16(buf); + buf += 2; + + w = AV_RB16(buf); + buf += 2; + + h = AV_RB16(buf); + buf += 2; + +#ifdef DEBUG + av_log(avctx, AV_LOG_INFO, "Window dimensions x=%d, y=%d, w=%d, h=%d\n", x, y, w, h); +#endif + + ctx->window->x = x; + ctx->window->y = y; + ctx->window->w = w; + ctx->window->h = h; + +} + + +#ifdef DEBUG_SAVE_IMAGES +#undef fprintf +#undef perror +#undef exit +static void ppm_save(const char *filename, uint8_t *bitmap, int w, int h, + uint32_t *rgba_palette) +{ + int x, y, v; + FILE *f; + + f = fopen(filename, "w"); + if (!f) { + perror(filename); + exit(1); + } + fprintf(f, "P6\n" + "%d %d\n" + "%d\n", + w, h, 255); + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + v = rgba_palette[bitmap[y * w + x]]; + putc((v >> 16) & 0xff, f); + putc((v >> 8) & 0xff, f); + putc((v >> 0) & 0xff, f); + } + } + fclose(f); +} +#endif + +static int pgssub_display_end_segment(AVCodecContext *avctx, + void *data, + const uint8_t *buf, int buf_size) +{ + AVSubtitle *sub = data; + PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data; + + sub->start_display_time = 0; + sub->end_display_time = 10000; + sub->format = 0; + + if (!sub->rects) { + sub->rects = av_mallocz(sizeof(*sub->rects)); + sub->rects[0] = av_mallocz(sizeof(*sub->rects[0])); + sub->num_rects = 1; + } + + sub->rects[0]->x = ctx->presentation->x; + sub->rects[0]->y = ctx->presentation->y; + sub->rects[0]->w = ctx->picture->w; + sub->rects[0]->h = ctx->picture->h; + sub->rects[0]->type = SUBTITLE_BITMAP; + + /* Allocate memory for bitmap */ + sub->rects[0]->pict.data[0] = av_malloc(ctx->picture->w * ctx->picture->h); + sub->rects[0]->pict.linesize[0] = ctx->picture->w; + + memcpy(sub->rects[0]->pict.data[0], ctx->picture->bitmap, ctx->picture->w * ctx->picture->h); + + /* Allocate memory for colours */ + sub->rects[0]->nb_colors = 256; + sub->rects[0]->pict.data[1] = av_mallocz(sub->rects[0]->nb_colors * sizeof(uint32_t)); + + memcpy(sub->rects[0]->pict.data[1], ctx->clut, sub->rects[0]->nb_colors * sizeof(uint32_t)); + +#ifdef DEBUG_SAVE_IMAGES + ppm_save("/tmp/a.ppm", sub->rects[0]->pict.data[0], + sub->rects[0]->w, sub->rects[0]->h, sub->rects[0]->pict.data[1]); +#endif + + return 1; +} + +static int pgssub_decode(AVCodecContext *avctx, + void *data, int *data_size, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + uint8_t segment_type; + int segment_length; + +#ifdef DEBUG_PACKET_CONTENTS + int i; + + av_log(avctx, AV_LOG_INFO, "PGS sub packet:\n"); + + for (i=0; i < buf_size; i++) { + av_log(avctx, AV_LOG_INFO, "%02x ", buf[i]); + if (i % 16 == 15) + av_log(avctx, AV_LOG_INFO, "\n"); + } + + if (i % 16) + av_log(avctx, AV_LOG_INFO, "\n"); + +#endif + + *data_size = 0; + + /* Ensure that we have received at a least a segment code and segment length */ + if (buf_size < 3) + return -1; + + buf_end = buf + buf_size; + + /* Step through buffer to identify segments */ + while (buf < buf_end) { + segment_type = AV_RB8(buf); + buf += 1; + segment_length = AV_RB16(buf); + buf += 2; + +#ifdef DEBUG + av_log(avctx, AV_LOG_INFO, "Segment Length %d, Segment Type %x\n", segment_length,segment_type); +#endif + + if (!(segment_type == PGSSUB_DISPLAY_SEGMENT) && (buf + segment_length > buf_end)) + break; + + switch (segment_type) { + case PGSSUB_PALETTE_SEGMENT: + pgssub_parse_palette_segment(avctx, buf, segment_length); + break; + case PGSSUB_PICTURE_SEGMENT: + pgssub_parse_picture_segment(avctx, buf, segment_length); + break; + case PGSSUB_PRESENTATION_SEGMENT: + pgssub_parse_presentation_segment(avctx, buf, segment_length); + break; + case PGSSUB_WINDOW_SEGMENT: + pgssub_parse_window_segment(avctx, buf, segment_length); + break; + case PGSSUB_DISPLAY_SEGMENT: + *data_size = pgssub_display_end_segment(avctx, data, buf, segment_length); + break; + default: +#ifdef DEBUG + av_log(avctx, AV_LOG_INFO, "Subtitling segment type 0x%x, length %d\n", + segment_type, segment_length); +#endif + break; + } + + buf += segment_length; + } + + return buf_size; +} + + +AVCodec pgssub_decoder = { + "pgssub", + CODEC_TYPE_SUBTITLE, + CODEC_ID_HDMV_PGS_SUBTITLE, + sizeof(PGSSubContext), + pgssub_init_decoder, + NULL, + pgssub_close_decoder, + pgssub_decode, + .long_name = NULL_IF_CONFIG_SMALL("HDMV Presentation Graphic Stream subtitles"), +}; Index: libs/libavcodec/myth_utils.c =================================================================== --- libs/libavcodec/myth_utils.c (revision 20970) +++ libs/libavcodec/myth_utils.c (working copy) @@ -201,6 +201,8 @@ /* subtitle codecs */ case CODEC_ID_DVD_SUBTITLE: return "DVD_SUBTITLE"; case CODEC_ID_DVB_SUBTITLE: return "DVB_SUBTITLE"; + case CODEC_ID_HDMV_PGS_SUBTITLE: + return "HDMV_PGS_SUBTITLE"; case CODEC_ID_MPEG2VBI: return "MPEG2VBI"; case CODEC_ID_DVB_VBI: return "DVB_VBI"; Index: libs/libavformat/mpegts.c =================================================================== --- libs/libavformat/mpegts.c (revision 20970) +++ libs/libavformat/mpegts.c (working copy) @@ -888,9 +888,11 @@ case STREAM_TYPE_AUDIO_AAC: case STREAM_TYPE_AUDIO_AC3: case STREAM_TYPE_AUDIO_DTS: + case STREAM_TYPE_AUDIO_HDMV_DTS: //case STREAM_TYPE_PRIVATE_DATA: case STREAM_TYPE_VBI_DVB: case STREAM_TYPE_SUBTITLE_DVB: + case STREAM_TYPE_SUBTITLE_PGS: case STREAM_TYPE_DSMCC_B: val = 1; break; @@ -1463,6 +1465,7 @@ codec_id = CODEC_ID_AC3; break; case STREAM_TYPE_AUDIO_DTS: + case STREAM_TYPE_AUDIO_HDMV_DTS: codec_type = CODEC_TYPE_AUDIO; codec_id = CODEC_ID_DTS; break; @@ -1474,6 +1477,10 @@ codec_type = CODEC_TYPE_SUBTITLE; codec_id = CODEC_ID_DVB_SUBTITLE; break; + case STREAM_TYPE_SUBTITLE_PGS: + codec_type = CODEC_TYPE_SUBTITLE; + codec_id = CODEC_ID_HDMV_PGS_SUBTITLE; + break; case STREAM_TYPE_DSMCC_B: codec_type = CODEC_TYPE_DATA; codec_id = CODEC_ID_DSMCC_B; Index: libs/libavformat/mpegts.h =================================================================== --- libs/libavformat/mpegts.h (revision 20970) +++ libs/libavformat/mpegts.h (working copy) @@ -61,8 +61,10 @@ #define STREAM_TYPE_AUDIO_AC3 0x81 #define STREAM_TYPE_AUDIO_DTS 0x8a +#define STREAM_TYPE_AUDIO_HDMV_DTS 0x82 #define STREAM_TYPE_SUBTITLE_DVB 0x100 +#define STREAM_TYPE_SUBTITLE_PGS 0x90 #define STREAM_TYPE_VBI_DVB 0x101 typedef struct MpegTSContext MpegTSContext;