[libav-devel] [PATCH] flv: support stream text data as onTextData

Luca Barbato lu_zero at gentoo.org
Sun May 13 00:21:16 CEST 2012


On 12/05/12 09:59, Anton Khirnov wrote:
> 
> On Wed,  9 May 2012 14:35:58 -0700, Luca Barbato <lu_zero at gentoo.org> wrote:
>> Adobe specifies onTextData as the standard message to use to deliver
>> text information.
>> ---
> 
> First of all, I'd appreciate it if you could split the muxer and demuxer
> parts.

I can do but would be sort of pointless.

>>  libavformat/flvdec.c |  102 ++++++++++++++++++++++++++++++++++++++++++-------
>>  libavformat/flvenc.c |   77 ++++++++++++++++++++++++++++++++-----
>>  2 files changed, 153 insertions(+), 26 deletions(-)
>>
>> diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
>> index 7c4b792..d2e9fdd 100644
>> --- a/libavformat/flvdec.c
>> +++ b/libavformat/flvdec.c
>> @@ -66,6 +66,17 @@ static int flv_probe(AVProbeData *p)
>>      return 0;
>>  }
>>  
>> +static AVStream *create_stream(AVFormatContext *s, int tag, int codec_type)
>> +{
>> +    AVStream *st = avformat_new_stream(s, NULL);
>> +    if (!st)
>> +        return NULL;
>> +    st->id = tag;
> 
> I don't really like this abuse of id to store demuxer private
> information. Can't you just check for AVMEDIA_TYPE_DATA?

tag is used in a strange way in flv, I might try to fix it later and see
if we can support multistream flv later (that is the XXX)

>> +    st->codec->codec_type = codec_type;
>> +    avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
>> +    return st;
>> +}
>> +
>>  static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, AVCodecContext *acodec, int flv_codecid) {
>>      switch(flv_codecid) {
>>          //no distinction between S16 and S8 PCM codec flags
>> @@ -302,6 +313,12 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst
>>                  vcodec->bit_rate = num_val * 1024.0;
>>              else if (!strcmp(key, "audiodatarate") && acodec && 0 <= (int)(num_val * 1024.0))
>>                  acodec->bit_rate = num_val * 1024.0;
>> +            else if (!strcmp(key, "datastream")) {
>> +                AVStream *st = create_stream(s, 2, AVMEDIA_TYPE_DATA);
>> +                if (!st)
>> +                    return AVERROR(ENOMEM);
>> +                st->codec->codec_id = CODEC_ID_TEXT;
>> +            }
>>          }
>>  
>>          if (!strcmp(key, "duration")        ||
>> @@ -344,7 +361,14 @@ static int flv_read_metabody(AVFormatContext *s, int64_t next_pos) {
>>  
>>      //first object needs to be "onMetaData" string
>>      type = avio_r8(ioc);
>> -    if(type != AMF_DATA_TYPE_STRING || amf_get_string(ioc, buffer, sizeof(buffer)) < 0 || strcmp(buffer, "onMetaData"))
>> +    if (type != AMF_DATA_TYPE_STRING ||
>> +        amf_get_string(ioc, buffer, sizeof(buffer)) < 0)
>> +        return -1;
>> +
>> +    if (!strcmp(buffer, "onTextData"))
>> +        return 1;
>> +
>> +    if (strcmp(buffer, "onMetaData"))
>>          return -1;
>>  
>>      //find the streams now so that amf_parse_object doesn't need to do the lookup every time it is called.
>> @@ -361,16 +385,6 @@ static int flv_read_metabody(AVFormatContext *s, int64_t next_pos) {
>>      return 0;
>>  }
>>  
>> -static AVStream *create_stream(AVFormatContext *s, int is_audio){
>> -    AVStream *st = avformat_new_stream(s, NULL);
>> -    if (!st)
>> -        return NULL;
>> -    st->id = is_audio;
>> -    st->codec->codec_type = is_audio ? AVMEDIA_TYPE_AUDIO : AVMEDIA_TYPE_VIDEO;
>> -    avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
>> -    return st;
>> -}
>> -
>>  static int flv_read_header(AVFormatContext *s)
>>  {
>>      int offset, flags;
>> @@ -389,11 +403,11 @@ static int flv_read_header(AVFormatContext *s)
>>          s->ctx_flags |= AVFMTCTX_NOHEADER;
>>  
>>      if(flags & FLV_HEADER_FLAG_HASVIDEO){
>> -        if(!create_stream(s, 0))
>> +        if(!create_stream(s, 0, AVMEDIA_TYPE_VIDEO))
>>              return AVERROR(ENOMEM);
>>      }
>>      if(flags & FLV_HEADER_FLAG_HASAUDIO){
>> -        if(!create_stream(s, 1))
>> +        if(!create_stream(s, 1, AVMEDIA_TYPE_AUDIO))
>>              return AVERROR(ENOMEM);
>>      }
>>  
>> @@ -453,6 +467,61 @@ static void clear_index_entries(AVFormatContext *s, int64_t pos)
>>      }
>>  }
>>  
>> +
>> +static int flv_data_packet(AVFormatContext *s, AVPacket *pkt,
>> +                           int64_t dts, int64_t next)
>> +{
>> +    AVIOContext *pb = s->pb;
>> +    AVStream *st = NULL;
>> +    AMFDataType type;
>> +    char buf[20];
>> +    int codec_id;
>> +    int length;
>> +    int ret = AVERROR_INVALIDDATA, i;
>> +
>> +    type = avio_r8(pb);
>> +    if (type == AMF_DATA_TYPE_MIXEDARRAY)
>> +        avio_seek(pb, 4, SEEK_CUR);
>> +    else if (type != AMF_DATA_TYPE_OBJECT)
>> +        goto out;
>> +    amf_get_string(pb, buf, sizeof(buf));
>> +    if (strcmp(buf,"type") || avio_r8(pb) != AMF_DATA_TYPE_STRING)
>> +        goto out;
>> +    amf_get_string(pb, buf, sizeof(buf));
>> +    //FIXME parse it as codec_id
>> +    amf_get_string(pb, buf, sizeof(buf));
>> +    if (strcmp(buf,"text") || avio_r8(pb) != AMF_DATA_TYPE_STRING)
>> +        goto out;
>> +    length = avio_rb16(pb);
>> +    ret = av_get_packet(s->pb, pkt, length);
>> +    if (ret < 0) {
>> +        ret = AVERROR(EIO);
>> +        goto out;
>> +    }
>> +
>> +    for(i=0;i<s->nb_streams;i++) {
>> +        st = s->streams[i];
>> +        if (st->id == 2) //XXX
> 
> Exactly. Please fix the XXX
> also some spaces in for() would help

Supporting multiple streams is ortogonal.

>> +    pkt->size = ret;
>> +    pkt->dts = dts;
>> +    pkt->pts = dts;
>> +    pkt->stream_index = st->index;
>> +    pkt->flags |= AV_PKT_FLAG_KEY;
> 
> Extra karma for vertical alignment.

Good point, I have a full cleanup patch slated for later.

lu

-- 

Luca Barbato
Gentoo/linux
http://dev.gentoo.org/~lu_zero



More information about the libav-devel mailing list