3 * Copyright (c) 2009 Stephen Backway
5 * This file is part of Libav.
7 * Libav 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.
12 * Libav 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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * PGS subtitle decoder
29 #include "bytestream.h"
30 #include "libavutil/colorspace.h"
31 #include "libavutil/imgutils.h"
33 #define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
36 PALETTE_SEGMENT
= 0x14,
37 PICTURE_SEGMENT
= 0x15,
38 PRESENTATION_SEGMENT
= 0x16,
39 WINDOW_SEGMENT
= 0x17,
40 DISPLAY_SEGMENT
= 0x80,
43 typedef struct PGSSubPresentation
{
48 uint8_t composition_flag
;
52 typedef struct PGSSubPicture
{
56 unsigned int rle_buffer_size
, rle_data_len
;
57 unsigned int rle_remaining_len
;
60 typedef struct PGSSubContext
{
61 PGSSubPresentation presentation
;
63 PGSSubPicture picture
;
66 static av_cold
int init_decoder(AVCodecContext
*avctx
)
68 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
73 static av_cold
int close_decoder(AVCodecContext
*avctx
)
75 PGSSubContext
*ctx
= avctx
->priv_data
;
77 av_freep(&ctx
->picture
.rle
);
78 ctx
->picture
.rle_buffer_size
= 0;
84 * Decode the RLE data.
86 * The subtitle is stored as an Run Length Encoded image.
88 * @param avctx contains the current codec context
89 * @param sub pointer to the processed subtitle data
90 * @param buf pointer to the RLE data to process
91 * @param buf_size size of the RLE data to process
93 static int decode_rle(AVCodecContext
*avctx
, AVSubtitle
*sub
,
94 const uint8_t *buf
, unsigned int buf_size
)
96 const uint8_t *rle_bitmap_end
;
97 int pixel_count
, line_count
;
99 rle_bitmap_end
= buf
+ buf_size
;
101 sub
->rects
[0]->pict
.data
[0] = av_malloc(sub
->rects
[0]->w
* sub
->rects
[0]->h
);
103 if (!sub
->rects
[0]->pict
.data
[0])
109 while (buf
< rle_bitmap_end
&& line_count
< sub
->rects
[0]->h
) {
110 uint8_t flags
, color
;
113 color
= bytestream_get_byte(&buf
);
117 flags
= bytestream_get_byte(&buf
);
120 run
= (run
<< 8) + bytestream_get_byte(&buf
);
121 color
= flags
& 0x80 ? bytestream_get_byte(&buf
) : 0;
124 if (run
> 0 && pixel_count
+ run
<= sub
->rects
[0]->w
* sub
->rects
[0]->h
) {
125 memset(sub
->rects
[0]->pict
.data
[0] + pixel_count
, color
, run
);
129 * New Line. Check if correct pixels decoded, if not display warning
130 * and adjust bitmap pointer to correct new line position.
132 if (pixel_count
% sub
->rects
[0]->w
> 0)
133 av_log(avctx
, AV_LOG_ERROR
, "Decoded %d pixels, when line should be %d pixels\n",
134 pixel_count
% sub
->rects
[0]->w
, sub
->rects
[0]->w
);
139 if (pixel_count
< sub
->rects
[0]->w
* sub
->rects
[0]->h
) {
140 av_log(avctx
, AV_LOG_ERROR
, "Insufficient RLE data for subtitle\n");
144 av_dlog(avctx
, "Pixel Count = %d, Area = %d\n", pixel_count
, sub
->rects
[0]->w
* sub
->rects
[0]->h
);
150 * Parse the picture segment packet.
152 * The picture segment contains details on the sequence id,
153 * width, height and Run Length Encoded (RLE) bitmap data.
155 * @param avctx contains the current codec context
156 * @param buf pointer to the packet to process
157 * @param buf_size size of packet to process
158 * @todo TODO: Enable support for RLE data over multiple packets
160 static int parse_picture_segment(AVCodecContext
*avctx
,
161 const uint8_t *buf
, int buf_size
)
163 PGSSubContext
*ctx
= avctx
->priv_data
;
165 uint8_t sequence_desc
;
166 unsigned int rle_bitmap_len
, width
, height
;
172 /* skip 3 unknown bytes: Object ID (2 bytes), Version Number */
175 /* Read the Sequence Description to determine if start of RLE data or appended to previous RLE */
176 sequence_desc
= bytestream_get_byte(&buf
);
178 if (!(sequence_desc
& 0x80)) {
179 /* Additional RLE data */
180 if (buf_size
> ctx
->picture
.rle_remaining_len
)
183 memcpy(ctx
->picture
.rle
+ ctx
->picture
.rle_data_len
, buf
, buf_size
);
184 ctx
->picture
.rle_data_len
+= buf_size
;
185 ctx
->picture
.rle_remaining_len
-= buf_size
;
194 /* Decode rle bitmap length, stored size includes width/height data */
195 rle_bitmap_len
= bytestream_get_be24(&buf
) - 2*2;
197 /* Get bitmap dimensions from data */
198 width
= bytestream_get_be16(&buf
);
199 height
= bytestream_get_be16(&buf
);
201 /* Make sure the bitmap is not too large */
202 if (avctx
->width
< width
|| avctx
->height
< height
) {
203 av_log(avctx
, AV_LOG_ERROR
, "Bitmap dimensions larger than video.\n");
207 ctx
->picture
.w
= width
;
208 ctx
->picture
.h
= height
;
210 av_fast_malloc(&ctx
->picture
.rle
, &ctx
->picture
.rle_buffer_size
, rle_bitmap_len
);
212 if (!ctx
->picture
.rle
)
215 memcpy(ctx
->picture
.rle
, buf
, buf_size
);
216 ctx
->picture
.rle_data_len
= buf_size
;
217 ctx
->picture
.rle_remaining_len
= rle_bitmap_len
- buf_size
;
223 * Parse the palette segment packet.
225 * The palette segment contains details of the palette,
226 * a maximum of 256 colors can be defined.
228 * @param avctx contains the current codec context
229 * @param buf pointer to the packet to process
230 * @param buf_size size of packet to process
232 static void parse_palette_segment(AVCodecContext
*avctx
,
233 const uint8_t *buf
, int buf_size
)
235 PGSSubContext
*ctx
= avctx
->priv_data
;
237 const uint8_t *buf_end
= buf
+ buf_size
;
238 const uint8_t *cm
= ff_cropTbl
+ MAX_NEG_CROP
;
240 int y
, cb
, cr
, alpha
;
241 int r
, g
, b
, r_add
, g_add
, b_add
;
243 /* Skip two null bytes */
246 while (buf
< buf_end
) {
247 color_id
= bytestream_get_byte(&buf
);
248 y
= bytestream_get_byte(&buf
);
249 cr
= bytestream_get_byte(&buf
);
250 cb
= bytestream_get_byte(&buf
);
251 alpha
= bytestream_get_byte(&buf
);
254 YUV_TO_RGB2(r
, g
, b
, y
);
256 av_dlog(avctx
, "Color %d := (%d,%d,%d,%d)\n", color_id
, r
, g
, b
, alpha
);
258 /* Store color in palette */
259 ctx
->clut
[color_id
] = RGBA(r
,g
,b
,alpha
);
264 * Parse the presentation segment packet.
266 * The presentation segment contains details on the video
267 * width, video height, x & y subtitle position.
269 * @param avctx contains the current codec context
270 * @param buf pointer to the packet to process
271 * @param buf_size size of packet to process
272 * @todo TODO: Implement cropping
273 * @todo TODO: Implement forcing of subtitles
275 static void parse_presentation_segment(AVCodecContext
*avctx
,
276 const uint8_t *buf
, int buf_size
,
279 PGSSubContext
*ctx
= avctx
->priv_data
;
283 int w
= bytestream_get_be16(&buf
);
284 int h
= bytestream_get_be16(&buf
);
286 ctx
->presentation
.pts
= pts
;
288 av_dlog(avctx
, "Video Dimensions %dx%d\n",
290 if (av_image_check_size(w
, h
, 0, avctx
) >= 0)
291 avcodec_set_dimensions(avctx
, w
, h
);
293 /* Skip 1 bytes of unknown, frame rate? */
296 ctx
->presentation
.id_number
= bytestream_get_be16(&buf
);
299 * Skip 3 bytes of unknown:
301 * palette_update_flag (0x80),
306 ctx
->presentation
.object_number
= bytestream_get_byte(&buf
);
307 ctx
->presentation
.composition_flag
= 0;
308 if (!ctx
->presentation
.object_number
)
312 * Skip 3 bytes of unknown:
313 * object_id_ref (2 bytes),
317 ctx
->presentation
.composition_flag
= bytestream_get_byte(&buf
);
319 x
= bytestream_get_be16(&buf
);
320 y
= bytestream_get_be16(&buf
);
322 /* TODO If cropping, cropping_x, cropping_y, cropping_width, cropping_height (all 2 bytes).*/
324 av_dlog(avctx
, "Subtitle Placement x=%d, y=%d\n", x
, y
);
326 if (x
> avctx
->width
|| y
> avctx
->height
) {
327 av_log(avctx
, AV_LOG_ERROR
, "Subtitle out of video bounds. x = %d, y = %d, video width = %d, video height = %d.\n",
328 x
, y
, avctx
->width
, avctx
->height
);
332 /* Fill in dimensions */
333 ctx
->presentation
.x
= x
;
334 ctx
->presentation
.y
= y
;
338 * Parse the display segment packet.
340 * The display segment controls the updating of the display.
342 * @param avctx contains the current codec context
343 * @param data pointer to the data pertaining the subtitle to display
344 * @param buf pointer to the packet to process
345 * @param buf_size size of packet to process
346 * @todo TODO: Fix start time, relies on correct PTS, currently too late
348 * @todo TODO: Fix end time, normally cleared by a second display
349 * @todo segment, which is currently ignored as it clears
350 * @todo the subtitle too early.
352 static int display_end_segment(AVCodecContext
*avctx
, void *data
,
353 const uint8_t *buf
, int buf_size
)
355 AVSubtitle
*sub
= data
;
356 PGSSubContext
*ctx
= avctx
->priv_data
;
359 * The end display time is a timeout value and is only reached
360 * if the next subtitle is later then timeout or subtitle has
361 * not been cleared by a subsequent empty display command.
364 memset(sub
, 0, sizeof(*sub
));
365 sub
->pts
= ctx
->presentation
.pts
;
367 // Blank if last object_number was 0.
368 // Note that this may be wrong for more complex subtitles.
369 if (!ctx
->presentation
.object_number
)
371 sub
->start_display_time
= 0;
372 sub
->end_display_time
= 20000;
375 sub
->rects
= av_mallocz(sizeof(*sub
->rects
));
376 sub
->rects
[0] = av_mallocz(sizeof(*sub
->rects
[0]));
379 if (ctx
->presentation
.composition_flag
& 0x40)
380 sub
->rects
[0]->flags
|= AV_SUBTITLE_FLAG_FORCED
;
382 sub
->rects
[0]->x
= ctx
->presentation
.x
;
383 sub
->rects
[0]->y
= ctx
->presentation
.y
;
384 sub
->rects
[0]->w
= ctx
->picture
.w
;
385 sub
->rects
[0]->h
= ctx
->picture
.h
;
386 sub
->rects
[0]->type
= SUBTITLE_BITMAP
;
389 sub
->rects
[0]->pict
.linesize
[0] = ctx
->picture
.w
;
391 if (ctx
->picture
.rle
) {
392 if (ctx
->picture
.rle_remaining_len
)
393 av_log(avctx
, AV_LOG_ERROR
, "RLE data length %u is %u bytes shorter than expected\n",
394 ctx
->picture
.rle_data_len
, ctx
->picture
.rle_remaining_len
);
395 if(decode_rle(avctx
, sub
, ctx
->picture
.rle
, ctx
->picture
.rle_data_len
) < 0)
398 /* Allocate memory for colors */
399 sub
->rects
[0]->nb_colors
= 256;
400 sub
->rects
[0]->pict
.data
[1] = av_mallocz(AVPALETTE_SIZE
);
402 memcpy(sub
->rects
[0]->pict
.data
[1], ctx
->clut
, sub
->rects
[0]->nb_colors
* sizeof(uint32_t));
407 static int decode(AVCodecContext
*avctx
, void *data
, int *data_size
,
410 const uint8_t *buf
= avpkt
->data
;
411 int buf_size
= avpkt
->size
;
413 const uint8_t *buf_end
;
414 uint8_t segment_type
;
418 av_dlog(avctx
, "PGS sub packet:\n");
420 for (i
= 0; i
< buf_size
; i
++) {
421 av_dlog(avctx
, "%02x ", buf
[i
]);
423 av_dlog(avctx
, "\n");
427 av_dlog(avctx
, "\n");
431 /* Ensure that we have received at a least a segment code and segment length */
435 buf_end
= buf
+ buf_size
;
437 /* Step through buffer to identify segments */
438 while (buf
< buf_end
) {
439 segment_type
= bytestream_get_byte(&buf
);
440 segment_length
= bytestream_get_be16(&buf
);
442 av_dlog(avctx
, "Segment Length %d, Segment Type %x\n", segment_length
, segment_type
);
444 if (segment_type
!= DISPLAY_SEGMENT
&& segment_length
> buf_end
- buf
)
447 switch (segment_type
) {
448 case PALETTE_SEGMENT
:
449 parse_palette_segment(avctx
, buf
, segment_length
);
451 case PICTURE_SEGMENT
:
452 parse_picture_segment(avctx
, buf
, segment_length
);
454 case PRESENTATION_SEGMENT
:
455 parse_presentation_segment(avctx
, buf
, segment_length
, avpkt
->pts
);
459 * Window Segment Structure (No new information provided):
461 * 2 bytes: X position of subtitle,
462 * 2 bytes: Y position of subtitle,
463 * 2 bytes: Width of subtitle,
464 * 2 bytes: Height of subtitle.
467 case DISPLAY_SEGMENT
:
468 *data_size
= display_end_segment(avctx
, data
, buf
, segment_length
);
471 av_log(avctx
, AV_LOG_ERROR
, "Unknown subtitle segment type 0x%x, length %d\n",
472 segment_type
, segment_length
);
476 buf
+= segment_length
;
482 AVCodec ff_pgssub_decoder
= {
484 .type
= AVMEDIA_TYPE_SUBTITLE
,
485 .id
= AV_CODEC_ID_HDMV_PGS_SUBTITLE
,
486 .priv_data_size
= sizeof(PGSSubContext
),
487 .init
= init_decoder
,
488 .close
= close_decoder
,
490 .long_name
= NULL_IF_CONFIG_SMALL("HDMV Presentation Graphic Stream subtitles"),