00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 #include <stdarg.h>
00023 #include "avcodec.h"
00024 #include "libavutil/avstring.h"
00025 #include "libavutil/intreadwrite.h"
00026 #include "ass_split.h"
00027 #include "ass.h"
00028 
00029 typedef struct {
00030     ASSSplitContext *ass_ctx;
00031     char buffer[2048];
00032     char *ptr;
00033     char *end;
00034 } MovTextContext;
00035 
00036 
00037 static av_cold int mov_text_encode_init(AVCodecContext *avctx)
00038 {
00039     
00040 
00041 
00042 
00043     static uint8_t text_sample_entry[] = {
00044         0x00, 0x00, 0x00, 0x00, 
00045         0x01,                   
00046         0xFF,                   
00047         0x00, 0x00, 0x00, 0x00, 
00048         
00049         0x00, 0x00,             
00050         0x00, 0x00,             
00051         0x00, 0x00,             
00052         0x00, 0x00,             
00053         
00054         
00055         0x00, 0x00,             
00056         0x00, 0x00,             
00057         0x00, 0x01,             
00058         0x00,                   
00059         0x12,                   
00060         0xFF, 0xFF, 0xFF, 0xFF, 
00061         
00062         
00063         0x00, 0x00, 0x00, 0x12, 
00064         'f', 't', 'a', 'b',     
00065         0x00, 0x01,             
00066         
00067         0x00, 0x01,             
00068         0x05,                   
00069         'S', 'e', 'r', 'i', 'f',
00070         
00071         
00072     };
00073 
00074     MovTextContext *s = avctx->priv_data;
00075 
00076     avctx->extradata_size = sizeof text_sample_entry;
00077     avctx->extradata = av_mallocz(avctx->extradata_size);
00078     if (!avctx->extradata)
00079         return AVERROR(ENOMEM);
00080 
00081     memcpy(avctx->extradata, text_sample_entry, avctx->extradata_size);
00082 
00083     s->ass_ctx = ff_ass_split(avctx->subtitle_header);
00084     return s->ass_ctx ? 0 : AVERROR_INVALIDDATA;
00085 }
00086 
00087 static void mov_text_text_cb(void *priv, const char *text, int len)
00088 {
00089     MovTextContext *s = priv;
00090     av_strlcpy(s->ptr, text, FFMIN(s->end - s->ptr, len + 1));
00091     s->ptr += len;
00092 }
00093 
00094 static void mov_text_new_line_cb(void *priv, int forced)
00095 {
00096     MovTextContext *s = priv;
00097     av_strlcpy(s->ptr, "\n", FFMIN(s->end - s->ptr, 2));
00098     s->ptr++;
00099 }
00100 
00101 static const ASSCodesCallbacks mov_text_callbacks = {
00102     .text     = mov_text_text_cb,
00103     .new_line = mov_text_new_line_cb,
00104 };
00105 
00106 static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf,
00107                                  int bufsize, const AVSubtitle *sub)
00108 {
00109     MovTextContext *s = avctx->priv_data;
00110     ASSDialog *dialog;
00111     int i, len, num;
00112 
00113     s->ptr = s->buffer;
00114     s->end = s->ptr + sizeof(s->buffer);
00115 
00116     for (i = 0; i < sub->num_rects; i++) {
00117 
00118         if (sub->rects[i]->type != SUBTITLE_ASS) {
00119             av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n");
00120             return AVERROR(ENOSYS);
00121         }
00122 
00123         dialog = ff_ass_split_dialog(s->ass_ctx, sub->rects[i]->ass, 0, &num);
00124         for (; dialog && num--; dialog++) {
00125             ff_ass_split_override_codes(&mov_text_callbacks, s, dialog->text);
00126         }
00127     }
00128 
00129     if (s->ptr == s->buffer)
00130         return 0;
00131 
00132     AV_WB16(buf, strlen(s->buffer));
00133     buf += 2;
00134 
00135     len = av_strlcpy(buf, s->buffer, bufsize - 2);
00136 
00137     if (len > bufsize-3) {
00138         av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n");
00139         return AVERROR(EINVAL);
00140     }
00141 
00142     return len + 2;
00143 }
00144 
00145 static int mov_text_encode_close(AVCodecContext *avctx)
00146 {
00147     MovTextContext *s = avctx->priv_data;
00148     ff_ass_split_free(s->ass_ctx);
00149     return 0;
00150 }
00151 
00152 AVCodec ff_movtext_encoder = {
00153     .name           = "mov_text",
00154     .long_name      = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"),
00155     .type           = AVMEDIA_TYPE_SUBTITLE,
00156     .id             = AV_CODEC_ID_MOV_TEXT,
00157     .priv_data_size = sizeof(MovTextContext),
00158     .init           = mov_text_encode_init,
00159     .encode_sub     = mov_text_encode_frame,
00160     .close          = mov_text_encode_close,
00161 };