[FFmpeg-devel] [PATCH 2/4] add ASS parser

Aurelien Jacobs aurel
Tue Jul 6 22:54:54 CEST 2010


---
 libavcodec/Makefile     |    1 
 libavcodec/allcodecs.c  |    1 
 libavcodec/ass_parser.c |  108 ++++++++++++++++++-----------------------------
 3 files changed, 44 insertions(+), 66 deletions(-)
 copy libavformat/assdec.c => libavcodec/ass_parser.c (60%)
-------------- next part --------------
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index dc28ccb..ffc2560 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -551,6 +551,7 @@ OBJS-$(CONFIG_AAC_PARSER)              += aac_parser.o aac_ac3_parser.o \
                                           mpeg4audio.o
 OBJS-$(CONFIG_AC3_PARSER)              += ac3_parser.o ac3tab.o \
                                           aac_ac3_parser.o
+OBJS-$(CONFIG_ASS_PARSER)              += ass_parser.o
 OBJS-$(CONFIG_CAVSVIDEO_PARSER)        += cavs_parser.o
 OBJS-$(CONFIG_DCA_PARSER)              += dca_parser.o
 OBJS-$(CONFIG_DIRAC_PARSER)            += dirac_parser.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 48a7bb3..2acc2c2 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -358,6 +358,7 @@ void avcodec_register_all(void)
     /* parsers */
     REGISTER_PARSER  (AAC, aac);
     REGISTER_PARSER  (AC3, ac3);
+    REGISTER_PARSER  (ASS, ass);
     REGISTER_PARSER  (CAVSVIDEO, cavsvideo);
     REGISTER_PARSER  (DCA, dca);
     REGISTER_PARSER  (DIRAC, dirac);
diff --git a/libavformat/assdec.c b/libavcodec/ass_parser.c
similarity index 60%
copy from libavformat/assdec.c
copy to libavcodec/ass_parser.c
index 5f8e0b9..c1ce309 100644
--- a/libavformat/assdec.c
+++ b/libavcodec/ass_parser.c
@@ -1,6 +1,7 @@
 /*
- * SSA/ASS demuxer
+ * SSA/ASS parser
  * Copyright (c) 2008 Michael Niedermayer
+ * Copyright (C) 2010  Aurelien Jacobs <aurel at gnuage.org>
  *
  * This file is part of FFmpeg.
  *
@@ -19,7 +20,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "avformat.h"
+#include "parser.h"
 
 #define MAX_LINESIZE 2000
 
@@ -30,39 +31,25 @@ typedef struct ASSContext{
     unsigned int event_index;
 }ASSContext;
 
-static void get_line(ByteIOContext *s, char *buf, int maxlen)
+static int get_line(const char *buf, int buf_size, char *line, int maxlen)
 {
     int i = 0;
-    char c;
 
     do{
-        c = get_byte(s);
         if (i < maxlen-1)
-            buf[i++] = c;
-    }while(c != '\n' && c);
+            line[i] = *buf;
+    } while (++i<buf_size && *buf != '\n' && *buf++);
 
-    buf[i] = 0;
+    line[i] = 0;
+    return i;
 }
 
-static int probe(AVProbeData *p)
-{
-    const char *header= "[Script Info]";
-
-    if(   !memcmp(p->buf  , header, strlen(header))
-       || !memcmp(p->buf+3, header, strlen(header)))
-        return AVPROBE_SCORE_MAX;
-
-    return 0;
-}
-
-static int read_close(AVFormatContext *s)
+static void ass_close(AVCodecParserContext *s)
 {
     ASSContext *ass = s->priv_data;
 
     av_freep(&ass->event_buffer);
     av_freep(&ass->event);
-
-    return 0;
 }
 
 static int64_t get_pts(const uint8_t *p)
@@ -77,7 +64,7 @@ static int64_t get_pts(const uint8_t *p)
     min+= 60*hour;
     sec+= 60*min;
 
-    return sec*100+hsec;
+    return sec*1000+hsec*10;
 }
 
 static int event_cmp(uint8_t **a, uint8_t **b)
@@ -85,30 +72,24 @@ static int event_cmp(uint8_t **a, uint8_t **b)
     return get_pts(*a) - get_pts(*b);
 }
 
-static int read_header(AVFormatContext *s, AVFormatParameters *ap)
+static int ass_read_header(AVCodecParserContext *s, AVCodecContext *avctx,
+                           const uint8_t *buf, int size)
 {
     int i, header_remaining;
     ASSContext *ass = s->priv_data;
-    ByteIOContext *pb = s->pb;
-    AVStream *st;
     int allocated[2]={0};
     uint8_t *p, **dst[2]={0};
     int pos[2]={0};
 
-    st = av_new_stream(s, 0);
-    if (!st)
-        return -1;
-    av_set_pts_info(st, 64, 1, 100);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id= CODEC_ID_SSA;
-
     header_remaining= INT_MAX;
-    dst[0] = &st->codec->extradata;
+    dst[0] = &avctx->extradata;
     dst[1] = &ass->event_buffer;
-    while(!url_feof(pb)){
+    while (size > 0) {
         uint8_t line[MAX_LINESIZE];
 
-        get_line(pb, line, sizeof(line));
+        i = get_line(buf, size, line, sizeof(line));
+        buf += i;
+        size -= i;
 
         if(!memcmp(line, "[Events]", 8))
             header_remaining= 2;
@@ -125,11 +106,11 @@ static int read_header(AVFormatContext *s, AVFormatParameters *ap)
             goto fail;
         *(dst[i])= p;
         memcpy(p + pos[i], line, strlen(line)+1);
-        pos[i] += strlen(line);
+        pos[i] += strlen(line)+i;
         if(i) ass->event_count++;
         else  header_remaining--;
     }
-    st->codec->extradata_size= pos[0];
+    avctx->extradata_size= pos[0];
 
     if(ass->event_count >= UINT_MAX / sizeof(*ass->event))
         goto fail;
@@ -138,9 +119,7 @@ static int read_header(AVFormatContext *s, AVFormatParameters *ap)
     p= ass->event_buffer;
     for(i=0; i<ass->event_count; i++){
         ass->event[i]= p;
-        while(*p && *p != '\n')
-            p++;
-        p++;
+        while(*p++);
     }
 
     qsort(ass->event, ass->event_count, sizeof(*ass->event), (void*)event_cmp);
@@ -148,40 +127,37 @@ static int read_header(AVFormatContext *s, AVFormatParameters *ap)
     return 0;
 
 fail:
-    read_close(s);
+    ass_close(s);
 
     return -1;
 }
 
-static int read_packet(AVFormatContext *s, AVPacket *pkt)
+static int ass_parse(AVCodecParserContext *s, AVCodecContext *avctx,
+                     const uint8_t **poutbuf, int *poutbuf_size,
+                     const uint8_t *buf, int buf_size)
 {
     ASSContext *ass = s->priv_data;
-    uint8_t *p, *end;
-
-    if(ass->event_index >= ass->event_count)
-        return AVERROR(EIO);
 
-    p= ass->event[ ass->event_index ];
+    if (!ass->event_buffer)
+        ass_read_header(s, avctx, buf, buf_size);
 
-    end= strchr(p, '\n');
-    av_new_packet(pkt, end ? end-p+1 : strlen(p));
-    pkt->flags |= AV_PKT_FLAG_KEY;
-    pkt->pos= p - ass->event_buffer + s->streams[0]->codec->extradata_size;
-    pkt->pts= pkt->dts= get_pts(p);
-    memcpy(pkt->data, p, pkt->size);
-
-    ass->event_index++;
+    if (ass->event_index >= ass->event_count) {
+        *poutbuf = NULL;
+        *poutbuf_size = 0;
+        return buf_size;
+    }
 
-    return 0;
+    *poutbuf = ass->event[ass->event_index++];
+    *poutbuf_size = strlen(*poutbuf);
+    s->pts = s->dts = get_pts(*poutbuf);
+    if (ass->event_index >= ass->event_count)
+        return buf_size;
+    return *poutbuf_size;
 }
 
-AVInputFormat ass_demuxer = {
-    "ass",
-    NULL_IF_CONFIG_SMALL("SSA/ASS format"),
-    sizeof(ASSContext),
-    probe,
-    read_header,
-    read_packet,
-    read_close,
-//    read_seek,
+AVCodecParser ass_parser = {
+    .codec_ids      = { CODEC_ID_SSA },
+    .priv_data_size = sizeof(ASSContext),
+    .parser_parse   = ass_parse,
+    .parser_close   = ass_close
 };



More information about the ffmpeg-devel mailing list