Ticket #6748: bluray_subtitles_mythtv_trunk_21007.diff

File bluray_subtitles_mythtv_trunk_21007.diff, 18.3 KB (added by Stephen <stev391@…>, 15 years ago)

Updated patch with cleanups suggested by FFmpeg Developers.

  • libs/libavcodec/allcodecs.c

     
    302302    /* subtitles */
    303303    REGISTER_ENCDEC  (DVBSUB, dvbsub);
    304304    REGISTER_ENCDEC  (DVDSUB, dvdsub);
     305    REGISTER_DECODER (PGSSUB, pgssub);
    305306    REGISTER_ENCDEC  (XSUB, xsub);
    306307
    307308    /* external libraries */
  • libs/libavcodec/avcodec.h

     
    329329    CODEC_ID_XSUB,
    330330    CODEC_ID_SSA,
    331331    CODEC_ID_MOV_TEXT,
     332    CODEC_ID_HDMV_PGS_SUBTITLE,
    332333
    333334    /* teletext codecs */
    334335    CODEC_ID_MPEG2VBI,
  • libs/libavcodec/libavcodec.pro

     
    222222contains( CONFIG_PGM_ENCODER, yes )             { SOURCES *= pnmenc.c }
    223223contains( CONFIG_PGMYUV_DECODER, yes )          { SOURCES *= pnmenc.c pnm.c }
    224224contains( CONFIG_PGMYUV_ENCODER, yes )          { SOURCES *= pnmenc.c }
     225contains( CONFIG_PGSSUB_DECODER, yes )          { SOURCES *= pgssubdec.c }
    225226contains( CONFIG_PNG_DECODER, yes )             { SOURCES *= png.c pngdec.c }
    226227contains( CONFIG_PNG_ENCODER, yes )             { SOURCES *= png.c pngenc.c }
    227228contains( CONFIG_PPM_DECODER, yes )             { SOURCES *= pnmenc.c pnm.c }
  • libs/libavcodec/pgssubdec.c

     
     1/*
     2 * PGS subtitle decoding
     3 * Copyright (c) 2009 Stephen Backway
     4 *
     5 * This file is part of FFmpeg.
     6 *
     7 * FFmpeg is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU Lesser General Public
     9 * License as published by the Free Software Foundation; either
     10 * version 2.1 of the License, or (at your option) any later version.
     11 *
     12 * FFmpeg is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15 * Lesser General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU Lesser General Public
     18 * License along with FFmpeg; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     20 */
     21
     22/**
     23 * @file libavcodec/pgssubdec.c
     24 * PGS subtitle decoder
     25 */
     26
     27#include "avcodec.h"
     28#include "dsputil.h"
     29#include "colorspace.h"
     30#include "bytestream.h"
     31
     32//#define DEBUG_PACKET_CONTENTS
     33//#define DEBUG_SAVE_IMAGES
     34
     35#define PGSSUB_PALETTE_SEGMENT      0x14
     36#define PGSSUB_PICTURE_SEGMENT      0x15
     37#define PGSSUB_PRESENTATION_SEGMENT 0x16
     38#define PGSSUB_WINDOW_SEGMENT       0x17
     39#define PGSSUB_DISPLAY_SEGMENT      0x80
     40
     41#define cm (ff_cropTbl + MAX_NEG_CROP)
     42#define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
     43
     44typedef struct PGSSubPresentation {
     45    int x;
     46    int y;
     47    int video_w;
     48    int video_h;
     49    int id_number;
     50
     51} PGSSubPresentation;
     52
     53typedef struct PGSSubWindow {
     54    int x;
     55    int y;
     56    int w;
     57    int h;
     58
     59} PGSSubWindow;
     60
     61typedef struct PGSSubPicture {
     62    int w;
     63    int h;
     64
     65    uint8_t *bitmap;
     66
     67} PGSSubPicture;
     68
     69typedef struct PGSSubContext {
     70    PGSSubPresentation *presentation;
     71    PGSSubWindow       *window;
     72    uint32_t           clut[256];
     73    PGSSubPicture      *picture;
     74
     75} PGSSubContext;
     76
     77static av_cold int pgssub_init_decoder(AVCodecContext *avctx)
     78{
     79    avctx->pix_fmt     = PIX_FMT_RGB32;
     80    PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data;
     81
     82    ctx->presentation  = av_mallocz(sizeof(PGSSubPresentation));
     83    ctx->window        = av_mallocz(sizeof(PGSSubWindow));
     84    ctx->picture       = av_mallocz(sizeof(PGSSubPicture));
     85
     86    return 0;
     87}
     88
     89static av_cold int pgssub_close_decoder(AVCodecContext *avctx)
     90{
     91    PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data;
     92
     93    if (ctx->picture->bitmap)
     94        av_freep(&ctx->picture->bitmap);
     95
     96    av_freep(&ctx->presentation);
     97    av_freep(&ctx->window);
     98    av_freep(&ctx->picture);
     99    return 0;
     100}
     101
     102static void pgssub_parse_picture_segment(AVCodecContext *avctx,
     103                                         const uint8_t *buf, int buf_size)
     104{
     105    PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data;
     106
     107    uint8_t block, flags, colour, *rle_bitmap_end, sequence_desc;
     108    int rle_bitmap_len, pixel_count, line_count, run, width, height;
     109
     110    /* skip 3 unknown bytes: Object ID (2 bytes), Version Number */
     111    buf += 3;
     112
     113    /* Read the Sequence Description to determine if start of RLE data or Appended to previous RLE */
     114    sequence_desc = bytestream_get_byte(&buf);
     115
     116    if (!(sequence_desc & 0x80)) {
     117        av_log(avctx, AV_LOG_ERROR, "Decoder does not support object data over multiple packets.\n");
     118        return;
     119    }
     120
     121    /* Decode rle bitmap length */
     122    rle_bitmap_len = bytestream_get_be24(&buf);
     123
     124    /* Check to ensure we have enough data for rle_bitmap_length if just a single packet*/
     125    if (rle_bitmap_len > (buf_size - 7)) {
     126        av_log(avctx, AV_LOG_ERROR, "Not enough RLE data for specified length of %d.\n", rle_bitmap_len);
     127        return;
     128    }
     129
     130    rle_bitmap_end = buf + rle_bitmap_len;
     131
     132    /* Get bitmap dimensions from data */
     133    width  = bytestream_get_be16(&buf);
     134    height = bytestream_get_be16(&buf);
     135
     136    /* Make sure the bitmap is not too large. */
     137    if (ctx->presentation->video_w < width || ctx->presentation->video_h < height) {
     138        av_log(avctx, AV_LOG_ERROR, "Bitmap dimensions larger then video.\n");
     139        return;
     140    }
     141
     142    ctx->picture->w = width;
     143    ctx->picture->h = height;
     144
     145    ctx->picture->bitmap = av_malloc(width * height * sizeof(uint8_t));
     146
     147    pixel_count = 0;
     148    line_count  = 0;
     149
     150    while (buf < rle_bitmap_end && line_count < height) {
     151        block = bytestream_get_byte(&buf);
     152
     153        if (block == 0x00) {
     154            block = bytestream_get_byte(&buf);
     155            flags = block & 0xC0;
     156
     157            switch (flags) {
     158            case 0x00:
     159                run = block & 0x3F;
     160                if (run > 0)
     161                    colour = 0;
     162                break;
     163            case 0xC0:
     164                run = (block & 0x3F) << 8 | bytestream_get_byte(&buf);
     165                colour = bytestream_get_byte(&buf);
     166                break;
     167            case 0x80:
     168                run = block & 0x3F;
     169                colour = bytestream_get_byte(&buf);
     170                break;
     171            case 0x40:
     172                run = (block & 0x3F) << 8 | bytestream_get_byte(&buf);
     173                colour = 0;
     174                break;
     175            default:
     176                av_log(avctx, AV_LOG_ERROR, "Unknown RLE code.\n");
     177                run = -1;
     178                break;
     179            }
     180        } else {
     181            run = 1;
     182            colour = block;
     183        }
     184
     185        if (run > 0) {
     186            memset(ctx->picture->bitmap + pixel_count, colour, run);
     187            pixel_count += run;
     188        } else if (run == 0) {
     189            /* New Line. Check if correct pixels decoded,
     190               if not display warning and adjust bitmap
     191               pointer to correct new line position. */
     192            if (pixel_count % width == width - 1)
     193                av_log(avctx, AV_LOG_ERROR, "Decoded %d pixels, when line should be %d pixels\n",
     194                       pixel_count % width, width);
     195            line_count++;
     196        }
     197    }
     198
     199    dprintf(avctx, "Pixel Count = %d, Area = %d\n", pixel_count, width * height);
     200}
     201
     202static void pgssub_parse_palette_segment(AVCodecContext *avctx,
     203                                         const uint8_t *buf, int buf_size)
     204{
     205    PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data;
     206
     207    const uint8_t *buf_end = buf + buf_size;
     208    int colour_id, max_colour_id;
     209    int y, cb, cr, alpha;
     210    int r, g, b, r_add, g_add, b_add;
     211
     212    max_colour_id = (buf_size - 2) % 5;
     213
     214    /* Check to ensure that the buffer provided is not larger then the maximum palette */
     215    if (max_colour_id > 255) {
     216        av_log(avctx, AV_LOG_INFO, "max_colour_id to large at %d\n", max_colour_id);
     217        return;
     218    }
     219
     220    /* Skip two null bytes */
     221    buf += 2;
     222
     223    while (buf < buf_end) {
     224        colour_id = bytestream_get_byte(&buf);
     225        y         = bytestream_get_byte(&buf);
     226        cb        = bytestream_get_byte(&buf);
     227        cr        = bytestream_get_byte(&buf);
     228        alpha     = bytestream_get_byte(&buf);
     229
     230        YUV_TO_RGB1(cb, cr);
     231        YUV_TO_RGB2(r, g, b, y);
     232
     233        dprintf(avctx, "Colour %d := (%d,%d,%d,%d)\n", colour_id, r, g, b, alpha);
     234
     235        /* Store colour in palette */
     236        if (colour_id < 255)
     237            ctx->clut[colour_id] = RGBA(r,g,b,alpha);
     238    }
     239}
     240
     241static void pgssub_parse_presentation_segment(AVCodecContext *avctx,
     242                                              const uint8_t *buf, int buf_size)
     243{
     244    PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data;
     245
     246    int x, y, video_w, video_h;
     247    uint8_t block;
     248
     249    video_w = bytestream_get_be16(&buf);
     250    video_h = bytestream_get_be16(&buf);
     251
     252    dprintf(avctx, "Video Dimensions %dx%d\n", video_w, video_h);
     253
     254    ctx->presentation->video_w = video_w;
     255    ctx->presentation->video_h = video_h;
     256
     257    /* Skip 1 bytes of unknown, frame rate? */
     258    buf += 1;
     259
     260    ctx->presentation->id_number = bytestream_get_be16(&buf);
     261
     262    /* Next byte is the state. */
     263    block = bytestream_get_byte(&buf);
     264    if (block == 0x80) {
     265        /* Skip 7 bytes (+1 for previous byte) of unknown:
     266               palette_update_flag (0x80),
     267               palette_id_to_use,
     268               Object Number (if > 0 determines if more data to process),
     269               object_id_ref (2 bytes),
     270               window_id_ref,
     271               composition_flag (0x80 - object cropped, 0x40 - object forced) */
     272        buf += 7;
     273
     274        x = bytestream_get_be16(&buf);
     275        y = bytestream_get_be16(&buf);
     276
     277        /* TODO If cropping, cropping_x, cropping_y, cropping_width, cropping Height (all 2 bytes).*/
     278
     279        dprintf(avctx, "Subtitle Placement x=%d, y=%d\n", x, y);
     280
     281        if (x > video_w || y > video_h) {
     282            av_log(avctx, AV_LOG_ERROR, "Subtitle out of video bounds. x = %d, y = %d, video width = %d, video height = %d.\n",
     283                   x, y, video_w, video_h);
     284            x = 0; y =0;
     285        }
     286        /* Fill in dimensions */
     287        ctx->presentation->x = x;
     288        ctx->presentation->y = y;
     289    } else if (block == 0x00) {
     290        /* TODO: Blank context as subtitle should not be displayed.
     291                 If the subtitle is blanked now the subtitle is not
     292                 on screen long enough to read, due to a delay in
     293                 initial display timing. */
     294    }
     295}
     296
     297static void pgssub_parse_window_segment(AVCodecContext *avctx,
     298                                        const uint8_t *buf, int buf_size)
     299{
     300    PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data;
     301    int x, y, w, h;
     302
     303    /* Skip 2 bytes of unknown, */
     304    buf += 2;
     305
     306    x = bytestream_get_be16(&buf);
     307    y = bytestream_get_be16(&buf);
     308    w = bytestream_get_be16(&buf);
     309    h = bytestream_get_be16(&buf);
     310
     311    dprintf(avctx, "Window dimensions x=%d, y=%d, w=%d, h=%d\n", x, y, w, h);
     312
     313    ctx->window->x = x;
     314    ctx->window->y = y;
     315    ctx->window->w = w;
     316    ctx->window->h = h;
     317
     318}
     319
     320#ifdef DEBUG_SAVE_IMAGES
     321#undef fprintf
     322#undef perror
     323#undef exit
     324static void ppm_save(const char *filename, uint8_t *bitmap, int w, int h,
     325                     uint32_t *rgba_palette)
     326{
     327    int x, y, v;
     328    FILE *f;
     329
     330    f = fopen(filename, "w");
     331    if (!f) {
     332        perror(filename);
     333        exit(1);
     334    }
     335    fprintf(f, "P6\n"
     336            "%d %d\n"
     337            "%d\n",
     338            w, h, 255);
     339    for(y = 0; y < h; y++) {
     340        for(x = 0; x < w; x++) {
     341            v = rgba_palette[bitmap[y * w + x]];
     342            putc((v >> 16) & 0xff, f);
     343            putc((v >> 8) & 0xff, f);
     344            putc((v >> 0) & 0xff, f);
     345        }
     346    }
     347    fclose(f);
     348}
     349#endif
     350
     351static int pgssub_display_end_segment(AVCodecContext *avctx,
     352                                        void *data,
     353                                        const uint8_t *buf, int buf_size)
     354{
     355    AVSubtitle    *sub = data;
     356    PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data;
     357
     358    sub->start_display_time = 0;
     359    sub->end_display_time   = 20000;
     360    sub->format             = 0;
     361
     362    if (!sub->rects) {
     363        sub->rects     = av_mallocz(sizeof(*sub->rects));
     364        sub->rects[0]  = av_mallocz(sizeof(*sub->rects[0]));
     365        sub->num_rects = 1;
     366    }
     367
     368    sub->rects[0]->x    = ctx->presentation->x;
     369    sub->rects[0]->y    = ctx->presentation->y;
     370    sub->rects[0]->w    = ctx->picture->w;
     371    sub->rects[0]->h    = ctx->picture->h;
     372    sub->rects[0]->type = SUBTITLE_BITMAP;
     373
     374    /* Allocate memory for bitmap */
     375    sub->rects[0]->pict.data[0]     = av_malloc(ctx->picture->w * ctx->picture->h);
     376    sub->rects[0]->pict.linesize[0] = ctx->picture->w;
     377
     378    if (ctx->picture->bitmap)
     379        memcpy(sub->rects[0]->pict.data[0], ctx->picture->bitmap, ctx->picture->w * ctx->picture->h);
     380
     381    /* Allocate memory for colours */
     382    sub->rects[0]->nb_colors    = 256;
     383    sub->rects[0]->pict.data[1] = av_mallocz(sub->rects[0]->nb_colors * sizeof(uint32_t));
     384
     385    memcpy(sub->rects[0]->pict.data[1], ctx->clut, sub->rects[0]->nb_colors * sizeof(uint32_t));
     386
     387#ifdef DEBUG_SAVE_IMAGES
     388    ppm_save("/tmp/a.ppm", sub->rects[0]->pict.data[0],
     389             sub->rects[0]->w, sub->rects[0]->h, sub->rects[0]->pict.data[1]);
     390#endif
     391
     392    return 1;
     393}
     394
     395static int pgssub_decode(AVCodecContext *avctx,
     396                         void *data, int *data_size,
     397                         AVPacket *avpkt)
     398{
     399    const uint8_t *buf = avpkt->data;
     400    int buf_size       = avpkt->size;
     401    const uint8_t *buf_end;
     402    uint8_t segment_type;
     403    int segment_length;
     404
     405#ifdef DEBUG_PACKET_CONTENTS
     406    int i;
     407
     408    av_log(avctx, AV_LOG_INFO, "PGS sub packet:\n");
     409
     410    for (i = 0; i < buf_size; i++) {
     411        av_log(avctx, AV_LOG_INFO, "%02x ", buf[i]);
     412        if (i % 16 == 15)
     413            av_log(avctx, AV_LOG_INFO, "\n");
     414    }
     415
     416    if (i % 16)
     417        av_log(avctx, AV_LOG_INFO, "\n");
     418#endif
     419
     420    *data_size = 0;
     421
     422    /* Ensure that we have received at a least a segment code and segment length */
     423    if (buf_size < 3)
     424        return -1;
     425
     426    buf_end = buf + buf_size;
     427
     428    /* Step through buffer to identify segments */
     429    while (buf < buf_end) {
     430        segment_type   = bytestream_get_byte(&buf);
     431        segment_length = bytestream_get_be16(&buf);
     432
     433        dprintf(avctx, "Segment Length %d, Segment Type %x\n", segment_length, segment_type);
     434
     435        if (!(segment_type == PGSSUB_DISPLAY_SEGMENT) && (buf + segment_length > buf_end))
     436            break;
     437
     438        switch (segment_type) {
     439        case PGSSUB_PALETTE_SEGMENT:
     440            pgssub_parse_palette_segment(avctx, buf, segment_length);
     441            break;
     442        case PGSSUB_PICTURE_SEGMENT:
     443            pgssub_parse_picture_segment(avctx, buf, segment_length);
     444            break;
     445        case PGSSUB_PRESENTATION_SEGMENT:
     446            pgssub_parse_presentation_segment(avctx, buf, segment_length);
     447            break;
     448        case PGSSUB_WINDOW_SEGMENT:
     449            pgssub_parse_window_segment(avctx, buf, segment_length);
     450            break;
     451        case PGSSUB_DISPLAY_SEGMENT:
     452            *data_size = pgssub_display_end_segment(avctx, data, buf, segment_length);
     453            break;
     454        default:
     455            av_log(avctx, AV_LOG_ERROR, "Unknown subtitle segment type 0x%x, length %d\n",
     456                   segment_type, segment_length);
     457            break;
     458        }
     459
     460        buf += segment_length;
     461    }
     462
     463    return buf_size;
     464}
     465
     466AVCodec pgssub_decoder = {
     467    "pgssub",
     468    CODEC_TYPE_SUBTITLE,
     469    CODEC_ID_HDMV_PGS_SUBTITLE,
     470    sizeof(PGSSubContext),
     471    pgssub_init_decoder,
     472    NULL,
     473    pgssub_close_decoder,
     474    pgssub_decode,
     475    .long_name = NULL_IF_CONFIG_SMALL("HDMV Presentation Graphic Stream subtitles"),
     476};
  • libs/libavcodec/myth_utils.c

     
    201201            /* subtitle codecs */
    202202        case CODEC_ID_DVD_SUBTITLE:     return "DVD_SUBTITLE";
    203203        case CODEC_ID_DVB_SUBTITLE:     return "DVB_SUBTITLE";
     204        case CODEC_ID_HDMV_PGS_SUBTITLE:
     205             return "HDMV_PGS_SUBTITLE";
    204206
    205207        case CODEC_ID_MPEG2VBI:         return "MPEG2VBI";
    206208        case CODEC_ID_DVB_VBI:          return "DVB_VBI";
  • libs/libavformat/mpegts.c

     
    577577    { 0x84, CODEC_TYPE_AUDIO, CODEC_ID_AC3 },
    578578    { 0x85, CODEC_TYPE_AUDIO, CODEC_ID_DTS },
    579579    { 0x86, CODEC_TYPE_AUDIO, CODEC_ID_DTS },
     580    { 0x90, CODEC_TYPE_SUBTITLE, CODEC_ID_HDMV_PGS_SUBTITLE },
    580581    { 0 },
    581582};
    582583
     
    10091010            //case STREAM_TYPE_PRIVATE_DATA:
    10101011        case STREAM_TYPE_VBI_DVB:
    10111012        case STREAM_TYPE_SUBTITLE_DVB:
     1013        case STREAM_TYPE_SUBTITLE_PGS:
    10121014        case STREAM_TYPE_DSMCC_B:
    10131015            val = 1;
    10141016            break;
     
    15921594            codec_type = CODEC_TYPE_SUBTITLE;
    15931595            codec_id = CODEC_ID_DVB_SUBTITLE;
    15941596            break;
     1597        case STREAM_TYPE_SUBTITLE_PGS:
     1598            codec_type = CODEC_TYPE_SUBTITLE;
     1599            codec_id = CODEC_ID_HDMV_PGS_SUBTITLE;
     1600            break;
    15951601        case STREAM_TYPE_DSMCC_B:
    15961602            codec_type = CODEC_TYPE_DATA;
    15971603            codec_id = CODEC_ID_DSMCC_B;
  • libs/libavformat/mpegts.h

     
    6868#define STREAM_TYPE_AUDIO_HDMV_DTS_HD_MASTER 0x86
    6969
    7070#define STREAM_TYPE_SUBTITLE_DVB    0x100
     71#define STREAM_TYPE_SUBTITLE_PGS    0x90
    7172#define STREAM_TYPE_VBI_DVB         0x101
    7273
    7374typedef struct MpegTSContext MpegTSContext;