Ticket #6748: bluray_subtitles_mythtv_trunk_21011.diff

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

Subtitles appearing (by overriding scale factor)

  • libs/libmythtv/NuppelVideoPlayer.cpp

     
    71487148                if (player_ctx->buffer->isDVD())
    71497149                    vsize = (float) video_disp_dim.height();
    71507150
    7151                 float hmult = osd->GetSubtitleBounds().width() / 720.0;
    7152                 float vmult = osd->GetSubtitleBounds().height() / vsize;
     7151//                float hmult = osd->GetSubtitleBounds().width() / 720.0;
     7152//                float vmult = osd->GetSubtitleBounds().height() / vsize;
     7153                float hmult = 1.0;
     7154                float vmult = 1.0;
    71537155
    7154                 rect->x = (int)(rect->x * hmult);
    7155                 rect->y = (int)(rect->y * vmult);
    7156                 rect->w = (int)(rect->w * hmult);
    7157                 rect->h = (int)(rect->h * vmult);
     7156                rect->x = (int)(rect->x / hmult);
     7157                rect->y = (int)(rect->y / vmult);
     7158                rect->w = (int)(rect->w / hmult);
     7159                rect->h = (int)(rect->h / vmult);
    71587160
    71597161                if (hmult < 0.98 || hmult > 1.02 || vmult < 0.98 || hmult > 1.02)
    71607162                    qImage = qImage.scaled(rect->w, rect->h,
  • 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 decoder
     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} PGSSubPresentation;
     51
     52typedef struct PGSSubPicture {
     53    int w;
     54    int h;
     55    uint8_t *bitmap;
     56} PGSSubPicture;
     57
     58typedef struct PGSSubContext {
     59    PGSSubPresentation *presentation;
     60    uint32_t           clut[256];
     61    PGSSubPicture      *picture;
     62} PGSSubContext;
     63
     64static av_cold int pgssub_init_decoder(AVCodecContext *avctx)
     65{
     66    avctx->pix_fmt     = PIX_FMT_RGB32;
     67    PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data;
     68
     69    ctx->presentation  = av_mallocz(sizeof(PGSSubPresentation));
     70    ctx->picture       = av_mallocz(sizeof(PGSSubPicture));
     71    return 0;
     72}
     73
     74static av_cold int pgssub_close_decoder(AVCodecContext *avctx)
     75{
     76    PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data;
     77
     78    if (ctx->picture->bitmap)
     79        av_freep(&ctx->picture->bitmap);
     80
     81    av_freep(&ctx->presentation);
     82    av_freep(&ctx->picture);
     83    return 0;
     84}
     85
     86static void pgssub_parse_picture_segment(AVCodecContext *avctx,
     87                                         const uint8_t *buf, int buf_size)
     88{
     89    PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data;
     90
     91    uint8_t block, flags, colour, *rle_bitmap_end, sequence_desc;
     92    int rle_bitmap_len, pixel_count, line_count, run, width, height;
     93
     94    /* skip 3 unknown bytes: Object ID (2 bytes), Version Number */
     95    buf += 3;
     96
     97    /* Read the Sequence Description to determine if start of RLE data or Appended to previous RLE */
     98    sequence_desc = bytestream_get_byte(&buf);
     99
     100    if (!(sequence_desc & 0x80)) {
     101        av_log(avctx, AV_LOG_ERROR, "Decoder does not support object data over multiple packets.\n");
     102        return;
     103    }
     104
     105    /* Decode rle bitmap length */
     106    rle_bitmap_len = bytestream_get_be24(&buf);
     107
     108    /* Check to ensure we have enough data for rle_bitmap_length if just a single packet*/
     109    if (rle_bitmap_len > (buf_size - 7)) {
     110        av_log(avctx, AV_LOG_ERROR, "Not enough RLE data for specified length of %d.\n", rle_bitmap_len);
     111        return;
     112    }
     113
     114    rle_bitmap_end = buf + rle_bitmap_len;
     115
     116    /* Get bitmap dimensions from data */
     117    width  = bytestream_get_be16(&buf);
     118    height = bytestream_get_be16(&buf);
     119
     120    /* Make sure the bitmap is not too large. */
     121    if (ctx->presentation->video_w < width || ctx->presentation->video_h < height) {
     122        av_log(avctx, AV_LOG_ERROR, "Bitmap dimensions larger then video.\n");
     123        return;
     124    }
     125
     126    ctx->picture->w = width;
     127    ctx->picture->h = height;
     128
     129    ctx->picture->bitmap = av_malloc(width * height * sizeof(uint8_t));
     130
     131    pixel_count = 0;
     132    line_count  = 0;
     133
     134    while (buf < rle_bitmap_end && line_count < height) {
     135        block = bytestream_get_byte(&buf);
     136
     137        if (block == 0x00) {
     138            block = bytestream_get_byte(&buf);
     139            flags = block & 0xC0;
     140
     141            switch (flags) {
     142            case 0x00:
     143                run = block & 0x3F;
     144                if (run > 0)
     145                    colour = 0;
     146                break;
     147            case 0xC0:
     148                run = (block & 0x3F) << 8 | bytestream_get_byte(&buf);
     149                colour = bytestream_get_byte(&buf);
     150                break;
     151            case 0x80:
     152                run = block & 0x3F;
     153                colour = bytestream_get_byte(&buf);
     154                break;
     155            case 0x40:
     156                run = (block & 0x3F) << 8 | bytestream_get_byte(&buf);
     157                colour = 0;
     158                break;
     159            default:
     160                av_log(avctx, AV_LOG_ERROR, "Unknown RLE code.\n");
     161                run = -1;
     162                break;
     163            }
     164        } else {
     165            run = 1;
     166            colour = block;
     167        }
     168
     169        if (run > 0) {
     170            memset(ctx->picture->bitmap + pixel_count, colour, run);
     171            pixel_count += run;
     172        } else if (run == 0) {
     173            /**
     174             * New Line. Check if correct pixels decoded,
     175             * if not display warning and adjust bitmap
     176             * pointer to correct new line position.
     177             */
     178            if (pixel_count % width == width - 1)
     179                av_log(avctx, AV_LOG_ERROR, "Decoded %d pixels, when line should be %d pixels\n",
     180                       pixel_count % width, width);
     181            line_count++;
     182        }
     183    }
     184
     185    dprintf(avctx, "Pixel Count = %d, Area = %d\n", pixel_count, width * height);
     186}
     187
     188static void pgssub_parse_palette_segment(AVCodecContext *avctx,
     189                                         const uint8_t *buf, int buf_size)
     190{
     191    PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data;
     192
     193    const uint8_t *buf_end = buf + buf_size;
     194    int colour_id, max_colour_id;
     195    int y, cb, cr, alpha;
     196    int r, g, b, r_add, g_add, b_add;
     197
     198    max_colour_id = (buf_size - 2) % 5;
     199
     200    /* Check to ensure that the buffer provided is not larger then the maximum palette */
     201    if (max_colour_id > 255) {
     202        av_log(avctx, AV_LOG_INFO, "Palette Packet too large, pontentially %d colours defined.\n",
     203               max_colour_id);
     204        return;
     205    }
     206
     207    /* Skip two null bytes */
     208    buf += 2;
     209
     210    while (buf < buf_end) {
     211        colour_id = bytestream_get_byte(&buf);
     212        y         = bytestream_get_byte(&buf);
     213        cb        = bytestream_get_byte(&buf);
     214        cr        = bytestream_get_byte(&buf);
     215        alpha     = bytestream_get_byte(&buf);
     216
     217        YUV_TO_RGB1(cb, cr);
     218        YUV_TO_RGB2(r, g, b, y);
     219
     220        dprintf(avctx, "Colour %d := (%d,%d,%d,%d)\n", colour_id, r, g, b, alpha);
     221
     222        /* Store colour in palette */
     223        if (colour_id < 255)
     224            ctx->clut[colour_id] = RGBA(r,g,b,alpha);
     225    }
     226}
     227
     228static void pgssub_parse_presentation_segment(AVCodecContext *avctx,
     229                                              const uint8_t *buf, int buf_size)
     230{
     231    PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data;
     232
     233    int x, y;
     234    uint8_t block;
     235
     236    ctx->presentation->video_w = bytestream_get_be16(&buf);
     237    ctx->presentation->video_h = bytestream_get_be16(&buf);
     238
     239    dprintf(avctx, "Video Dimensions %dx%d\n",
     240            ctx->presentation->video_w, ctx->presentation->video_h);
     241
     242    /* Skip 1 bytes of unknown, frame rate? */
     243    buf += 1;
     244
     245    ctx->presentation->id_number = bytestream_get_be16(&buf);
     246
     247    /* Next byte is the state. */
     248    block = bytestream_get_byte(&buf);
     249    if (block == 0x80) {
     250        /**
     251         * Skip 7 bytes (+1 for previous byte) of unknown:
     252         *     palette_update_flag (0x80),
     253         *     palette_id_to_use,
     254         *     Object Number (if > 0 determines if more data to process),
     255         *     object_id_ref (2 bytes),
     256         *     window_id_ref,
     257         *     composition_flag (0x80 - object cropped, 0x40 - object forced)
     258         */
     259        buf += 7;
     260
     261        x = bytestream_get_be16(&buf);
     262        y = bytestream_get_be16(&buf);
     263
     264        /* TODO If cropping, cropping_x, cropping_y, cropping_width, cropping_height (all 2 bytes).*/
     265
     266        dprintf(avctx, "Subtitle Placement x=%d, y=%d\n", x, y);
     267
     268        if (x > ctx->presentation->video_w || y > ctx->presentation->video_h) {
     269            av_log(avctx, AV_LOG_ERROR, "Subtitle out of video bounds. x = %d, y = %d, video width = %d, video height = %d.\n",
     270                   x, y, ctx->presentation->video_w, ctx->presentation->video_h);
     271            x = 0; y =0;
     272        }
     273
     274        /* Fill in dimensions */
     275        ctx->presentation->x = x;
     276        ctx->presentation->y = y;
     277    } else if (block == 0x00) {
     278        /* TODO: Blank context as subtitle should not be displayed.
     279         *       If the subtitle is blanked now the subtitle is not
     280         *       on screen long enough to read, due to a delay in
     281         *       initial display timing.
     282         */
     283    }
     284}
     285
     286#ifdef DEBUG_SAVE_IMAGES
     287#undef fprintf
     288#undef perror
     289#undef exit
     290static void ppm_save(const char *filename, uint8_t *bitmap, int w, int h,
     291                     uint32_t *rgba_palette)
     292{
     293    int x, y, v;
     294    FILE *f;
     295
     296    f = fopen(filename, "w");
     297    if (!f) {
     298        perror(filename);
     299        exit(1);
     300    }
     301    fprintf(f, "P6\n"
     302            "%d %d\n"
     303            "%d\n",
     304            w, h, 255);
     305    for (y = 0; y < h; y++) {
     306        for (x = 0; x < w; x++) {
     307            v = rgba_palette[bitmap[y * w + x]];
     308            putc((v >> 16) & 0xff, f);
     309            putc((v >> 8) & 0xff, f);
     310            putc((v >> 0) & 0xff, f);
     311        }
     312    }
     313    fclose(f);
     314}
     315#endif
     316
     317static int pgssub_display_end_segment(AVCodecContext *avctx,
     318                                      void *data,
     319                                      const uint8_t *buf, int buf_size)
     320{
     321    AVSubtitle    *sub = data;
     322    PGSSubContext *ctx = (PGSSubContext*) avctx->priv_data;
     323
     324    sub->start_display_time = 0;
     325    sub->end_display_time   = 20000;
     326    sub->format             = 0;
     327
     328    if (!sub->rects) {
     329        sub->rects     = av_mallocz(sizeof(*sub->rects));
     330        sub->rects[0]  = av_mallocz(sizeof(*sub->rects[0]));
     331        sub->num_rects = 1;
     332    }
     333
     334    sub->rects[0]->x    = ctx->presentation->x;
     335    sub->rects[0]->y    = ctx->presentation->y;
     336    sub->rects[0]->w    = ctx->picture->w;
     337    sub->rects[0]->h    = ctx->picture->h;
     338    sub->rects[0]->type = SUBTITLE_BITMAP;
     339
     340    /* Allocate memory for bitmap */
     341    sub->rects[0]->pict.data[0]     = av_malloc(ctx->picture->w * ctx->picture->h);
     342    sub->rects[0]->pict.linesize[0] = ctx->picture->w;
     343
     344    if (ctx->picture->bitmap)
     345        memcpy(sub->rects[0]->pict.data[0], ctx->picture->bitmap, ctx->picture->w * ctx->picture->h);
     346
     347    /* Allocate memory for colours */
     348    sub->rects[0]->nb_colors    = 256;
     349    sub->rects[0]->pict.data[1] = av_mallocz(sub->rects[0]->nb_colors * sizeof(uint32_t));
     350
     351    memcpy(sub->rects[0]->pict.data[1], ctx->clut, sub->rects[0]->nb_colors * sizeof(uint32_t));
     352
     353#ifdef DEBUG_SAVE_IMAGES
     354    ppm_save("/tmp/a.ppm", sub->rects[0]->pict.data[0],
     355             sub->rects[0]->w, sub->rects[0]->h, sub->rects[0]->pict.data[1]);
     356#endif
     357
     358    return 1;
     359}
     360
     361static int pgssub_decode(AVCodecContext *avctx,
     362                         void *data, int *data_size,
     363                         AVPacket *avpkt)
     364{
     365    const uint8_t *buf = avpkt->data;
     366    int buf_size       = avpkt->size;
     367    const uint8_t *buf_end;
     368    uint8_t segment_type;
     369    int segment_length;
     370
     371#ifdef DEBUG_PACKET_CONTENTS
     372    int i;
     373
     374    av_log(avctx, AV_LOG_INFO, "PGS sub packet:\n");
     375
     376    for (i = 0; i < buf_size; i++) {
     377        av_log(avctx, AV_LOG_INFO, "%02x ", buf[i]);
     378        if (i % 16 == 15)
     379            av_log(avctx, AV_LOG_INFO, "\n");
     380    }
     381
     382    if (i % 16)
     383        av_log(avctx, AV_LOG_INFO, "\n");
     384#endif
     385
     386    *data_size = 0;
     387
     388    /* Ensure that we have received at a least a segment code and segment length */
     389    if (buf_size < 3)
     390        return -1;
     391
     392    buf_end = buf + buf_size;
     393
     394    /* Step through buffer to identify segments */
     395    while (buf < buf_end) {
     396        segment_type   = bytestream_get_byte(&buf);
     397        segment_length = bytestream_get_be16(&buf);
     398
     399        dprintf(avctx, "Segment Length %d, Segment Type %x\n", segment_length, segment_type);
     400
     401        if (!(segment_type == PGSSUB_DISPLAY_SEGMENT) && (buf + segment_length > buf_end))
     402            break;
     403
     404        switch (segment_type) {
     405        case PGSSUB_PALETTE_SEGMENT:
     406            pgssub_parse_palette_segment(avctx, buf, segment_length);
     407            break;
     408        case PGSSUB_PICTURE_SEGMENT:
     409            pgssub_parse_picture_segment(avctx, buf, segment_length);
     410            break;
     411        case PGSSUB_PRESENTATION_SEGMENT:
     412            pgssub_parse_presentation_segment(avctx, buf, segment_length);
     413            break;
     414        case PGSSUB_WINDOW_SEGMENT:
     415            /**
     416             * Window Segment Structure (No new information provided):
     417             *     2 bytes: Unkown,
     418             *     2 bytes: X position of subtitle,
     419             *     2 bytes: Y position of subtitle,
     420             *     2 bytes: Width of subtitle,
     421             *     2 bytes: Height of subtitle.
     422             */
     423            break;
     424        case PGSSUB_DISPLAY_SEGMENT:
     425            *data_size = pgssub_display_end_segment(avctx, data, buf, segment_length);
     426            break;
     427        default:
     428            av_log(avctx, AV_LOG_ERROR, "Unknown subtitle segment type 0x%x, length %d\n",
     429                   segment_type, segment_length);
     430            break;
     431        }
     432
     433        buf += segment_length;
     434    }
     435
     436    return buf_size;
     437}
     438
     439AVCodec pgssub_decoder = {
     440    "pgssub",
     441    CODEC_TYPE_SUBTITLE,
     442    CODEC_ID_HDMV_PGS_SUBTITLE,
     443    sizeof(PGSSubContext),
     444    pgssub_init_decoder,
     445    NULL,
     446    pgssub_close_decoder,
     447    pgssub_decode,
     448    .long_name = NULL_IF_CONFIG_SMALL("HDMV Presentation Graphic Stream subtitles"),
     449};
  • 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;