annotate ffmpeg/libavcodec/pgssubdec.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * PGS subtitle decoder
yading@10 3 * Copyright (c) 2009 Stephen Backway
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 /**
yading@10 23 * @file
yading@10 24 * PGS subtitle decoder
yading@10 25 */
yading@10 26
yading@10 27 #include "avcodec.h"
yading@10 28 #include "dsputil.h"
yading@10 29 #include "bytestream.h"
yading@10 30 #include "libavutil/colorspace.h"
yading@10 31 #include "libavutil/imgutils.h"
yading@10 32 #include "libavutil/opt.h"
yading@10 33
yading@10 34 #define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
yading@10 35
yading@10 36 enum SegmentType {
yading@10 37 PALETTE_SEGMENT = 0x14,
yading@10 38 PICTURE_SEGMENT = 0x15,
yading@10 39 PRESENTATION_SEGMENT = 0x16,
yading@10 40 WINDOW_SEGMENT = 0x17,
yading@10 41 DISPLAY_SEGMENT = 0x80,
yading@10 42 };
yading@10 43
yading@10 44 typedef struct PGSSubPictureReference {
yading@10 45 int x;
yading@10 46 int y;
yading@10 47 int picture_id;
yading@10 48 int composition;
yading@10 49 } PGSSubPictureReference;
yading@10 50
yading@10 51 typedef struct PGSSubPresentation {
yading@10 52 int id_number;
yading@10 53 int object_count;
yading@10 54 PGSSubPictureReference *objects;
yading@10 55 int64_t pts;
yading@10 56 } PGSSubPresentation;
yading@10 57
yading@10 58 typedef struct PGSSubPicture {
yading@10 59 int w;
yading@10 60 int h;
yading@10 61 uint8_t *rle;
yading@10 62 unsigned int rle_buffer_size, rle_data_len;
yading@10 63 unsigned int rle_remaining_len;
yading@10 64 } PGSSubPicture;
yading@10 65
yading@10 66 typedef struct PGSSubContext {
yading@10 67 AVClass *class;
yading@10 68 PGSSubPresentation presentation;
yading@10 69 uint32_t clut[256];
yading@10 70 PGSSubPicture pictures[UINT16_MAX];
yading@10 71 int forced_subs_only;
yading@10 72 } PGSSubContext;
yading@10 73
yading@10 74 static av_cold int init_decoder(AVCodecContext *avctx)
yading@10 75 {
yading@10 76 avctx->pix_fmt = AV_PIX_FMT_PAL8;
yading@10 77
yading@10 78 return 0;
yading@10 79 }
yading@10 80
yading@10 81 static av_cold int close_decoder(AVCodecContext *avctx)
yading@10 82 {
yading@10 83 uint16_t picture;
yading@10 84
yading@10 85 PGSSubContext *ctx = avctx->priv_data;
yading@10 86
yading@10 87 av_freep(&ctx->presentation.objects);
yading@10 88 ctx->presentation.object_count = 0;
yading@10 89
yading@10 90 for (picture = 0; picture < UINT16_MAX; ++picture) {
yading@10 91 av_freep(&ctx->pictures[picture].rle);
yading@10 92 ctx->pictures[picture].rle_buffer_size = 0;
yading@10 93 }
yading@10 94
yading@10 95 return 0;
yading@10 96 }
yading@10 97
yading@10 98 /**
yading@10 99 * Decode the RLE data.
yading@10 100 *
yading@10 101 * The subtitle is stored as an Run Length Encoded image.
yading@10 102 *
yading@10 103 * @param avctx contains the current codec context
yading@10 104 * @param sub pointer to the processed subtitle data
yading@10 105 * @param buf pointer to the RLE data to process
yading@10 106 * @param buf_size size of the RLE data to process
yading@10 107 */
yading@10 108 static int decode_rle(AVCodecContext *avctx, AVSubtitle *sub, int rect,
yading@10 109 const uint8_t *buf, unsigned int buf_size)
yading@10 110 {
yading@10 111 const uint8_t *rle_bitmap_end;
yading@10 112 int pixel_count, line_count;
yading@10 113
yading@10 114 rle_bitmap_end = buf + buf_size;
yading@10 115
yading@10 116 sub->rects[rect]->pict.data[0] = av_malloc(sub->rects[rect]->w * sub->rects[rect]->h);
yading@10 117
yading@10 118 if (!sub->rects[rect]->pict.data[0])
yading@10 119 return -1;
yading@10 120
yading@10 121 pixel_count = 0;
yading@10 122 line_count = 0;
yading@10 123
yading@10 124 while (buf < rle_bitmap_end && line_count < sub->rects[rect]->h) {
yading@10 125 uint8_t flags, color;
yading@10 126 int run;
yading@10 127
yading@10 128 color = bytestream_get_byte(&buf);
yading@10 129 run = 1;
yading@10 130
yading@10 131 if (color == 0x00) {
yading@10 132 flags = bytestream_get_byte(&buf);
yading@10 133 run = flags & 0x3f;
yading@10 134 if (flags & 0x40)
yading@10 135 run = (run << 8) + bytestream_get_byte(&buf);
yading@10 136 color = flags & 0x80 ? bytestream_get_byte(&buf) : 0;
yading@10 137 }
yading@10 138
yading@10 139 if (run > 0 && pixel_count + run <= sub->rects[rect]->w * sub->rects[rect]->h) {
yading@10 140 memset(sub->rects[rect]->pict.data[0] + pixel_count, color, run);
yading@10 141 pixel_count += run;
yading@10 142 } else if (!run) {
yading@10 143 /*
yading@10 144 * New Line. Check if correct pixels decoded, if not display warning
yading@10 145 * and adjust bitmap pointer to correct new line position.
yading@10 146 */
yading@10 147 if (pixel_count % sub->rects[rect]->w > 0)
yading@10 148 av_log(avctx, AV_LOG_ERROR, "Decoded %d pixels, when line should be %d pixels\n",
yading@10 149 pixel_count % sub->rects[rect]->w, sub->rects[rect]->w);
yading@10 150 line_count++;
yading@10 151 }
yading@10 152 }
yading@10 153
yading@10 154 if (pixel_count < sub->rects[rect]->w * sub->rects[rect]->h) {
yading@10 155 av_log(avctx, AV_LOG_ERROR, "Insufficient RLE data for subtitle\n");
yading@10 156 return -1;
yading@10 157 }
yading@10 158
yading@10 159 av_dlog(avctx, "Pixel Count = %d, Area = %d\n", pixel_count, sub->rects[rect]->w * sub->rects[rect]->h);
yading@10 160
yading@10 161 return 0;
yading@10 162 }
yading@10 163
yading@10 164 /**
yading@10 165 * Parse the picture segment packet.
yading@10 166 *
yading@10 167 * The picture segment contains details on the sequence id,
yading@10 168 * width, height and Run Length Encoded (RLE) bitmap data.
yading@10 169 *
yading@10 170 * @param avctx contains the current codec context
yading@10 171 * @param buf pointer to the packet to process
yading@10 172 * @param buf_size size of packet to process
yading@10 173 * @todo TODO: Enable support for RLE data over multiple packets
yading@10 174 */
yading@10 175 static int parse_picture_segment(AVCodecContext *avctx,
yading@10 176 const uint8_t *buf, int buf_size)
yading@10 177 {
yading@10 178 PGSSubContext *ctx = avctx->priv_data;
yading@10 179
yading@10 180 uint8_t sequence_desc;
yading@10 181 unsigned int rle_bitmap_len, width, height;
yading@10 182 uint16_t picture_id;
yading@10 183
yading@10 184 if (buf_size <= 4)
yading@10 185 return -1;
yading@10 186 buf_size -= 4;
yading@10 187
yading@10 188 picture_id = bytestream_get_be16(&buf);
yading@10 189
yading@10 190 /* skip 1 unknown byte: Version Number */
yading@10 191 buf++;
yading@10 192
yading@10 193 /* Read the Sequence Description to determine if start of RLE data or appended to previous RLE */
yading@10 194 sequence_desc = bytestream_get_byte(&buf);
yading@10 195
yading@10 196 if (!(sequence_desc & 0x80)) {
yading@10 197 /* Additional RLE data */
yading@10 198 if (buf_size > ctx->pictures[picture_id].rle_remaining_len)
yading@10 199 return -1;
yading@10 200
yading@10 201 memcpy(ctx->pictures[picture_id].rle + ctx->pictures[picture_id].rle_data_len, buf, buf_size);
yading@10 202 ctx->pictures[picture_id].rle_data_len += buf_size;
yading@10 203 ctx->pictures[picture_id].rle_remaining_len -= buf_size;
yading@10 204
yading@10 205 return 0;
yading@10 206 }
yading@10 207
yading@10 208 if (buf_size <= 7)
yading@10 209 return -1;
yading@10 210 buf_size -= 7;
yading@10 211
yading@10 212 /* Decode rle bitmap length, stored size includes width/height data */
yading@10 213 rle_bitmap_len = bytestream_get_be24(&buf) - 2*2;
yading@10 214
yading@10 215 /* Get bitmap dimensions from data */
yading@10 216 width = bytestream_get_be16(&buf);
yading@10 217 height = bytestream_get_be16(&buf);
yading@10 218
yading@10 219 /* Make sure the bitmap is not too large */
yading@10 220 if (avctx->width < width || avctx->height < height) {
yading@10 221 av_log(avctx, AV_LOG_ERROR, "Bitmap dimensions larger than video.\n");
yading@10 222 return -1;
yading@10 223 }
yading@10 224
yading@10 225 if (buf_size > rle_bitmap_len) {
yading@10 226 av_log(avctx, AV_LOG_ERROR, "too much RLE data\n");
yading@10 227 return AVERROR_INVALIDDATA;
yading@10 228 }
yading@10 229
yading@10 230 ctx->pictures[picture_id].w = width;
yading@10 231 ctx->pictures[picture_id].h = height;
yading@10 232
yading@10 233 av_fast_malloc(&ctx->pictures[picture_id].rle, &ctx->pictures[picture_id].rle_buffer_size, rle_bitmap_len);
yading@10 234
yading@10 235 if (!ctx->pictures[picture_id].rle)
yading@10 236 return -1;
yading@10 237
yading@10 238 memcpy(ctx->pictures[picture_id].rle, buf, buf_size);
yading@10 239 ctx->pictures[picture_id].rle_data_len = buf_size;
yading@10 240 ctx->pictures[picture_id].rle_remaining_len = rle_bitmap_len - buf_size;
yading@10 241
yading@10 242 return 0;
yading@10 243 }
yading@10 244
yading@10 245 /**
yading@10 246 * Parse the palette segment packet.
yading@10 247 *
yading@10 248 * The palette segment contains details of the palette,
yading@10 249 * a maximum of 256 colors can be defined.
yading@10 250 *
yading@10 251 * @param avctx contains the current codec context
yading@10 252 * @param buf pointer to the packet to process
yading@10 253 * @param buf_size size of packet to process
yading@10 254 */
yading@10 255 static void parse_palette_segment(AVCodecContext *avctx,
yading@10 256 const uint8_t *buf, int buf_size)
yading@10 257 {
yading@10 258 PGSSubContext *ctx = avctx->priv_data;
yading@10 259
yading@10 260 const uint8_t *buf_end = buf + buf_size;
yading@10 261 const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
yading@10 262 int color_id;
yading@10 263 int y, cb, cr, alpha;
yading@10 264 int r, g, b, r_add, g_add, b_add;
yading@10 265
yading@10 266 /* Skip two null bytes */
yading@10 267 buf += 2;
yading@10 268
yading@10 269 while (buf < buf_end) {
yading@10 270 color_id = bytestream_get_byte(&buf);
yading@10 271 y = bytestream_get_byte(&buf);
yading@10 272 cr = bytestream_get_byte(&buf);
yading@10 273 cb = bytestream_get_byte(&buf);
yading@10 274 alpha = bytestream_get_byte(&buf);
yading@10 275
yading@10 276 YUV_TO_RGB1(cb, cr);
yading@10 277 YUV_TO_RGB2(r, g, b, y);
yading@10 278
yading@10 279 av_dlog(avctx, "Color %d := (%d,%d,%d,%d)\n", color_id, r, g, b, alpha);
yading@10 280
yading@10 281 /* Store color in palette */
yading@10 282 ctx->clut[color_id] = RGBA(r,g,b,alpha);
yading@10 283 }
yading@10 284 }
yading@10 285
yading@10 286 /**
yading@10 287 * Parse the presentation segment packet.
yading@10 288 *
yading@10 289 * The presentation segment contains details on the video
yading@10 290 * width, video height, x & y subtitle position.
yading@10 291 *
yading@10 292 * @param avctx contains the current codec context
yading@10 293 * @param buf pointer to the packet to process
yading@10 294 * @param buf_size size of packet to process
yading@10 295 * @todo TODO: Implement cropping
yading@10 296 */
yading@10 297 static void parse_presentation_segment(AVCodecContext *avctx,
yading@10 298 const uint8_t *buf, int buf_size,
yading@10 299 int64_t pts)
yading@10 300 {
yading@10 301 PGSSubContext *ctx = avctx->priv_data;
yading@10 302
yading@10 303 int w = bytestream_get_be16(&buf);
yading@10 304 int h = bytestream_get_be16(&buf);
yading@10 305
yading@10 306 uint16_t object_index;
yading@10 307
yading@10 308 ctx->presentation.pts = pts;
yading@10 309
yading@10 310 av_dlog(avctx, "Video Dimensions %dx%d\n",
yading@10 311 w, h);
yading@10 312 if (av_image_check_size(w, h, 0, avctx) >= 0)
yading@10 313 avcodec_set_dimensions(avctx, w, h);
yading@10 314
yading@10 315 /* Skip 1 bytes of unknown, frame rate? */
yading@10 316 buf++;
yading@10 317
yading@10 318 ctx->presentation.id_number = bytestream_get_be16(&buf);
yading@10 319
yading@10 320 /*
yading@10 321 * Skip 3 bytes of unknown:
yading@10 322 * state
yading@10 323 * palette_update_flag (0x80),
yading@10 324 * palette_id_to_use,
yading@10 325 */
yading@10 326 buf += 3;
yading@10 327
yading@10 328 ctx->presentation.object_count = bytestream_get_byte(&buf);
yading@10 329 if (!ctx->presentation.object_count)
yading@10 330 return;
yading@10 331
yading@10 332 /* Verify that enough bytes are remaining for all of the objects. */
yading@10 333 buf_size -= 11;
yading@10 334 if (buf_size < ctx->presentation.object_count * 8) {
yading@10 335 ctx->presentation.object_count = 0;
yading@10 336 return;
yading@10 337 }
yading@10 338
yading@10 339 av_freep(&ctx->presentation.objects);
yading@10 340 ctx->presentation.objects = av_malloc(sizeof(PGSSubPictureReference) * ctx->presentation.object_count);
yading@10 341 if (!ctx->presentation.objects) {
yading@10 342 ctx->presentation.object_count = 0;
yading@10 343 return;
yading@10 344 }
yading@10 345
yading@10 346 for (object_index = 0; object_index < ctx->presentation.object_count; ++object_index) {
yading@10 347 PGSSubPictureReference *reference = &ctx->presentation.objects[object_index];
yading@10 348 reference->picture_id = bytestream_get_be16(&buf);
yading@10 349
yading@10 350 /* Skip window_id_ref */
yading@10 351 buf++;
yading@10 352 /* composition_flag (0x80 - object cropped, 0x40 - object forced) */
yading@10 353 reference->composition = bytestream_get_byte(&buf);
yading@10 354
yading@10 355 reference->x = bytestream_get_be16(&buf);
yading@10 356 reference->y = bytestream_get_be16(&buf);
yading@10 357
yading@10 358 /* TODO If cropping, cropping_x, cropping_y, cropping_width, cropping_height (all 2 bytes).*/
yading@10 359 av_dlog(avctx, "Subtitle Placement ID=%d, x=%d, y=%d\n", reference->picture_id, reference->x, reference->y);
yading@10 360
yading@10 361 if (reference->x > avctx->width || reference->y > avctx->height) {
yading@10 362 av_log(avctx, AV_LOG_ERROR, "Subtitle out of video bounds. x = %d, y = %d, video width = %d, video height = %d.\n",
yading@10 363 reference->x, reference->y, avctx->width, avctx->height);
yading@10 364 reference->x = 0;
yading@10 365 reference->y = 0;
yading@10 366 }
yading@10 367 }
yading@10 368 }
yading@10 369
yading@10 370 /**
yading@10 371 * Parse the display segment packet.
yading@10 372 *
yading@10 373 * The display segment controls the updating of the display.
yading@10 374 *
yading@10 375 * @param avctx contains the current codec context
yading@10 376 * @param data pointer to the data pertaining the subtitle to display
yading@10 377 * @param buf pointer to the packet to process
yading@10 378 * @param buf_size size of packet to process
yading@10 379 * @todo TODO: Fix start time, relies on correct PTS, currently too late
yading@10 380 *
yading@10 381 * @todo TODO: Fix end time, normally cleared by a second display
yading@10 382 * @todo segment, which is currently ignored as it clears
yading@10 383 * @todo the subtitle too early.
yading@10 384 */
yading@10 385 static int display_end_segment(AVCodecContext *avctx, void *data,
yading@10 386 const uint8_t *buf, int buf_size)
yading@10 387 {
yading@10 388 AVSubtitle *sub = data;
yading@10 389 PGSSubContext *ctx = avctx->priv_data;
yading@10 390 int64_t pts;
yading@10 391
yading@10 392 uint16_t rect;
yading@10 393
yading@10 394 /*
yading@10 395 * The end display time is a timeout value and is only reached
yading@10 396 * if the next subtitle is later than timeout or subtitle has
yading@10 397 * not been cleared by a subsequent empty display command.
yading@10 398 */
yading@10 399
yading@10 400 pts = ctx->presentation.pts != AV_NOPTS_VALUE ? ctx->presentation.pts : sub->pts;
yading@10 401 memset(sub, 0, sizeof(*sub));
yading@10 402 sub->pts = pts;
yading@10 403 ctx->presentation.pts = AV_NOPTS_VALUE;
yading@10 404
yading@10 405 // Blank if last object_count was 0.
yading@10 406 if (!ctx->presentation.object_count)
yading@10 407 return 1;
yading@10 408
yading@10 409 sub->start_display_time = 0;
yading@10 410 sub->end_display_time = 20000;
yading@10 411 sub->format = 0;
yading@10 412
yading@10 413 sub->num_rects = ctx->presentation.object_count;
yading@10 414 sub->rects = av_mallocz(sizeof(*sub->rects) * sub->num_rects);
yading@10 415
yading@10 416 for (rect = 0; rect < sub->num_rects; ++rect) {
yading@10 417 uint16_t picture_id = ctx->presentation.objects[rect].picture_id;
yading@10 418 sub->rects[rect] = av_mallocz(sizeof(*sub->rects[rect]));
yading@10 419 sub->rects[rect]->x = ctx->presentation.objects[rect].x;
yading@10 420 sub->rects[rect]->y = ctx->presentation.objects[rect].y;
yading@10 421 sub->rects[rect]->w = ctx->pictures[picture_id].w;
yading@10 422 sub->rects[rect]->h = ctx->pictures[picture_id].h;
yading@10 423 sub->rects[rect]->type = SUBTITLE_BITMAP;
yading@10 424
yading@10 425 /* Process bitmap */
yading@10 426 sub->rects[rect]->pict.linesize[0] = ctx->pictures[picture_id].w;
yading@10 427 if (ctx->pictures[picture_id].rle) {
yading@10 428 if (ctx->pictures[picture_id].rle_remaining_len)
yading@10 429 av_log(avctx, AV_LOG_ERROR, "RLE data length %u is %u bytes shorter than expected\n",
yading@10 430 ctx->pictures[picture_id].rle_data_len, ctx->pictures[picture_id].rle_remaining_len);
yading@10 431 if (decode_rle(avctx, sub, rect, ctx->pictures[picture_id].rle, ctx->pictures[picture_id].rle_data_len) < 0)
yading@10 432 return 0;
yading@10 433 }
yading@10 434
yading@10 435 /* Allocate memory for colors */
yading@10 436 sub->rects[rect]->nb_colors = 256;
yading@10 437 sub->rects[rect]->pict.data[1] = av_mallocz(AVPALETTE_SIZE);
yading@10 438
yading@10 439 /* Copy the forced flag */
yading@10 440 sub->rects[rect]->flags = (ctx->presentation.objects[rect].composition & 0x40) != 0 ? AV_SUBTITLE_FLAG_FORCED : 0;
yading@10 441
yading@10 442 if (!ctx->forced_subs_only || ctx->presentation.objects[rect].composition & 0x40)
yading@10 443 memcpy(sub->rects[rect]->pict.data[1], ctx->clut, sub->rects[rect]->nb_colors * sizeof(uint32_t));
yading@10 444 }
yading@10 445
yading@10 446 return 1;
yading@10 447 }
yading@10 448
yading@10 449 static int decode(AVCodecContext *avctx, void *data, int *data_size,
yading@10 450 AVPacket *avpkt)
yading@10 451 {
yading@10 452 const uint8_t *buf = avpkt->data;
yading@10 453 int buf_size = avpkt->size;
yading@10 454 AVSubtitle *sub = data;
yading@10 455
yading@10 456 const uint8_t *buf_end;
yading@10 457 uint8_t segment_type;
yading@10 458 int segment_length;
yading@10 459 int i;
yading@10 460
yading@10 461 av_dlog(avctx, "PGS sub packet:\n");
yading@10 462
yading@10 463 for (i = 0; i < buf_size; i++) {
yading@10 464 av_dlog(avctx, "%02x ", buf[i]);
yading@10 465 if (i % 16 == 15)
yading@10 466 av_dlog(avctx, "\n");
yading@10 467 }
yading@10 468
yading@10 469 if (i & 15)
yading@10 470 av_dlog(avctx, "\n");
yading@10 471
yading@10 472 *data_size = 0;
yading@10 473
yading@10 474 /* Ensure that we have received at a least a segment code and segment length */
yading@10 475 if (buf_size < 3)
yading@10 476 return -1;
yading@10 477
yading@10 478 buf_end = buf + buf_size;
yading@10 479
yading@10 480 /* Step through buffer to identify segments */
yading@10 481 while (buf < buf_end) {
yading@10 482 segment_type = bytestream_get_byte(&buf);
yading@10 483 segment_length = bytestream_get_be16(&buf);
yading@10 484
yading@10 485 av_dlog(avctx, "Segment Length %d, Segment Type %x\n", segment_length, segment_type);
yading@10 486
yading@10 487 if (segment_type != DISPLAY_SEGMENT && segment_length > buf_end - buf)
yading@10 488 break;
yading@10 489
yading@10 490 switch (segment_type) {
yading@10 491 case PALETTE_SEGMENT:
yading@10 492 parse_palette_segment(avctx, buf, segment_length);
yading@10 493 break;
yading@10 494 case PICTURE_SEGMENT:
yading@10 495 parse_picture_segment(avctx, buf, segment_length);
yading@10 496 break;
yading@10 497 case PRESENTATION_SEGMENT:
yading@10 498 parse_presentation_segment(avctx, buf, segment_length, sub->pts);
yading@10 499 break;
yading@10 500 case WINDOW_SEGMENT:
yading@10 501 /*
yading@10 502 * Window Segment Structure (No new information provided):
yading@10 503 * 2 bytes: Unknown,
yading@10 504 * 2 bytes: X position of subtitle,
yading@10 505 * 2 bytes: Y position of subtitle,
yading@10 506 * 2 bytes: Width of subtitle,
yading@10 507 * 2 bytes: Height of subtitle.
yading@10 508 */
yading@10 509 break;
yading@10 510 case DISPLAY_SEGMENT:
yading@10 511 *data_size = display_end_segment(avctx, data, buf, segment_length);
yading@10 512 break;
yading@10 513 default:
yading@10 514 av_log(avctx, AV_LOG_ERROR, "Unknown subtitle segment type 0x%x, length %d\n",
yading@10 515 segment_type, segment_length);
yading@10 516 break;
yading@10 517 }
yading@10 518
yading@10 519 buf += segment_length;
yading@10 520 }
yading@10 521
yading@10 522 return buf_size;
yading@10 523 }
yading@10 524
yading@10 525 #define OFFSET(x) offsetof(PGSSubContext, x)
yading@10 526 #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM
yading@10 527 static const AVOption options[] = {
yading@10 528 {"forced_subs_only", "Only show forced subtitles", OFFSET(forced_subs_only), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, SD},
yading@10 529 { NULL },
yading@10 530 };
yading@10 531
yading@10 532 static const AVClass pgsdec_class = {
yading@10 533 .class_name = "PGS subtitle decoder",
yading@10 534 .item_name = av_default_item_name,
yading@10 535 .option = options,
yading@10 536 .version = LIBAVUTIL_VERSION_INT,
yading@10 537 };
yading@10 538
yading@10 539 AVCodec ff_pgssub_decoder = {
yading@10 540 .name = "pgssub",
yading@10 541 .type = AVMEDIA_TYPE_SUBTITLE,
yading@10 542 .id = AV_CODEC_ID_HDMV_PGS_SUBTITLE,
yading@10 543 .priv_data_size = sizeof(PGSSubContext),
yading@10 544 .init = init_decoder,
yading@10 545 .close = close_decoder,
yading@10 546 .decode = decode,
yading@10 547 .long_name = NULL_IF_CONFIG_SMALL("HDMV Presentation Graphic Stream subtitles"),
yading@10 548 .priv_class = &pgsdec_class,
yading@10 549 };