Mercurial > libavcodec.hg
annotate pgssubdec.c @ 10936:b2ea6b0d17bf libavcodec
Update libx264.c to use new libx264 features
With b_keyframe instead of IDR for detecting keyframes, ffmpeg should now
support periodic encoding with periodic intra refresh (although there is no
interface option for it yet).
Set the new timebase values for full VFR input support.
Bump configure to check for API version 83.
author | darkshikari |
---|---|
date | Tue, 19 Jan 2010 04:00:08 +0000 |
parents | e85fbfe709d8 |
children | 8a4984c5cacc |
rev | line source |
---|---|
10083 | 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 | |
34 #define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) | |
35 | |
36 enum SegmentType { | |
37 PALETTE_SEGMENT = 0x14, | |
38 PICTURE_SEGMENT = 0x15, | |
39 PRESENTATION_SEGMENT = 0x16, | |
40 WINDOW_SEGMENT = 0x17, | |
41 DISPLAY_SEGMENT = 0x80, | |
42 }; | |
43 | |
44 typedef struct PGSSubPresentation { | |
45 int x; | |
46 int y; | |
47 int video_w; | |
48 int video_h; | |
49 int id_number; | |
50 } PGSSubPresentation; | |
51 | |
52 typedef struct PGSSubPicture { | |
53 int w; | |
54 int h; | |
55 uint8_t *rle; | |
56 unsigned int rle_buffer_size, rle_data_len; | |
57 } PGSSubPicture; | |
58 | |
59 typedef struct PGSSubContext { | |
60 PGSSubPresentation presentation; | |
61 uint32_t clut[256]; | |
62 PGSSubPicture picture; | |
63 } PGSSubContext; | |
64 | |
65 static av_cold int init_decoder(AVCodecContext *avctx) | |
66 { | |
67 avctx->pix_fmt = PIX_FMT_RGB32; | |
68 | |
69 return 0; | |
70 } | |
71 | |
72 static av_cold int close_decoder(AVCodecContext *avctx) | |
73 { | |
74 PGSSubContext *ctx = avctx->priv_data; | |
75 | |
76 av_freep(&ctx->picture.rle); | |
77 ctx->picture.rle_buffer_size = 0; | |
78 | |
79 return 0; | |
80 } | |
81 | |
82 /** | |
83 * Decodes the RLE data. | |
84 * | |
85 * The subtitle is stored as an Run Length Encoded image. | |
86 * | |
87 * @param avctx contains the current codec context | |
88 * @param sub pointer to the processed subtitle data | |
89 * @param buf pointer to the RLE data to process | |
90 * @param buf_size size of the RLE data to process | |
91 */ | |
92 static int decode_rle(AVCodecContext *avctx, AVSubtitle *sub, | |
93 const uint8_t *buf, unsigned int buf_size) | |
94 { | |
95 const uint8_t *rle_bitmap_end; | |
96 int pixel_count, line_count; | |
97 | |
98 rle_bitmap_end = buf + buf_size; | |
99 | |
100 sub->rects[0]->pict.data[0] = av_malloc(sub->rects[0]->w * sub->rects[0]->h); | |
101 | |
102 if (!sub->rects[0]->pict.data[0]) | |
103 return -1; | |
104 | |
105 pixel_count = 0; | |
106 line_count = 0; | |
107 | |
108 while (buf < rle_bitmap_end && line_count < sub->rects[0]->h) { | |
109 uint8_t flags, color; | |
110 int run; | |
111 | |
112 color = bytestream_get_byte(&buf); | |
113 run = 1; | |
114 | |
115 if (color == 0x00) { | |
116 flags = bytestream_get_byte(&buf); | |
117 run = flags & 0x3f; | |
118 if (flags & 0x40) | |
119 run = (run << 8) + bytestream_get_byte(&buf); | |
120 color = flags & 0x80 ? bytestream_get_byte(&buf) : 0; | |
121 } | |
122 | |
123 if (run > 0 && pixel_count + run <= sub->rects[0]->w * sub->rects[0]->h) { | |
124 memset(sub->rects[0]->pict.data[0] + pixel_count, color, run); | |
125 pixel_count += run; | |
126 } else if (!run) { | |
127 /* | |
128 * New Line. Check if correct pixels decoded, if not display warning | |
129 * and adjust bitmap pointer to correct new line position. | |
130 */ | |
131 if (pixel_count % sub->rects[0]->w > 0) | |
132 av_log(avctx, AV_LOG_ERROR, "Decoded %d pixels, when line should be %d pixels\n", | |
133 pixel_count % sub->rects[0]->w, sub->rects[0]->w); | |
134 line_count++; | |
135 } | |
136 } | |
137 | |
138 dprintf(avctx, "Pixel Count = %d, Area = %d\n", pixel_count, sub->rects[0]->w * sub->rects[0]->h); | |
139 | |
140 return 0; | |
141 } | |
142 | |
143 /** | |
144 * Parses the picture segment packet. | |
145 * | |
146 * The picture segment contains details on the sequence id, | |
147 * width, height and Run Length Encoded (RLE) bitmap data. | |
148 * | |
149 * @param avctx contains the current codec context | |
150 * @param buf pointer to the packet to process | |
151 * @param buf_size size of packet to process | |
152 * @todo TODO: Enable support for RLE data over multiple packets | |
153 */ | |
154 static int parse_picture_segment(AVCodecContext *avctx, | |
155 const uint8_t *buf, int buf_size) | |
156 { | |
157 PGSSubContext *ctx = avctx->priv_data; | |
158 | |
159 uint8_t sequence_desc; | |
160 unsigned int rle_bitmap_len, width, height; | |
161 | |
162 /* skip 3 unknown bytes: Object ID (2 bytes), Version Number */ | |
163 buf += 3; | |
164 | |
165 /* Read the Sequence Description to determine if start of RLE data or appended to previous RLE */ | |
166 sequence_desc = bytestream_get_byte(&buf); | |
167 | |
168 if (!(sequence_desc & 0x80)) { | |
169 av_log(avctx, AV_LOG_ERROR, "Decoder does not support object data over multiple packets.\n"); | |
170 return -1; | |
171 } | |
172 | |
173 /* Decode rle bitmap length */ | |
174 rle_bitmap_len = bytestream_get_be24(&buf); | |
175 | |
176 /* Check to ensure we have enough data for rle_bitmap_length if just a single packet */ | |
177 if (rle_bitmap_len > buf_size - 7) { | |
178 av_log(avctx, AV_LOG_ERROR, "Not enough RLE data for specified length of %d.\n", rle_bitmap_len); | |
179 return -1; | |
180 } | |
181 | |
182 ctx->picture.rle_data_len = rle_bitmap_len; | |
183 | |
184 /* Get bitmap dimensions from data */ | |
185 width = bytestream_get_be16(&buf); | |
186 height = bytestream_get_be16(&buf); | |
187 | |
188 /* Make sure the bitmap is not too large */ | |
189 if (ctx->presentation.video_w < width || ctx->presentation.video_h < height) { | |
190 av_log(avctx, AV_LOG_ERROR, "Bitmap dimensions larger then video.\n"); | |
191 return -1; | |
192 } | |
193 | |
194 ctx->picture.w = width; | |
195 ctx->picture.h = height; | |
196 | |
197 av_fast_malloc(&ctx->picture.rle, &ctx->picture.rle_buffer_size, rle_bitmap_len); | |
198 | |
199 if (!ctx->picture.rle) | |
200 return -1; | |
201 | |
202 memcpy(ctx->picture.rle, buf, rle_bitmap_len); | |
203 | |
204 return 0; | |
205 } | |
206 | |
207 /** | |
208 * Parses the palette segment packet. | |
209 * | |
210 * The palette segment contains details of the palette, | |
211 * a maximum of 256 colors can be defined. | |
212 * | |
213 * @param avctx contains the current codec context | |
214 * @param buf pointer to the packet to process | |
215 * @param buf_size size of packet to process | |
216 */ | |
217 static void parse_palette_segment(AVCodecContext *avctx, | |
218 const uint8_t *buf, int buf_size) | |
219 { | |
220 PGSSubContext *ctx = avctx->priv_data; | |
221 | |
222 const uint8_t *buf_end = buf + buf_size; | |
223 const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; | |
224 int color_id; | |
225 int y, cb, cr, alpha; | |
226 int r, g, b, r_add, g_add, b_add; | |
227 | |
228 /* Skip two null bytes */ | |
229 buf += 2; | |
230 | |
231 while (buf < buf_end) { | |
232 color_id = bytestream_get_byte(&buf); | |
233 y = bytestream_get_byte(&buf); | |
234 cb = bytestream_get_byte(&buf); | |
235 cr = bytestream_get_byte(&buf); | |
236 alpha = bytestream_get_byte(&buf); | |
237 | |
238 YUV_TO_RGB1(cb, cr); | |
239 YUV_TO_RGB2(r, g, b, y); | |
240 | |
241 dprintf(avctx, "Color %d := (%d,%d,%d,%d)\n", color_id, r, g, b, alpha); | |
242 | |
243 /* Store color in palette */ | |
244 ctx->clut[color_id] = RGBA(r,g,b,alpha); | |
245 } | |
246 } | |
247 | |
248 /** | |
249 * Parses the presentation segment packet. | |
250 * | |
251 * The presentation segment contains details on the video | |
252 * width, video height, x & y subtitle position. | |
253 * | |
254 * @param avctx contains the current codec context | |
255 * @param buf pointer to the packet to process | |
256 * @param buf_size size of packet to process | |
257 * @todo TODO: Implement cropping | |
258 * @todo TODO: Implement forcing of subtitles | |
259 * @todo TODO: Blanking of subtitle | |
260 */ | |
261 static void parse_presentation_segment(AVCodecContext *avctx, | |
262 const uint8_t *buf, int buf_size) | |
263 { | |
264 PGSSubContext *ctx = avctx->priv_data; | |
265 | |
266 int x, y; | |
267 uint8_t block; | |
268 | |
269 ctx->presentation.video_w = bytestream_get_be16(&buf); | |
270 ctx->presentation.video_h = bytestream_get_be16(&buf); | |
271 | |
272 dprintf(avctx, "Video Dimensions %dx%d\n", | |
273 ctx->presentation.video_w, ctx->presentation.video_h); | |
274 | |
275 /* Skip 1 bytes of unknown, frame rate? */ | |
276 buf++; | |
277 | |
278 ctx->presentation.id_number = bytestream_get_be16(&buf); | |
279 | |
280 /* Next byte is the state. */ | |
281 block = bytestream_get_byte(&buf);; | |
282 if (block == 0x80) { | |
283 /* | |
284 * Skip 7 bytes of unknown: | |
285 * palette_update_flag (0x80), | |
286 * palette_id_to_use, | |
287 * Object Number (if > 0 determines if more data to process), | |
288 * object_id_ref (2 bytes), | |
289 * window_id_ref, | |
290 * composition_flag (0x80 - object cropped, 0x40 - object forced) | |
291 */ | |
292 buf += 7; | |
293 | |
294 x = bytestream_get_be16(&buf); | |
295 y = bytestream_get_be16(&buf); | |
296 | |
297 /* TODO If cropping, cropping_x, cropping_y, cropping_width, cropping_height (all 2 bytes).*/ | |
298 | |
299 dprintf(avctx, "Subtitle Placement x=%d, y=%d\n", x, y); | |
300 | |
301 if (x > ctx->presentation.video_w || y > ctx->presentation.video_h) { | |
302 av_log(avctx, AV_LOG_ERROR, "Subtitle out of video bounds. x = %d, y = %d, video width = %d, video height = %d.\n", | |
303 x, y, ctx->presentation.video_w, ctx->presentation.video_h); | |
304 x = 0; y = 0; | |
305 } | |
306 | |
307 /* Fill in dimensions */ | |
308 ctx->presentation.x = x; | |
309 ctx->presentation.y = y; | |
310 } else if (block == 0x00) { | |
311 /* TODO: Blank context as subtitle should not be displayed. | |
312 * If the subtitle is blanked now the subtitle is not | |
313 * on screen long enough to read, due to a delay in | |
314 * initial display timing. | |
315 */ | |
316 } | |
317 } | |
318 | |
319 /** | |
320 * Parses the display segment packet. | |
321 * | |
322 * The display segment controls the updating of the display. | |
323 * | |
324 * @param avctx contains the current codec context | |
325 * @param data pointer to the data pertaining the subtitle to display | |
326 * @param buf pointer to the packet to process | |
327 * @param buf_size size of packet to process | |
328 * @todo TODO: Fix start time, relies on correct PTS, currently too late | |
329 * | |
330 * @todo TODO: Fix end time, normally cleared by a second display | |
331 * @todo segment, which is currently ignored as it clears | |
332 * @todo the subtitle too early. | |
333 */ | |
334 static int display_end_segment(AVCodecContext *avctx, void *data, | |
335 const uint8_t *buf, int buf_size) | |
336 { | |
337 AVSubtitle *sub = data; | |
338 PGSSubContext *ctx = avctx->priv_data; | |
339 | |
340 /* | |
341 * The end display time is a timeout value and is only reached | |
342 * if the next subtitle is later then timeout or subtitle has | |
343 * not been cleared by a subsequent empty display command. | |
344 */ | |
345 | |
10087 | 346 memset(sub, 0, sizeof(*sub)); |
10083 | 347 sub->start_display_time = 0; |
348 sub->end_display_time = 20000; | |
349 sub->format = 0; | |
350 | |
10089 | 351 sub->rects = av_mallocz(sizeof(*sub->rects)); |
352 sub->rects[0] = av_mallocz(sizeof(*sub->rects[0])); | |
353 sub->num_rects = 1; | |
10083 | 354 |
355 sub->rects[0]->x = ctx->presentation.x; | |
356 sub->rects[0]->y = ctx->presentation.y; | |
357 sub->rects[0]->w = ctx->picture.w; | |
358 sub->rects[0]->h = ctx->picture.h; | |
359 sub->rects[0]->type = SUBTITLE_BITMAP; | |
360 | |
361 /* Process bitmap */ | |
362 sub->rects[0]->pict.linesize[0] = ctx->picture.w; | |
363 | |
364 if (ctx->picture.rle) | |
365 if(decode_rle(avctx, sub, ctx->picture.rle, ctx->picture.rle_data_len) < 0) | |
366 return 0; | |
367 | |
368 /* Allocate memory for colors */ | |
369 sub->rects[0]->nb_colors = 256; | |
10092
e85fbfe709d8
Always allocate a buffer of AVPALETTE_SIZE for palette in the
cehoyos
parents:
10089
diff
changeset
|
370 sub->rects[0]->pict.data[1] = av_mallocz(AVPALETTE_SIZE); |
10083 | 371 |
372 memcpy(sub->rects[0]->pict.data[1], ctx->clut, sub->rects[0]->nb_colors * sizeof(uint32_t)); | |
373 | |
374 return 1; | |
375 } | |
376 | |
377 static int decode(AVCodecContext *avctx, void *data, int *data_size, | |
378 AVPacket *avpkt) | |
379 { | |
380 const uint8_t *buf = avpkt->data; | |
381 int buf_size = avpkt->size; | |
382 | |
383 const uint8_t *buf_end; | |
384 uint8_t segment_type; | |
385 int segment_length; | |
386 | |
387 #ifdef DEBUG_PACKET_CONTENTS | |
388 int i; | |
389 | |
390 av_log(avctx, AV_LOG_INFO, "PGS sub packet:\n"); | |
391 | |
392 for (i = 0; i < buf_size; i++) { | |
393 av_log(avctx, AV_LOG_INFO, "%02x ", buf[i]); | |
394 if (i % 16 == 15) | |
395 av_log(avctx, AV_LOG_INFO, "\n"); | |
396 } | |
397 | |
398 if (i & 15) | |
399 av_log(avctx, AV_LOG_INFO, "\n"); | |
400 #endif | |
401 | |
402 *data_size = 0; | |
403 | |
404 /* Ensure that we have received at a least a segment code and segment length */ | |
405 if (buf_size < 3) | |
406 return -1; | |
407 | |
408 buf_end = buf + buf_size; | |
409 | |
410 /* Step through buffer to identify segments */ | |
411 while (buf < buf_end) { | |
412 segment_type = bytestream_get_byte(&buf); | |
413 segment_length = bytestream_get_be16(&buf); | |
414 | |
415 dprintf(avctx, "Segment Length %d, Segment Type %x\n", segment_length, segment_type); | |
416 | |
417 if (segment_type != DISPLAY_SEGMENT && segment_length > buf_end - buf) | |
418 break; | |
419 | |
420 switch (segment_type) { | |
421 case PALETTE_SEGMENT: | |
422 parse_palette_segment(avctx, buf, segment_length); | |
423 break; | |
424 case PICTURE_SEGMENT: | |
425 parse_picture_segment(avctx, buf, segment_length); | |
426 break; | |
427 case PRESENTATION_SEGMENT: | |
428 parse_presentation_segment(avctx, buf, segment_length); | |
429 break; | |
430 case WINDOW_SEGMENT: | |
431 /* | |
432 * Window Segment Structure (No new information provided): | |
433 * 2 bytes: Unkown, | |
434 * 2 bytes: X position of subtitle, | |
435 * 2 bytes: Y position of subtitle, | |
436 * 2 bytes: Width of subtitle, | |
437 * 2 bytes: Height of subtitle. | |
438 */ | |
439 break; | |
440 case DISPLAY_SEGMENT: | |
441 *data_size = display_end_segment(avctx, data, buf, segment_length); | |
442 break; | |
443 default: | |
444 av_log(avctx, AV_LOG_ERROR, "Unknown subtitle segment type 0x%x, length %d\n", | |
445 segment_type, segment_length); | |
446 break; | |
447 } | |
448 | |
449 buf += segment_length; | |
450 } | |
451 | |
452 return buf_size; | |
453 } | |
454 | |
455 AVCodec pgssub_decoder = { | |
456 "pgssub", | |
457 CODEC_TYPE_SUBTITLE, | |
458 CODEC_ID_HDMV_PGS_SUBTITLE, | |
459 sizeof(PGSSubContext), | |
460 init_decoder, | |
461 NULL, | |
462 close_decoder, | |
463 decode, | |
464 .long_name = NULL_IF_CONFIG_SMALL("HDMV Presentation Graphic Stream subtitles"), | |
465 }; |