diff options
Diffstat (limited to 'ffmpeg/libavcodec/xsubenc.c')
| -rw-r--r-- | ffmpeg/libavcodec/xsubenc.c | 221 |
1 files changed, 0 insertions, 221 deletions
diff --git a/ffmpeg/libavcodec/xsubenc.c b/ffmpeg/libavcodec/xsubenc.c deleted file mode 100644 index 53f4d6c..0000000 --- a/ffmpeg/libavcodec/xsubenc.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * DivX (XSUB) subtitle encoder - * Copyright (c) 2005 DivX, Inc. - * Copyright (c) 2009 Bjorn Axelsson - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "avcodec.h" -#include "bytestream.h" -#include "put_bits.h" - -/** - * Number of pixels to pad left and right. - * - * The official encoder pads the subtitles with two pixels on either side, - * but until we find out why, we won't do it (we will pad to have width - * divisible by 2 though). - */ -#define PADDING 0 -#define PADDING_COLOR 0 - -/** - * Encode a single color run. At most 16 bits will be used. - * @param len length of the run, values > 255 mean "until end of line", may not be < 0. - * @param color color to encode, only the lowest two bits are used and all others must be 0. - */ -static void put_xsub_rle(PutBitContext *pb, int len, int color) -{ - if (len <= 255) - put_bits(pb, 2 + ((ff_log2_tab[len] >> 1) << 2), len); - else - put_bits(pb, 14, 0); - put_bits(pb, 2, color); -} - -/** - * Encode a 4-color bitmap with XSUB rle. - * - * The encoded bitmap may be wider than the source bitmap due to padding. - */ -static int xsub_encode_rle(PutBitContext *pb, const uint8_t *bitmap, - int linesize, int w, int h) -{ - int x0, x1, y, len, color = PADDING_COLOR; - - for (y = 0; y < h; y++) { - x0 = 0; - while (x0 < w) { - // Make sure we have enough room for at least one run and padding - if (pb->size_in_bits - put_bits_count(pb) < 7*8) - return -1; - - x1 = x0; - color = bitmap[x1++] & 3; - while (x1 < w && (bitmap[x1] & 3) == color) - x1++; - len = x1 - x0; - if (PADDING && x0 == 0) { - if (color == PADDING_COLOR) { - len += PADDING; - x0 -= PADDING; - } else - put_xsub_rle(pb, PADDING, PADDING_COLOR); - } - - // Run can't be longer than 255, unless it is the rest of a row - if (x1 == w && color == PADDING_COLOR) { - len += PADDING + (w&1); - } else - len = FFMIN(len, 255); - put_xsub_rle(pb, len, color); - - x0 += len; - } - if (color != PADDING_COLOR && (PADDING + (w&1))) - put_xsub_rle(pb, PADDING + (w&1), PADDING_COLOR); - - avpriv_align_put_bits(pb); - - bitmap += linesize; - } - - return 0; -} - -static int make_tc(uint64_t ms, int *tc) -{ - static const int tc_divs[3] = { 1000, 60, 60 }; - int i; - for (i=0; i<3; i++) { - tc[i] = ms % tc_divs[i]; - ms /= tc_divs[i]; - } - tc[3] = ms; - return ms > 99; -} - -static int xsub_encode(AVCodecContext *avctx, unsigned char *buf, - int bufsize, const AVSubtitle *h) -{ - uint64_t startTime = h->pts / 1000; // FIXME: need better solution... - uint64_t endTime = startTime + h->end_display_time - h->start_display_time; - int start_tc[4], end_tc[4]; - uint8_t *hdr = buf + 27; // Point behind the timestamp - uint8_t *rlelenptr; - uint16_t width, height; - int i; - PutBitContext pb; - - if (bufsize < 27 + 7*2 + 4*3) { - av_log(avctx, AV_LOG_ERROR, "Buffer too small for XSUB header.\n"); - return -1; - } - - // TODO: support multiple rects - if (h->num_rects != 1) - av_log(avctx, AV_LOG_WARNING, "Only single rects supported (%d in subtitle.)\n", h->num_rects); - - // TODO: render text-based subtitles into bitmaps - if (!h->rects[0]->pict.data[0] || !h->rects[0]->pict.data[1]) { - av_log(avctx, AV_LOG_WARNING, "No subtitle bitmap available.\n"); - return -1; - } - - // TODO: color reduction, similar to dvdsub encoder - if (h->rects[0]->nb_colors > 4) - av_log(avctx, AV_LOG_WARNING, "No more than 4 subtitle colors supported (%d found.)\n", h->rects[0]->nb_colors); - - // TODO: Palette swapping if color zero is not transparent - if (((uint32_t *)h->rects[0]->pict.data[1])[0] & 0xff) - av_log(avctx, AV_LOG_WARNING, "Color index 0 is not transparent. Transparency will be messed up.\n"); - - if (make_tc(startTime, start_tc) || make_tc(endTime, end_tc)) { - av_log(avctx, AV_LOG_WARNING, "Time code >= 100 hours.\n"); - return -1; - } - - snprintf(buf, 28, - "[%02d:%02d:%02d.%03d-%02d:%02d:%02d.%03d]", - start_tc[3], start_tc[2], start_tc[1], start_tc[0], - end_tc[3], end_tc[2], end_tc[1], end_tc[0]); - - // Width and height must probably be multiples of 2. - // 2 pixels required on either side of subtitle. - // Possibly due to limitations of hardware renderers. - // TODO: check if the bitmap is already padded - width = FFALIGN(h->rects[0]->w, 2) + PADDING * 2; - height = FFALIGN(h->rects[0]->h, 2); - - bytestream_put_le16(&hdr, width); - bytestream_put_le16(&hdr, height); - bytestream_put_le16(&hdr, h->rects[0]->x); - bytestream_put_le16(&hdr, h->rects[0]->y); - bytestream_put_le16(&hdr, h->rects[0]->x + width -1); - bytestream_put_le16(&hdr, h->rects[0]->y + height -1); - - rlelenptr = hdr; // Will store length of first field here later. - hdr+=2; - - // Palette - for (i=0; i<4; i++) - bytestream_put_be24(&hdr, ((uint32_t *)h->rects[0]->pict.data[1])[i]); - - // Bitmap - // RLE buffer. Reserve 2 bytes for possible padding after the last row. - init_put_bits(&pb, hdr, bufsize - (hdr - buf) - 2); - if (xsub_encode_rle(&pb, h->rects[0]->pict.data[0], - h->rects[0]->pict.linesize[0]*2, - h->rects[0]->w, (h->rects[0]->h + 1) >> 1)) - return -1; - bytestream_put_le16(&rlelenptr, put_bits_count(&pb) >> 3); // Length of first field - - if (xsub_encode_rle(&pb, h->rects[0]->pict.data[0] + h->rects[0]->pict.linesize[0], - h->rects[0]->pict.linesize[0]*2, - h->rects[0]->w, h->rects[0]->h >> 1)) - return -1; - - // Enforce total height to be a multiple of 2 - if (h->rects[0]->h & 1) { - put_xsub_rle(&pb, h->rects[0]->w, PADDING_COLOR); - avpriv_align_put_bits(&pb); - } - - flush_put_bits(&pb); - - return hdr - buf + put_bits_count(&pb)/8; -} - -static av_cold int xsub_encoder_init(AVCodecContext *avctx) -{ - if (!avctx->codec_tag) - avctx->codec_tag = MKTAG('D','X','S','B'); - - avctx->bits_per_coded_sample = 4; - - return 0; -} - -AVCodec ff_xsub_encoder = { - .name = "xsub", - .long_name = NULL_IF_CONFIG_SMALL("DivX subtitles (XSUB)"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_XSUB, - .init = xsub_encoder_init, - .encode_sub = xsub_encode, -}; |
