-
-static int is_transp(const uint8_t *buf, int pitch, int n,
- const uint8_t *transp_color)
-{
- int i;
- for(i = 0; i < n; i++) {
- if (!transp_color[*buf])
- return 0;
- buf += pitch;
- }
- return 1;
-}
-
-/* return 0 if empty rectangle, 1 if non empty */
-static int find_smallest_bounding_rectangle(AVSubtitle *s)
-{
- uint8_t transp_color[256];
- int y1, y2, x1, x2, y, w, h, i;
- uint8_t *bitmap;
-
- if (s->num_rects == 0 || s->rects == NULL || s->rects[0].w <= 0 || s->rects[0].h <= 0)
- return 0;
-
- memset(transp_color, 0, 256);
- for(i = 0; i < s->rects[0].nb_colors; i++) {
- if ((s->rects[0].rgba_palette[i] >> 24) == 0)
- transp_color[i] = 1;
- }
- y1 = 0;
- while (y1 < s->rects[0].h && is_transp(s->rects[0].bitmap + y1 * s->rects[0].linesize,
- 1, s->rects[0].w, transp_color))
- y1++;
- if (y1 == s->rects[0].h) {
- av_freep(&s->rects[0].bitmap);
- s->rects[0].w = s->rects[0].h = 0;
- return 0;
- }
-
- y2 = s->rects[0].h - 1;
- while (y2 > 0 && is_transp(s->rects[0].bitmap + y2 * s->rects[0].linesize, 1,
- s->rects[0].w, transp_color))
- y2--;
- x1 = 0;
- while (x1 < (s->rects[0].w - 1) && is_transp(s->rects[0].bitmap + x1, s->rects[0].linesize,
- s->rects[0].h, transp_color))
- x1++;
- x2 = s->rects[0].w - 1;
- while (x2 > 0 && is_transp(s->rects[0].bitmap + x2, s->rects[0].linesize, s->rects[0].h,
- transp_color))
- x2--;
- w = x2 - x1 + 1;
- h = y2 - y1 + 1;
- bitmap = av_malloc(w * h);
- if (!bitmap)
- return 1;
- for(y = 0; y < h; y++) {
- memcpy(bitmap + w * y, s->rects[0].bitmap + x1 + (y1 + y) * s->rects[0].linesize, w);
- }
- av_freep(&s->rects[0].bitmap);
- s->rects[0].bitmap = bitmap;
- s->rects[0].linesize = w;
- s->rects[0].w = w;
- s->rects[0].h = h;
- s->rects[0].x += x1;
- s->rects[0].y += y1;
- return 1;
-}
-
-static int dvdsub_close_decoder(AVCodecContext *avctx)
-{
- return 0;
-}
-
-#ifdef DEBUG
-#undef fprintf
-static void ppm_save(const char *filename, uint8_t *bitmap, int w, int h,
- uint32_t *rgba_palette)
-{
- int x, y, v;
- FILE *f;
-
- f = fopen(filename, "w");
- if (!f) {
- perror(filename);
- exit(1);
- }
- fprintf(f, "P6\n"
- "%d %d\n"
- "%d\n",
- w, h, 255);
- for(y = 0; y < h; y++) {
- for(x = 0; x < w; x++) {
- v = rgba_palette[bitmap[y * w + x]];
- putc((v >> 16) & 0xff, f);
- putc((v >> 8) & 0xff, f);
- putc((v >> 0) & 0xff, f);
- }
- }
- fclose(f);
-}
-#endif
-
-static int dvdsub_decode(AVCodecContext *avctx,
- void *data, int *data_size,
- uint8_t *buf, int buf_size)
-{
- AVSubtitle *sub = (void *)data;
- int is_menu;
-
- is_menu = decode_dvd_subtitles(sub, buf, buf_size);
-
- if (is_menu < 0) {
- no_subtitle:
- *data_size = 0;
-
- return buf_size;
- }
- if (!is_menu && find_smallest_bounding_rectangle(sub) == 0)
- goto no_subtitle;
-
-#if defined(DEBUG)
- av_log(NULL, AV_LOG_INFO, "start=%d ms end =%d ms\n",
- sub->start_display_time,
- sub->end_display_time);
- ppm_save("/tmp/a.ppm", sub->rects[0].bitmap,
- sub->rects[0].w, sub->rects[0].h, sub->rects[0].rgba_palette);
-#endif
-
- *data_size = 1;
- return buf_size;
-}
-
-AVCodec dvdsub_decoder = {
- "dvdsub",
- CODEC_TYPE_SUBTITLE,
- CODEC_ID_DVD_SUBTITLE,
- sizeof(DVDSubContext),
- dvdsub_init_decoder,
- NULL,
- dvdsub_close_decoder,
- dvdsub_decode,
-};
-
-/* parser definition */
-typedef struct DVDSubParseContext {
- uint8_t *packet;
- int packet_len;
- int packet_index;
-} DVDSubParseContext;
-
-static int dvdsub_parse_init(AVCodecParserContext *s)
-{
- return 0;
-}
-
-static int dvdsub_parse(AVCodecParserContext *s,
- AVCodecContext *avctx,
- uint8_t **poutbuf, int *poutbuf_size,
- const uint8_t *buf, int buf_size)
-{
- DVDSubParseContext *pc = s->priv_data;
-
- if (pc->packet_index == 0) {
- if (buf_size < 2)
- return 0;
- pc->packet_len = (buf[0] << 8) | buf[1];
- av_freep(&pc->packet);
- pc->packet = av_malloc(pc->packet_len);
- }
- if (pc->packet) {
- if (pc->packet_index + buf_size <= pc->packet_len) {
- memcpy(pc->packet + pc->packet_index, buf, buf_size);
- pc->packet_index += buf_size;
- if (pc->packet_index >= pc->packet_len) {
- *poutbuf = pc->packet;
- *poutbuf_size = pc->packet_len;
- pc->packet_index = 0;
- return buf_size;
- }
- } else {
- /* erroneous size */
- pc->packet_index = 0;
- }
- }
- *poutbuf = NULL;
- *poutbuf_size = 0;
- return buf_size;
-}
-
-static void dvdsub_parse_close(AVCodecParserContext *s)
-{
- DVDSubParseContext *pc = s->priv_data;
- av_freep(&pc->packet);
-}
-
-AVCodecParser dvdsub_parser = {
- { CODEC_ID_DVD_SUBTITLE },
- sizeof(DVDSubParseContext),
- dvdsub_parse_init,
- dvdsub_parse,
- dvdsub_parse_close,
-};