[Ffmpeg-devel] Patch to add header info to flv format

Benjamin Larsson banan
Thu Jul 13 11:06:07 CEST 2006


Hi, nice to finally get these features.

Philipp Klaus wrote:
>>> I implemented a patch against ffmpeg, that adds a minimal header (meta
>>> data) to the flv video format. This is needed if you want to have the
>>> progress slider display anything in a flash video player.
>>>
>>> I've searched the ffmpeg homepage for an email address to send the patch
>>> to but have not found one. What's the usual way to send patches to this
>>> project? Send the patch to this list? Or is there a central address for
>>> every module where I have to send my patch?
>>
>>
>> Send patches here using the unified diff format ( diff -u ).
> 
> 
> Here it is, hope it's possible to integrate with the current source code 
> but as I looked a the CVS there wasn't much change in the flvenc.c file 
> in the last months.

Check out a new version from svn and rediff.

> 
> Philipp
> 
> 
> ------------------------------------------------------------------------
> 
> diff -ruN ffmpeg-20060317/ffmpeg.c ffmpeg-20060317_pylon/ffmpeg.c
> --- ffmpeg-20060317/ffmpeg.c	2006-03-17 14:23:28.000000000 +0100
> +++ ffmpeg-20060317_pylon/ffmpeg.c	2006-07-12 13:58:27.000000000 +0200
> @@ -1485,6 +1485,7 @@
>      AVInputStream *ist, **ist_table = NULL;
>      AVInputFile *file_table;
>      AVFormatContext *stream_no_data;
> +	int64_t total_duration = 0;

Tabs are not allowed, use whitespaces. And I'm not sure it is correct to 
pass this from ffmpeg.c. I think this should be calculated inside the 
flvmuxer.

>      int key;
>  
>      file_table= (AVInputFile*) av_mallocz(nb_input_files * sizeof(AVInputFile));
> @@ -1514,6 +1515,7 @@
>      j = 0;
>      for(i=0;i<nb_input_files;i++) {
>          is = input_files[i];
> +		total_duration += is->duration;

Tabs.

>          for(k=0;k<is->nb_streams;k++) {
>              ist = ist_table[j++];
>              ist->st = is->streams[k];
> @@ -1533,6 +1535,7 @@
>      nb_ostreams = 0;
>      for(i=0;i<nb_output_files;i++) {
>          os = output_files[i];
> +		os->duration = total_duration;

Tabs.

>          nb_ostreams += os->nb_streams;
>      }
>      if (nb_stream_maps > 0 && nb_stream_maps != nb_ostreams) {
> diff -ruN ffmpeg-20060317/libavformat/flvenc.c ffmpeg-20060317_pylon/libavformat/flvenc.c
> --- ffmpeg-20060317/libavformat/flvenc.c	2006-01-13 11:22:22.000000000 +0100
> +++ ffmpeg-20060317_pylon/libavformat/flvenc.c	2006-07-12 18:03:11.000000000 +0200
> @@ -79,11 +79,44 @@
>      return flags;
>  }
>  
> +#define AMF_DOUBLE  0
> +#define AMF_BOOLEAN 1
> +#define AMF_STRING  2
> +#define AMF_OBJECT  3
> +#define AMF_MIXED_ARRAY 8
> +#define AMF_ARRAY  10
> +#define AMF_DATE   11
> +
> +void put_amf_string(ByteIOContext *pb, const char *str)
> +{
> +    size_t len = strlen(str);
> +    put_be16(pb, len);
> +    put_buffer(pb, str, len);
> +}
> +
> +void put_amf_double(ByteIOContext *pb, double d)
> +{
> +    unsigned char *llp = (uint64_t *)&d;
> +    unsigned char nllp[8];
> +    int i;
> +    for (i = 0; i < 8; i++) {
> +        nllp[i] = llp[7-i];
> +    }
> +    put_byte(pb, AMF_DOUBLE);
> +    put_buffer(pb, nllp, 8);
> +}
> +
> +
>  static int flv_write_header(AVFormatContext *s)
>  {
>      ByteIOContext *pb = &s->pb;
>      FLVContext *flv = s->priv_data;
>      int i;
> +    double d;
> +    int width = 0;
> +    int height = 0;
> +    double framerate = 0.0;
> +    int audiosamplerate = 0;
>  
>      flv->hasAudio = 0;
>      flv->hasVideo = 0;
> @@ -96,6 +129,17 @@
>  
>      for(i=0; i<s->nb_streams; i++){
>          AVCodecContext *enc = s->streams[i]->codec;
> +        if (enc->codec_type == CODEC_TYPE_VIDEO) {
> +            width = enc->width;
> +            height = enc->height;
> +            if (s->streams[i]->r_frame_rate.den && s->streams[i]->r_frame_rate.num) {
> +                framerate = av_q2d(s->streams[i]->r_frame_rate);
> +            } else {
> +                framerate = 1/av_q2d(s->streams[i]->codec->time_base);
> +            }
> +        } else {
> +            audiosamplerate = enc->sample_rate;
> +        }
>          av_set_pts_info(s->streams[i], 24, 1, 1000); /* 24 bit pts in ms */
>          if(enc->codec_tag == 5){
>              put_byte(pb,8); // message type
> @@ -108,10 +152,61 @@
>          if(enc->codec_type == CODEC_TYPE_AUDIO && get_audio_flags(enc)<0)
>              return -1;
>      }
> +    
> +    /* write meta_tag */
> +    #define DATA_SIZE 162
> +    put_byte(pb, 18);         // tag type META
> +    put_be24(pb, DATA_SIZE);        // size of data part (sum of all parts below)
> +    put_be24(pb, 0);          // time stamp
> +    put_be32(pb, 0);          // reserved
> +    
> +    /* now data of data_size size */
> +    
> +    /* first event name as a string */
> +    put_byte(pb, AMF_STRING); // 1 byte
> +    put_amf_string(pb, "onMetaData"); // 12 bytes
> +    
> +    /* mixed array (hash) with size and string/type/data tuples */
> +    put_byte(pb, AMF_MIXED_ARRAY);          // 1 byte 
> +    put_be32(pb, 7);          // number of entries in the hash (4 bytes)
> +    
> +    put_amf_string(pb, "duration"); // 10 bytes
> +    if (s->duration != AV_NOPTS_VALUE) {
> +        d = (double) s->duration;
> +        d /= AV_TIME_BASE;
> +    } else {
> +        d = 0.0;
> +    }
> +    put_amf_double(pb, d); // 9 bytes
> +    
> +    put_amf_string(pb, "width"); // 7 bytes
> +    put_amf_double(pb, (double) width); // 9 bytes
> +    
> +    put_amf_string(pb, "height"); // 8 bytes
> +    put_amf_double(pb, (double) height); // 9 bytes
Any special reason to not use enc->height and enc->width here ?
> +    
> +    put_amf_string(pb, "videodatarate"); // 15 bytes
> +    put_amf_double(pb, (double) s->bit_rate / 1024.0); // 9 bytes
> +    
> +    put_amf_string(pb, "filesize"); // 10 bytes
> +    put_amf_double(pb, (double) s->file_size); // 9 bytes
> +    
> +    put_amf_string(pb, "framerate"); // 11 bytes
> +    put_amf_double(pb, framerate); // 9 bytes
> +    
> +    put_amf_string(pb, "audiosamplerate"); // 17 bytes
> +    put_amf_double(pb, (double) audiosamplerate); // 9 bytes
> +    
> +    put_amf_string(pb, ""); // 2 bytes
> +    put_byte(pb, 9); // end marker 1 byte
> +    
> +    /* write total size of tag */
> +    put_be32(pb, DATA_SIZE + 11);
>  
>      return 0;
>  }
>  
> +

Cosmetics, non needed line.

>  static int flv_write_trailer(AVFormatContext *s)
>  {
>      int64_t file_size;
> 

MvH
Benjamin Larsson




More information about the ffmpeg-devel mailing list