1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * PGS subtitle decoder 3cabdff1aSopenharmony_ci * Copyright (c) 2009 Stephen Backway 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * PGS subtitle decoder 25cabdff1aSopenharmony_ci */ 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include "avcodec.h" 28cabdff1aSopenharmony_ci#include "bytestream.h" 29cabdff1aSopenharmony_ci#include "codec_internal.h" 30cabdff1aSopenharmony_ci#include "internal.h" 31cabdff1aSopenharmony_ci#include "mathops.h" 32cabdff1aSopenharmony_ci 33cabdff1aSopenharmony_ci#include "libavutil/colorspace.h" 34cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 35cabdff1aSopenharmony_ci#include "libavutil/opt.h" 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_ci#define RGBA(r,g,b,a) (((unsigned)(a) << 24) | ((r) << 16) | ((g) << 8) | (b)) 38cabdff1aSopenharmony_ci#define MAX_EPOCH_PALETTES 8 // Max 8 allowed per PGS epoch 39cabdff1aSopenharmony_ci#define MAX_EPOCH_OBJECTS 64 // Max 64 allowed per PGS epoch 40cabdff1aSopenharmony_ci#define MAX_OBJECT_REFS 2 // Max objects per display set 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_cienum SegmentType { 43cabdff1aSopenharmony_ci PALETTE_SEGMENT = 0x14, 44cabdff1aSopenharmony_ci OBJECT_SEGMENT = 0x15, 45cabdff1aSopenharmony_ci PRESENTATION_SEGMENT = 0x16, 46cabdff1aSopenharmony_ci WINDOW_SEGMENT = 0x17, 47cabdff1aSopenharmony_ci DISPLAY_SEGMENT = 0x80, 48cabdff1aSopenharmony_ci}; 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_citypedef struct PGSSubObjectRef { 51cabdff1aSopenharmony_ci int id; 52cabdff1aSopenharmony_ci int window_id; 53cabdff1aSopenharmony_ci uint8_t composition_flag; 54cabdff1aSopenharmony_ci int x; 55cabdff1aSopenharmony_ci int y; 56cabdff1aSopenharmony_ci int crop_x; 57cabdff1aSopenharmony_ci int crop_y; 58cabdff1aSopenharmony_ci int crop_w; 59cabdff1aSopenharmony_ci int crop_h; 60cabdff1aSopenharmony_ci} PGSSubObjectRef; 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_citypedef struct PGSSubPresentation { 63cabdff1aSopenharmony_ci int id_number; 64cabdff1aSopenharmony_ci int palette_id; 65cabdff1aSopenharmony_ci int object_count; 66cabdff1aSopenharmony_ci PGSSubObjectRef objects[MAX_OBJECT_REFS]; 67cabdff1aSopenharmony_ci int64_t pts; 68cabdff1aSopenharmony_ci} PGSSubPresentation; 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_citypedef struct PGSSubObject { 71cabdff1aSopenharmony_ci int id; 72cabdff1aSopenharmony_ci int w; 73cabdff1aSopenharmony_ci int h; 74cabdff1aSopenharmony_ci uint8_t *rle; 75cabdff1aSopenharmony_ci unsigned int rle_buffer_size, rle_data_len; 76cabdff1aSopenharmony_ci unsigned int rle_remaining_len; 77cabdff1aSopenharmony_ci} PGSSubObject; 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_citypedef struct PGSSubObjects { 80cabdff1aSopenharmony_ci int count; 81cabdff1aSopenharmony_ci PGSSubObject object[MAX_EPOCH_OBJECTS]; 82cabdff1aSopenharmony_ci} PGSSubObjects; 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_citypedef struct PGSSubPalette { 85cabdff1aSopenharmony_ci int id; 86cabdff1aSopenharmony_ci uint32_t clut[256]; 87cabdff1aSopenharmony_ci} PGSSubPalette; 88cabdff1aSopenharmony_ci 89cabdff1aSopenharmony_citypedef struct PGSSubPalettes { 90cabdff1aSopenharmony_ci int count; 91cabdff1aSopenharmony_ci PGSSubPalette palette[MAX_EPOCH_PALETTES]; 92cabdff1aSopenharmony_ci} PGSSubPalettes; 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_citypedef struct PGSSubContext { 95cabdff1aSopenharmony_ci AVClass *class; 96cabdff1aSopenharmony_ci PGSSubPresentation presentation; 97cabdff1aSopenharmony_ci PGSSubPalettes palettes; 98cabdff1aSopenharmony_ci PGSSubObjects objects; 99cabdff1aSopenharmony_ci int forced_subs_only; 100cabdff1aSopenharmony_ci} PGSSubContext; 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_cistatic void flush_cache(AVCodecContext *avctx) 103cabdff1aSopenharmony_ci{ 104cabdff1aSopenharmony_ci PGSSubContext *ctx = avctx->priv_data; 105cabdff1aSopenharmony_ci int i; 106cabdff1aSopenharmony_ci 107cabdff1aSopenharmony_ci for (i = 0; i < ctx->objects.count; i++) { 108cabdff1aSopenharmony_ci av_freep(&ctx->objects.object[i].rle); 109cabdff1aSopenharmony_ci ctx->objects.object[i].rle_buffer_size = 0; 110cabdff1aSopenharmony_ci ctx->objects.object[i].rle_remaining_len = 0; 111cabdff1aSopenharmony_ci } 112cabdff1aSopenharmony_ci ctx->objects.count = 0; 113cabdff1aSopenharmony_ci ctx->palettes.count = 0; 114cabdff1aSopenharmony_ci} 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_cistatic PGSSubObject * find_object(int id, PGSSubObjects *objects) 117cabdff1aSopenharmony_ci{ 118cabdff1aSopenharmony_ci int i; 119cabdff1aSopenharmony_ci 120cabdff1aSopenharmony_ci for (i = 0; i < objects->count; i++) { 121cabdff1aSopenharmony_ci if (objects->object[i].id == id) 122cabdff1aSopenharmony_ci return &objects->object[i]; 123cabdff1aSopenharmony_ci } 124cabdff1aSopenharmony_ci return NULL; 125cabdff1aSopenharmony_ci} 126cabdff1aSopenharmony_ci 127cabdff1aSopenharmony_cistatic PGSSubPalette * find_palette(int id, PGSSubPalettes *palettes) 128cabdff1aSopenharmony_ci{ 129cabdff1aSopenharmony_ci int i; 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci for (i = 0; i < palettes->count; i++) { 132cabdff1aSopenharmony_ci if (palettes->palette[i].id == id) 133cabdff1aSopenharmony_ci return &palettes->palette[i]; 134cabdff1aSopenharmony_ci } 135cabdff1aSopenharmony_ci return NULL; 136cabdff1aSopenharmony_ci} 137cabdff1aSopenharmony_ci 138cabdff1aSopenharmony_cistatic av_cold int init_decoder(AVCodecContext *avctx) 139cabdff1aSopenharmony_ci{ 140cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_PAL8; 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_ci return 0; 143cabdff1aSopenharmony_ci} 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_cistatic av_cold int close_decoder(AVCodecContext *avctx) 146cabdff1aSopenharmony_ci{ 147cabdff1aSopenharmony_ci flush_cache(avctx); 148cabdff1aSopenharmony_ci 149cabdff1aSopenharmony_ci return 0; 150cabdff1aSopenharmony_ci} 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci/** 153cabdff1aSopenharmony_ci * Decode the RLE data. 154cabdff1aSopenharmony_ci * 155cabdff1aSopenharmony_ci * The subtitle is stored as a Run Length Encoded image. 156cabdff1aSopenharmony_ci * 157cabdff1aSopenharmony_ci * @param avctx contains the current codec context 158cabdff1aSopenharmony_ci * @param sub pointer to the processed subtitle data 159cabdff1aSopenharmony_ci * @param buf pointer to the RLE data to process 160cabdff1aSopenharmony_ci * @param buf_size size of the RLE data to process 161cabdff1aSopenharmony_ci */ 162cabdff1aSopenharmony_cistatic int decode_rle(AVCodecContext *avctx, AVSubtitleRect *rect, 163cabdff1aSopenharmony_ci const uint8_t *buf, unsigned int buf_size) 164cabdff1aSopenharmony_ci{ 165cabdff1aSopenharmony_ci const uint8_t *rle_bitmap_end; 166cabdff1aSopenharmony_ci int pixel_count, line_count; 167cabdff1aSopenharmony_ci 168cabdff1aSopenharmony_ci rle_bitmap_end = buf + buf_size; 169cabdff1aSopenharmony_ci 170cabdff1aSopenharmony_ci rect->data[0] = av_malloc_array(rect->w, rect->h); 171cabdff1aSopenharmony_ci 172cabdff1aSopenharmony_ci if (!rect->data[0]) 173cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 174cabdff1aSopenharmony_ci 175cabdff1aSopenharmony_ci pixel_count = 0; 176cabdff1aSopenharmony_ci line_count = 0; 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ci while (buf < rle_bitmap_end && line_count < rect->h) { 179cabdff1aSopenharmony_ci uint8_t flags, color; 180cabdff1aSopenharmony_ci int run; 181cabdff1aSopenharmony_ci 182cabdff1aSopenharmony_ci color = bytestream_get_byte(&buf); 183cabdff1aSopenharmony_ci run = 1; 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_ci if (color == 0x00) { 186cabdff1aSopenharmony_ci flags = bytestream_get_byte(&buf); 187cabdff1aSopenharmony_ci run = flags & 0x3f; 188cabdff1aSopenharmony_ci if (flags & 0x40) 189cabdff1aSopenharmony_ci run = (run << 8) + bytestream_get_byte(&buf); 190cabdff1aSopenharmony_ci color = flags & 0x80 ? bytestream_get_byte(&buf) : 0; 191cabdff1aSopenharmony_ci } 192cabdff1aSopenharmony_ci 193cabdff1aSopenharmony_ci if (run > 0 && pixel_count + run <= rect->w * rect->h) { 194cabdff1aSopenharmony_ci memset(rect->data[0] + pixel_count, color, run); 195cabdff1aSopenharmony_ci pixel_count += run; 196cabdff1aSopenharmony_ci } else if (!run) { 197cabdff1aSopenharmony_ci /* 198cabdff1aSopenharmony_ci * New Line. Check if correct pixels decoded, if not display warning 199cabdff1aSopenharmony_ci * and adjust bitmap pointer to correct new line position. 200cabdff1aSopenharmony_ci */ 201cabdff1aSopenharmony_ci if (pixel_count % rect->w > 0) { 202cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Decoded %d pixels, when line should be %d pixels\n", 203cabdff1aSopenharmony_ci pixel_count % rect->w, rect->w); 204cabdff1aSopenharmony_ci if (avctx->err_recognition & AV_EF_EXPLODE) { 205cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 206cabdff1aSopenharmony_ci } 207cabdff1aSopenharmony_ci } 208cabdff1aSopenharmony_ci line_count++; 209cabdff1aSopenharmony_ci } 210cabdff1aSopenharmony_ci } 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ci if (pixel_count < rect->w * rect->h) { 213cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Insufficient RLE data for subtitle\n"); 214cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 215cabdff1aSopenharmony_ci } 216cabdff1aSopenharmony_ci 217cabdff1aSopenharmony_ci ff_dlog(avctx, "Pixel Count = %d, Area = %d\n", pixel_count, rect->w * rect->h); 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_ci return 0; 220cabdff1aSopenharmony_ci} 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_ci/** 223cabdff1aSopenharmony_ci * Parse the picture segment packet. 224cabdff1aSopenharmony_ci * 225cabdff1aSopenharmony_ci * The picture segment contains details on the sequence id, 226cabdff1aSopenharmony_ci * width, height and Run Length Encoded (RLE) bitmap data. 227cabdff1aSopenharmony_ci * 228cabdff1aSopenharmony_ci * @param avctx contains the current codec context 229cabdff1aSopenharmony_ci * @param buf pointer to the packet to process 230cabdff1aSopenharmony_ci * @param buf_size size of packet to process 231cabdff1aSopenharmony_ci */ 232cabdff1aSopenharmony_cistatic int parse_object_segment(AVCodecContext *avctx, 233cabdff1aSopenharmony_ci const uint8_t *buf, int buf_size) 234cabdff1aSopenharmony_ci{ 235cabdff1aSopenharmony_ci PGSSubContext *ctx = avctx->priv_data; 236cabdff1aSopenharmony_ci PGSSubObject *object; 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_ci uint8_t sequence_desc; 239cabdff1aSopenharmony_ci unsigned int rle_bitmap_len, width, height; 240cabdff1aSopenharmony_ci int id; 241cabdff1aSopenharmony_ci 242cabdff1aSopenharmony_ci if (buf_size <= 4) 243cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 244cabdff1aSopenharmony_ci buf_size -= 4; 245cabdff1aSopenharmony_ci 246cabdff1aSopenharmony_ci id = bytestream_get_be16(&buf); 247cabdff1aSopenharmony_ci object = find_object(id, &ctx->objects); 248cabdff1aSopenharmony_ci if (!object) { 249cabdff1aSopenharmony_ci if (ctx->objects.count >= MAX_EPOCH_OBJECTS) { 250cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Too many objects in epoch\n"); 251cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 252cabdff1aSopenharmony_ci } 253cabdff1aSopenharmony_ci object = &ctx->objects.object[ctx->objects.count++]; 254cabdff1aSopenharmony_ci object->id = id; 255cabdff1aSopenharmony_ci } 256cabdff1aSopenharmony_ci 257cabdff1aSopenharmony_ci /* skip object version number */ 258cabdff1aSopenharmony_ci buf += 1; 259cabdff1aSopenharmony_ci 260cabdff1aSopenharmony_ci /* Read the Sequence Description to determine if start of RLE data or appended to previous RLE */ 261cabdff1aSopenharmony_ci sequence_desc = bytestream_get_byte(&buf); 262cabdff1aSopenharmony_ci 263cabdff1aSopenharmony_ci if (!(sequence_desc & 0x80)) { 264cabdff1aSopenharmony_ci /* Additional RLE data */ 265cabdff1aSopenharmony_ci if (buf_size > object->rle_remaining_len) 266cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 267cabdff1aSopenharmony_ci 268cabdff1aSopenharmony_ci memcpy(object->rle + object->rle_data_len, buf, buf_size); 269cabdff1aSopenharmony_ci object->rle_data_len += buf_size; 270cabdff1aSopenharmony_ci object->rle_remaining_len -= buf_size; 271cabdff1aSopenharmony_ci 272cabdff1aSopenharmony_ci return 0; 273cabdff1aSopenharmony_ci } 274cabdff1aSopenharmony_ci 275cabdff1aSopenharmony_ci if (buf_size <= 7) 276cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 277cabdff1aSopenharmony_ci buf_size -= 7; 278cabdff1aSopenharmony_ci 279cabdff1aSopenharmony_ci /* Decode rle bitmap length, stored size includes width/height data */ 280cabdff1aSopenharmony_ci rle_bitmap_len = bytestream_get_be24(&buf) - 2*2; 281cabdff1aSopenharmony_ci 282cabdff1aSopenharmony_ci if (buf_size > rle_bitmap_len) { 283cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 284cabdff1aSopenharmony_ci "Buffer dimension %d larger than the expected RLE data %d\n", 285cabdff1aSopenharmony_ci buf_size, rle_bitmap_len); 286cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 287cabdff1aSopenharmony_ci } 288cabdff1aSopenharmony_ci 289cabdff1aSopenharmony_ci /* Get bitmap dimensions from data */ 290cabdff1aSopenharmony_ci width = bytestream_get_be16(&buf); 291cabdff1aSopenharmony_ci height = bytestream_get_be16(&buf); 292cabdff1aSopenharmony_ci 293cabdff1aSopenharmony_ci /* Make sure the bitmap is not too large */ 294cabdff1aSopenharmony_ci if (avctx->width < width || avctx->height < height || !width || !height) { 295cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Bitmap dimensions (%dx%d) invalid.\n", width, height); 296cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 297cabdff1aSopenharmony_ci } 298cabdff1aSopenharmony_ci 299cabdff1aSopenharmony_ci object->w = width; 300cabdff1aSopenharmony_ci object->h = height; 301cabdff1aSopenharmony_ci 302cabdff1aSopenharmony_ci av_fast_padded_malloc(&object->rle, &object->rle_buffer_size, rle_bitmap_len); 303cabdff1aSopenharmony_ci 304cabdff1aSopenharmony_ci if (!object->rle) { 305cabdff1aSopenharmony_ci object->rle_data_len = 0; 306cabdff1aSopenharmony_ci object->rle_remaining_len = 0; 307cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 308cabdff1aSopenharmony_ci } 309cabdff1aSopenharmony_ci 310cabdff1aSopenharmony_ci memcpy(object->rle, buf, buf_size); 311cabdff1aSopenharmony_ci object->rle_data_len = buf_size; 312cabdff1aSopenharmony_ci object->rle_remaining_len = rle_bitmap_len - buf_size; 313cabdff1aSopenharmony_ci 314cabdff1aSopenharmony_ci return 0; 315cabdff1aSopenharmony_ci} 316cabdff1aSopenharmony_ci 317cabdff1aSopenharmony_ci/** 318cabdff1aSopenharmony_ci * Parse the palette segment packet. 319cabdff1aSopenharmony_ci * 320cabdff1aSopenharmony_ci * The palette segment contains details of the palette, 321cabdff1aSopenharmony_ci * a maximum of 256 colors can be defined. 322cabdff1aSopenharmony_ci * 323cabdff1aSopenharmony_ci * @param avctx contains the current codec context 324cabdff1aSopenharmony_ci * @param buf pointer to the packet to process 325cabdff1aSopenharmony_ci * @param buf_size size of packet to process 326cabdff1aSopenharmony_ci */ 327cabdff1aSopenharmony_cistatic int parse_palette_segment(AVCodecContext *avctx, 328cabdff1aSopenharmony_ci const uint8_t *buf, int buf_size) 329cabdff1aSopenharmony_ci{ 330cabdff1aSopenharmony_ci PGSSubContext *ctx = avctx->priv_data; 331cabdff1aSopenharmony_ci PGSSubPalette *palette; 332cabdff1aSopenharmony_ci 333cabdff1aSopenharmony_ci const uint8_t *buf_end = buf + buf_size; 334cabdff1aSopenharmony_ci const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; 335cabdff1aSopenharmony_ci int color_id; 336cabdff1aSopenharmony_ci int y, cb, cr, alpha; 337cabdff1aSopenharmony_ci int r, g, b, r_add, g_add, b_add; 338cabdff1aSopenharmony_ci int id; 339cabdff1aSopenharmony_ci 340cabdff1aSopenharmony_ci id = bytestream_get_byte(&buf); 341cabdff1aSopenharmony_ci palette = find_palette(id, &ctx->palettes); 342cabdff1aSopenharmony_ci if (!palette) { 343cabdff1aSopenharmony_ci if (ctx->palettes.count >= MAX_EPOCH_PALETTES) { 344cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Too many palettes in epoch\n"); 345cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 346cabdff1aSopenharmony_ci } 347cabdff1aSopenharmony_ci palette = &ctx->palettes.palette[ctx->palettes.count++]; 348cabdff1aSopenharmony_ci palette->id = id; 349cabdff1aSopenharmony_ci } 350cabdff1aSopenharmony_ci 351cabdff1aSopenharmony_ci /* Skip palette version */ 352cabdff1aSopenharmony_ci buf += 1; 353cabdff1aSopenharmony_ci 354cabdff1aSopenharmony_ci while (buf < buf_end) { 355cabdff1aSopenharmony_ci color_id = bytestream_get_byte(&buf); 356cabdff1aSopenharmony_ci y = bytestream_get_byte(&buf); 357cabdff1aSopenharmony_ci cr = bytestream_get_byte(&buf); 358cabdff1aSopenharmony_ci cb = bytestream_get_byte(&buf); 359cabdff1aSopenharmony_ci alpha = bytestream_get_byte(&buf); 360cabdff1aSopenharmony_ci 361cabdff1aSopenharmony_ci /* Default to BT.709 colorspace. In case of <= 576 height use BT.601 */ 362cabdff1aSopenharmony_ci if (avctx->height <= 0 || avctx->height > 576) { 363cabdff1aSopenharmony_ci YUV_TO_RGB1_CCIR_BT709(cb, cr); 364cabdff1aSopenharmony_ci } else { 365cabdff1aSopenharmony_ci YUV_TO_RGB1_CCIR(cb, cr); 366cabdff1aSopenharmony_ci } 367cabdff1aSopenharmony_ci 368cabdff1aSopenharmony_ci YUV_TO_RGB2_CCIR(r, g, b, y); 369cabdff1aSopenharmony_ci 370cabdff1aSopenharmony_ci ff_dlog(avctx, "Color %d := (%d,%d,%d,%d)\n", color_id, r, g, b, alpha); 371cabdff1aSopenharmony_ci 372cabdff1aSopenharmony_ci /* Store color in palette */ 373cabdff1aSopenharmony_ci palette->clut[color_id] = RGBA(r,g,b,alpha); 374cabdff1aSopenharmony_ci } 375cabdff1aSopenharmony_ci return 0; 376cabdff1aSopenharmony_ci} 377cabdff1aSopenharmony_ci 378cabdff1aSopenharmony_ci/** 379cabdff1aSopenharmony_ci * Parse the presentation segment packet. 380cabdff1aSopenharmony_ci * 381cabdff1aSopenharmony_ci * The presentation segment contains details on the video 382cabdff1aSopenharmony_ci * width, video height, x & y subtitle position. 383cabdff1aSopenharmony_ci * 384cabdff1aSopenharmony_ci * @param avctx contains the current codec context 385cabdff1aSopenharmony_ci * @param buf pointer to the packet to process 386cabdff1aSopenharmony_ci * @param buf_size size of packet to process 387cabdff1aSopenharmony_ci * @todo TODO: Implement cropping 388cabdff1aSopenharmony_ci */ 389cabdff1aSopenharmony_cistatic int parse_presentation_segment(AVCodecContext *avctx, 390cabdff1aSopenharmony_ci const uint8_t *buf, int buf_size, 391cabdff1aSopenharmony_ci int64_t pts) 392cabdff1aSopenharmony_ci{ 393cabdff1aSopenharmony_ci PGSSubContext *ctx = avctx->priv_data; 394cabdff1aSopenharmony_ci int i, state, ret; 395cabdff1aSopenharmony_ci const uint8_t *buf_end = buf + buf_size; 396cabdff1aSopenharmony_ci 397cabdff1aSopenharmony_ci // Video descriptor 398cabdff1aSopenharmony_ci int w = bytestream_get_be16(&buf); 399cabdff1aSopenharmony_ci int h = bytestream_get_be16(&buf); 400cabdff1aSopenharmony_ci 401cabdff1aSopenharmony_ci ctx->presentation.pts = pts; 402cabdff1aSopenharmony_ci 403cabdff1aSopenharmony_ci ff_dlog(avctx, "Video Dimensions %dx%d\n", 404cabdff1aSopenharmony_ci w, h); 405cabdff1aSopenharmony_ci ret = ff_set_dimensions(avctx, w, h); 406cabdff1aSopenharmony_ci if (ret < 0) 407cabdff1aSopenharmony_ci return ret; 408cabdff1aSopenharmony_ci 409cabdff1aSopenharmony_ci /* Skip 1 bytes of unknown, frame rate */ 410cabdff1aSopenharmony_ci buf++; 411cabdff1aSopenharmony_ci 412cabdff1aSopenharmony_ci // Composition descriptor 413cabdff1aSopenharmony_ci ctx->presentation.id_number = bytestream_get_be16(&buf); 414cabdff1aSopenharmony_ci /* 415cabdff1aSopenharmony_ci * state is a 2 bit field that defines pgs epoch boundaries 416cabdff1aSopenharmony_ci * 00 - Normal, previously defined objects and palettes are still valid 417cabdff1aSopenharmony_ci * 01 - Acquisition point, previous objects and palettes can be released 418cabdff1aSopenharmony_ci * 10 - Epoch start, previous objects and palettes can be released 419cabdff1aSopenharmony_ci * 11 - Epoch continue, previous objects and palettes can be released 420cabdff1aSopenharmony_ci * 421cabdff1aSopenharmony_ci * reserved 6 bits discarded 422cabdff1aSopenharmony_ci */ 423cabdff1aSopenharmony_ci state = bytestream_get_byte(&buf) >> 6; 424cabdff1aSopenharmony_ci if (state != 0) { 425cabdff1aSopenharmony_ci flush_cache(avctx); 426cabdff1aSopenharmony_ci } 427cabdff1aSopenharmony_ci 428cabdff1aSopenharmony_ci /* 429cabdff1aSopenharmony_ci * skip palette_update_flag (0x80), 430cabdff1aSopenharmony_ci */ 431cabdff1aSopenharmony_ci buf += 1; 432cabdff1aSopenharmony_ci ctx->presentation.palette_id = bytestream_get_byte(&buf); 433cabdff1aSopenharmony_ci ctx->presentation.object_count = bytestream_get_byte(&buf); 434cabdff1aSopenharmony_ci if (ctx->presentation.object_count > MAX_OBJECT_REFS) { 435cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 436cabdff1aSopenharmony_ci "Invalid number of presentation objects %d\n", 437cabdff1aSopenharmony_ci ctx->presentation.object_count); 438cabdff1aSopenharmony_ci ctx->presentation.object_count = 2; 439cabdff1aSopenharmony_ci if (avctx->err_recognition & AV_EF_EXPLODE) { 440cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 441cabdff1aSopenharmony_ci } 442cabdff1aSopenharmony_ci } 443cabdff1aSopenharmony_ci 444cabdff1aSopenharmony_ci 445cabdff1aSopenharmony_ci for (i = 0; i < ctx->presentation.object_count; i++) 446cabdff1aSopenharmony_ci { 447cabdff1aSopenharmony_ci PGSSubObjectRef *const object = &ctx->presentation.objects[i]; 448cabdff1aSopenharmony_ci 449cabdff1aSopenharmony_ci if (buf_end - buf < 8) { 450cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Insufficent space for object\n"); 451cabdff1aSopenharmony_ci ctx->presentation.object_count = i; 452cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 453cabdff1aSopenharmony_ci } 454cabdff1aSopenharmony_ci 455cabdff1aSopenharmony_ci object->id = bytestream_get_be16(&buf); 456cabdff1aSopenharmony_ci object->window_id = bytestream_get_byte(&buf); 457cabdff1aSopenharmony_ci object->composition_flag = bytestream_get_byte(&buf); 458cabdff1aSopenharmony_ci 459cabdff1aSopenharmony_ci object->x = bytestream_get_be16(&buf); 460cabdff1aSopenharmony_ci object->y = bytestream_get_be16(&buf); 461cabdff1aSopenharmony_ci 462cabdff1aSopenharmony_ci // If cropping 463cabdff1aSopenharmony_ci if (object->composition_flag & 0x80) { 464cabdff1aSopenharmony_ci object->crop_x = bytestream_get_be16(&buf); 465cabdff1aSopenharmony_ci object->crop_y = bytestream_get_be16(&buf); 466cabdff1aSopenharmony_ci object->crop_w = bytestream_get_be16(&buf); 467cabdff1aSopenharmony_ci object->crop_h = bytestream_get_be16(&buf); 468cabdff1aSopenharmony_ci } 469cabdff1aSopenharmony_ci 470cabdff1aSopenharmony_ci ff_dlog(avctx, "Subtitle Placement x=%d, y=%d\n", 471cabdff1aSopenharmony_ci object->x, object->y); 472cabdff1aSopenharmony_ci 473cabdff1aSopenharmony_ci if (object->x > avctx->width || object->y > avctx->height) { 474cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Subtitle out of video bounds. x = %d, y = %d, video width = %d, video height = %d.\n", 475cabdff1aSopenharmony_ci object->x, object->y, 476cabdff1aSopenharmony_ci avctx->width, avctx->height); 477cabdff1aSopenharmony_ci object->y = object->x = 0; 478cabdff1aSopenharmony_ci if (avctx->err_recognition & AV_EF_EXPLODE) { 479cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 480cabdff1aSopenharmony_ci } 481cabdff1aSopenharmony_ci } 482cabdff1aSopenharmony_ci } 483cabdff1aSopenharmony_ci 484cabdff1aSopenharmony_ci return 0; 485cabdff1aSopenharmony_ci} 486cabdff1aSopenharmony_ci 487cabdff1aSopenharmony_ci/** 488cabdff1aSopenharmony_ci * Parse the display segment packet. 489cabdff1aSopenharmony_ci * 490cabdff1aSopenharmony_ci * The display segment controls the updating of the display. 491cabdff1aSopenharmony_ci * 492cabdff1aSopenharmony_ci * @param avctx contains the current codec context 493cabdff1aSopenharmony_ci * @param data pointer to the data pertaining the subtitle to display 494cabdff1aSopenharmony_ci * @param buf pointer to the packet to process 495cabdff1aSopenharmony_ci * @param buf_size size of packet to process 496cabdff1aSopenharmony_ci */ 497cabdff1aSopenharmony_cistatic int display_end_segment(AVCodecContext *avctx, AVSubtitle *sub, 498cabdff1aSopenharmony_ci const uint8_t *buf, int buf_size) 499cabdff1aSopenharmony_ci{ 500cabdff1aSopenharmony_ci PGSSubContext *ctx = avctx->priv_data; 501cabdff1aSopenharmony_ci int64_t pts; 502cabdff1aSopenharmony_ci PGSSubPalette *palette; 503cabdff1aSopenharmony_ci int i, ret; 504cabdff1aSopenharmony_ci 505cabdff1aSopenharmony_ci pts = ctx->presentation.pts != AV_NOPTS_VALUE ? ctx->presentation.pts : sub->pts; 506cabdff1aSopenharmony_ci memset(sub, 0, sizeof(*sub)); 507cabdff1aSopenharmony_ci sub->pts = pts; 508cabdff1aSopenharmony_ci ctx->presentation.pts = AV_NOPTS_VALUE; 509cabdff1aSopenharmony_ci sub->start_display_time = 0; 510cabdff1aSopenharmony_ci // There is no explicit end time for PGS subtitles. The end time 511cabdff1aSopenharmony_ci // is defined by the start of the next sub which may contain no 512cabdff1aSopenharmony_ci // objects (i.e. clears the previous sub) 513cabdff1aSopenharmony_ci sub->end_display_time = UINT32_MAX; 514cabdff1aSopenharmony_ci sub->format = 0; 515cabdff1aSopenharmony_ci 516cabdff1aSopenharmony_ci // Blank if last object_count was 0. 517cabdff1aSopenharmony_ci if (!ctx->presentation.object_count) 518cabdff1aSopenharmony_ci return 1; 519cabdff1aSopenharmony_ci sub->rects = av_calloc(ctx->presentation.object_count, sizeof(*sub->rects)); 520cabdff1aSopenharmony_ci if (!sub->rects) { 521cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 522cabdff1aSopenharmony_ci } 523cabdff1aSopenharmony_ci palette = find_palette(ctx->presentation.palette_id, &ctx->palettes); 524cabdff1aSopenharmony_ci if (!palette) { 525cabdff1aSopenharmony_ci // Missing palette. Should only happen with damaged streams. 526cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid palette id %d\n", 527cabdff1aSopenharmony_ci ctx->presentation.palette_id); 528cabdff1aSopenharmony_ci avsubtitle_free(sub); 529cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 530cabdff1aSopenharmony_ci } 531cabdff1aSopenharmony_ci for (i = 0; i < ctx->presentation.object_count; i++) { 532cabdff1aSopenharmony_ci AVSubtitleRect *const rect = av_mallocz(sizeof(*rect)); 533cabdff1aSopenharmony_ci PGSSubObject *object; 534cabdff1aSopenharmony_ci 535cabdff1aSopenharmony_ci if (!rect) 536cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 537cabdff1aSopenharmony_ci sub->rects[sub->num_rects++] = rect; 538cabdff1aSopenharmony_ci rect->type = SUBTITLE_BITMAP; 539cabdff1aSopenharmony_ci 540cabdff1aSopenharmony_ci /* Process bitmap */ 541cabdff1aSopenharmony_ci object = find_object(ctx->presentation.objects[i].id, &ctx->objects); 542cabdff1aSopenharmony_ci if (!object) { 543cabdff1aSopenharmony_ci // Missing object. Should only happen with damaged streams. 544cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid object id %d\n", 545cabdff1aSopenharmony_ci ctx->presentation.objects[i].id); 546cabdff1aSopenharmony_ci if (avctx->err_recognition & AV_EF_EXPLODE) 547cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 548cabdff1aSopenharmony_ci // Leaves rect empty with 0 width and height. 549cabdff1aSopenharmony_ci continue; 550cabdff1aSopenharmony_ci } 551cabdff1aSopenharmony_ci if (ctx->presentation.objects[i].composition_flag & 0x40) 552cabdff1aSopenharmony_ci rect->flags |= AV_SUBTITLE_FLAG_FORCED; 553cabdff1aSopenharmony_ci 554cabdff1aSopenharmony_ci rect->x = ctx->presentation.objects[i].x; 555cabdff1aSopenharmony_ci rect->y = ctx->presentation.objects[i].y; 556cabdff1aSopenharmony_ci 557cabdff1aSopenharmony_ci if (object->rle) { 558cabdff1aSopenharmony_ci rect->w = object->w; 559cabdff1aSopenharmony_ci rect->h = object->h; 560cabdff1aSopenharmony_ci 561cabdff1aSopenharmony_ci rect->linesize[0] = object->w; 562cabdff1aSopenharmony_ci 563cabdff1aSopenharmony_ci if (object->rle_remaining_len) { 564cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "RLE data length %u is %u bytes shorter than expected\n", 565cabdff1aSopenharmony_ci object->rle_data_len, object->rle_remaining_len); 566cabdff1aSopenharmony_ci if (avctx->err_recognition & AV_EF_EXPLODE) 567cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 568cabdff1aSopenharmony_ci } 569cabdff1aSopenharmony_ci ret = decode_rle(avctx, rect, object->rle, object->rle_data_len); 570cabdff1aSopenharmony_ci if (ret < 0) { 571cabdff1aSopenharmony_ci if ((avctx->err_recognition & AV_EF_EXPLODE) || 572cabdff1aSopenharmony_ci ret == AVERROR(ENOMEM)) { 573cabdff1aSopenharmony_ci return ret; 574cabdff1aSopenharmony_ci } 575cabdff1aSopenharmony_ci rect->w = 0; 576cabdff1aSopenharmony_ci rect->h = 0; 577cabdff1aSopenharmony_ci continue; 578cabdff1aSopenharmony_ci } 579cabdff1aSopenharmony_ci } 580cabdff1aSopenharmony_ci /* Allocate memory for colors */ 581cabdff1aSopenharmony_ci rect->nb_colors = 256; 582cabdff1aSopenharmony_ci rect->data[1] = av_mallocz(AVPALETTE_SIZE); 583cabdff1aSopenharmony_ci if (!rect->data[1]) 584cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 585cabdff1aSopenharmony_ci 586cabdff1aSopenharmony_ci if (!ctx->forced_subs_only || ctx->presentation.objects[i].composition_flag & 0x40) 587cabdff1aSopenharmony_ci memcpy(rect->data[1], palette->clut, rect->nb_colors * sizeof(uint32_t)); 588cabdff1aSopenharmony_ci } 589cabdff1aSopenharmony_ci return 1; 590cabdff1aSopenharmony_ci} 591cabdff1aSopenharmony_ci 592cabdff1aSopenharmony_cistatic int decode(AVCodecContext *avctx, AVSubtitle *sub, 593cabdff1aSopenharmony_ci int *got_sub_ptr, const AVPacket *avpkt) 594cabdff1aSopenharmony_ci{ 595cabdff1aSopenharmony_ci const uint8_t *buf = avpkt->data; 596cabdff1aSopenharmony_ci int buf_size = avpkt->size; 597cabdff1aSopenharmony_ci 598cabdff1aSopenharmony_ci const uint8_t *buf_end; 599cabdff1aSopenharmony_ci uint8_t segment_type; 600cabdff1aSopenharmony_ci int segment_length; 601cabdff1aSopenharmony_ci int i, ret; 602cabdff1aSopenharmony_ci 603cabdff1aSopenharmony_ci ff_dlog(avctx, "PGS sub packet:\n"); 604cabdff1aSopenharmony_ci 605cabdff1aSopenharmony_ci for (i = 0; i < buf_size; i++) { 606cabdff1aSopenharmony_ci ff_dlog(avctx, "%02x ", buf[i]); 607cabdff1aSopenharmony_ci if (i % 16 == 15) 608cabdff1aSopenharmony_ci ff_dlog(avctx, "\n"); 609cabdff1aSopenharmony_ci } 610cabdff1aSopenharmony_ci 611cabdff1aSopenharmony_ci if (i & 15) 612cabdff1aSopenharmony_ci ff_dlog(avctx, "\n"); 613cabdff1aSopenharmony_ci 614cabdff1aSopenharmony_ci *got_sub_ptr = 0; 615cabdff1aSopenharmony_ci 616cabdff1aSopenharmony_ci /* Ensure that we have received at a least a segment code and segment length */ 617cabdff1aSopenharmony_ci if (buf_size < 3) 618cabdff1aSopenharmony_ci return -1; 619cabdff1aSopenharmony_ci 620cabdff1aSopenharmony_ci buf_end = buf + buf_size; 621cabdff1aSopenharmony_ci 622cabdff1aSopenharmony_ci /* Step through buffer to identify segments */ 623cabdff1aSopenharmony_ci while (buf < buf_end) { 624cabdff1aSopenharmony_ci segment_type = bytestream_get_byte(&buf); 625cabdff1aSopenharmony_ci segment_length = bytestream_get_be16(&buf); 626cabdff1aSopenharmony_ci 627cabdff1aSopenharmony_ci ff_dlog(avctx, "Segment Length %d, Segment Type %x\n", segment_length, segment_type); 628cabdff1aSopenharmony_ci 629cabdff1aSopenharmony_ci if (segment_type != DISPLAY_SEGMENT && segment_length > buf_end - buf) 630cabdff1aSopenharmony_ci break; 631cabdff1aSopenharmony_ci 632cabdff1aSopenharmony_ci ret = 0; 633cabdff1aSopenharmony_ci switch (segment_type) { 634cabdff1aSopenharmony_ci case PALETTE_SEGMENT: 635cabdff1aSopenharmony_ci ret = parse_palette_segment(avctx, buf, segment_length); 636cabdff1aSopenharmony_ci break; 637cabdff1aSopenharmony_ci case OBJECT_SEGMENT: 638cabdff1aSopenharmony_ci ret = parse_object_segment(avctx, buf, segment_length); 639cabdff1aSopenharmony_ci break; 640cabdff1aSopenharmony_ci case PRESENTATION_SEGMENT: 641cabdff1aSopenharmony_ci ret = parse_presentation_segment(avctx, buf, segment_length, sub->pts); 642cabdff1aSopenharmony_ci break; 643cabdff1aSopenharmony_ci case WINDOW_SEGMENT: 644cabdff1aSopenharmony_ci /* 645cabdff1aSopenharmony_ci * Window Segment Structure (No new information provided): 646cabdff1aSopenharmony_ci * 2 bytes: Unknown, 647cabdff1aSopenharmony_ci * 2 bytes: X position of subtitle, 648cabdff1aSopenharmony_ci * 2 bytes: Y position of subtitle, 649cabdff1aSopenharmony_ci * 2 bytes: Width of subtitle, 650cabdff1aSopenharmony_ci * 2 bytes: Height of subtitle. 651cabdff1aSopenharmony_ci */ 652cabdff1aSopenharmony_ci break; 653cabdff1aSopenharmony_ci case DISPLAY_SEGMENT: 654cabdff1aSopenharmony_ci if (*got_sub_ptr) { 655cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Duplicate display segment\n"); 656cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 657cabdff1aSopenharmony_ci break; 658cabdff1aSopenharmony_ci } 659cabdff1aSopenharmony_ci ret = display_end_segment(avctx, sub, buf, segment_length); 660cabdff1aSopenharmony_ci if (ret >= 0) 661cabdff1aSopenharmony_ci *got_sub_ptr = ret; 662cabdff1aSopenharmony_ci break; 663cabdff1aSopenharmony_ci default: 664cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Unknown subtitle segment type 0x%x, length %d\n", 665cabdff1aSopenharmony_ci segment_type, segment_length); 666cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 667cabdff1aSopenharmony_ci break; 668cabdff1aSopenharmony_ci } 669cabdff1aSopenharmony_ci if (ret < 0 && (ret == AVERROR(ENOMEM) || 670cabdff1aSopenharmony_ci avctx->err_recognition & AV_EF_EXPLODE)) 671cabdff1aSopenharmony_ci return ret; 672cabdff1aSopenharmony_ci 673cabdff1aSopenharmony_ci buf += segment_length; 674cabdff1aSopenharmony_ci } 675cabdff1aSopenharmony_ci 676cabdff1aSopenharmony_ci return buf_size; 677cabdff1aSopenharmony_ci} 678cabdff1aSopenharmony_ci 679cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(PGSSubContext, x) 680cabdff1aSopenharmony_ci#define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM 681cabdff1aSopenharmony_cistatic const AVOption options[] = { 682cabdff1aSopenharmony_ci {"forced_subs_only", "Only show forced subtitles", OFFSET(forced_subs_only), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, SD}, 683cabdff1aSopenharmony_ci { NULL }, 684cabdff1aSopenharmony_ci}; 685cabdff1aSopenharmony_ci 686cabdff1aSopenharmony_cistatic const AVClass pgsdec_class = { 687cabdff1aSopenharmony_ci .class_name = "PGS subtitle decoder", 688cabdff1aSopenharmony_ci .item_name = av_default_item_name, 689cabdff1aSopenharmony_ci .option = options, 690cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 691cabdff1aSopenharmony_ci}; 692cabdff1aSopenharmony_ci 693cabdff1aSopenharmony_ciconst FFCodec ff_pgssub_decoder = { 694cabdff1aSopenharmony_ci .p.name = "pgssub", 695cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("HDMV Presentation Graphic Stream subtitles"), 696cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_SUBTITLE, 697cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_HDMV_PGS_SUBTITLE, 698cabdff1aSopenharmony_ci .priv_data_size = sizeof(PGSSubContext), 699cabdff1aSopenharmony_ci .init = init_decoder, 700cabdff1aSopenharmony_ci .close = close_decoder, 701cabdff1aSopenharmony_ci FF_CODEC_DECODE_SUB_CB(decode), 702cabdff1aSopenharmony_ci .p.priv_class = &pgsdec_class, 703cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 704cabdff1aSopenharmony_ci}; 705