flv格式简介

本来是应该先写一个媒体文件格式的简单讲解的,还没来得及写,以后再写。今天就先根据ffmpegflv.cflv_demux这个结构体来讲解一下当前比较流行的媒体格式flv.

FLVFLASH VIDEO的简称,FLV流媒体格式是随着Flash MX的推出发展而来的视频格式。由于它形成的文件极小、加载速度极快,使得网络观看视频文件成为可能.当前主流的媒体网站像国内的优酷、国外youtube其标清格式的文件均采用flv的格式。

FLV文件结构解析

FLV是一个二进制文件,其文件格式如下图,由文件头(FLV header)和很多tag组成。tag又可以分成三类:audio,video,script,分别代表音频流,视频流,脚本流(关键字或者文件信息之类)。

FLV Header

FLVHeader信息一般比较简单,包括文件类型之类的全局信息。如下图中解析:

文件类型3bytes总是FLV0x46 0x4C 0x56),否则就不是在ffmpeg中在没有指定文件格式的情况下,也是通过这个字段来探测文件是否属于FLV格式的。

版本1byte一般是0x01,表示FLV version 1

流信息1byte倒数第一bit1表示有视频,倒数第三bit1表示有音频,其他都应该是0(有些软件如flvtool2可能造成倒数第四bit1,不过也没发现有什么不对)

header长度4bytes整个文件头的长度,一般是93+1+1+4),当然头部字段也有可能包含其它信息这个时间其长度就不是9了。

FLV Body

FLV body就是由很多tag组成的,一个tag第一部分是tag header,tag header长度为11bytes,但是每个tag header前面有4bytes记录着上一个tag的长度,此待会儿再说。tag header的第1个byte为记录着tag的类型,音频(0x8),视频(0x9),脚本(0x12);第2到4bytes是数据区的长度,也就是tag data的长度;再后面3个bytes是时间戳,单位是毫秒,类型为0x12则时间戳为0,时间戳控制着文件播放的速度,可以根据音视频的帧率类设置;时间戳后面一个byte是扩展时间戳,时间戳不够长的时候用;最后3bytes是streamID,但是总为0,再后面就是数据区了(tag data),也即是h264的裸流,tag header 长度为1+3+3+1+3=11。

数据区:根据不同的tag类型就有不同的数据区。

脚本tag

如果tag data是脚本数据,Script Tag Data,该类型Tag又通常被称为Metadata(元数据) Tag,会放一些关于FLV视频和音频的参数信息,如duration、width、height等。通常该类型Tag会跟在File Header后面作为第一个Tag出现,而且只有一个。一般来说,该Tag Data结构包含两个AMF包。AMF(Action Message Format)是Adobe设计的一种通用数据封装格式,在Adobe的很多产品中应用,简单来说,AMF将不同类型的数据用统一的格式来描述。第一个 AMF包封装字符串类型数据,用来装入一个“onMetaData”标志,这个标志与Adobe的一些API调用有,在此不细述。第二个AMF包封装一个数组类型,这个数组中包含了音视频信息项的名称和值。具体说明如下,大家可以参照图片上的数据进行理解。

第一个AMF包:

 第1个字节表示AMF包类型,一般总是0x02,表示字符串,其他值表示意义请查阅文档。

  第2-3个字节为UI16类型值,表示字符串的长度,一般总是0x000A(“onMetaData”长度)。

  后面字节为字符串数据,一般总为“onMetaData”。

第二个AMF包:

 第1个字节表示AMF包类型,一般总是0x08,表示数组。

  第2-5个字节为UI32类型值,表示数组元素的个数。

  后面即为各数组元素的封装,数组元素为元素名称和值组成的对。表示方法如下:

   第1-2个字节表示元素名称的长度,假设为L。

     后面跟着为长度为L的字符串。

     第L+3个字节表示元素值的类型。

   后面跟着为对应值,占用字节数取决于值的类型。

脚本tag一般是用文本方式表示,如下图flvmetadata信息:

从中可以看出是通过文本的方式来标记的,其解析后其header信息为:

从中可以看出其type18time stamp0.data size33638.

metadata tag data信息解析后为:

其中有一些媒体信息:

例如视频的:高和宽它的codec id。帧率。音频的信息例如:音频的sample ratecodec id,sample size及是否立体声。还有整个文件的大小等等。

音频的tag信息:

tag data如果是音频数据,第一个byte记录audio信息:

前4bits表示音频格式(全部格式请看官方文档):

·0 -- 未压缩

·1 -- ADPCM

·2 -- MP3

·4 -- Nellymoser 16-kHz mono

·5 -- Nellymoser 8-kHz mono

·10 -- AAC

下面两个bits表示samplerate:

·0 -- 5.5KHz

·1 -- 11kHz

·2 -- 22kHz

·3 -- 44kHz

下面1bit表示采样长度:

·0 -- snd8Bit

·1 -- snd16Bit

下面1bit表示类型:

·0 -- sndMomo

·1 -- sndStereo

之后是数据。

视频tag

如果是视频数据,第一个byte记录video信息:

前4bits表示类型:

·1-- keyframe

·2 -- inner frame

·3 -- disposable inner frame (h.263 only)

·4 -- generated keyframe

后4bits表示解码器ID:

·2 -- seronson h.263

·3 -- screen video

·4 -- On2 VP6

·5 -- On2 VP6 with alpha channel

·6 -- Screen video version 2

·7 -- AVC (h.264)

之后是数据。

ffmpeg中的flv文件格式解析的实现:

其中flv_read_header主要是从文件中读取一些头信息,同时作一些初始化化的工作

static int flv_read_header(AVFormatContext *s,AVFormatParameters *ap)
{

         ……

    url_fskip(s->pb, 4); //flv的头去掉。
    flags = get_byte(s->pb);//
读出flvvideoaudio flag信息。

         …… 
        if(flags & FLV_HEADER_FLAG_HASVIDEO){
        if(!create_stream(s, 0))  //
创建视频流

            return AVERROR(ENOMEM);
    }
    if(flags & FLV_HEADER_FLAG_HASAUDIO){
        if(!create_stream(s, 1)) //
创建音频流

            return AVERROR(ENOMEM);
    }

    offset = get_be32(s->pb); //获取文件头长度

        ……
}

其它tag的读取:

static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
{

 ……
for(;;url_fskip(s->pb, 4)){ /* pkt size is repeated at end. skip it */
    pos = url_ftell(s->pb);
    type = get_byte(s->pb); //
获取tag的类型,前面已经提到flvtag大概有以下三种
FLV_TAG_TYPE_AUDIO = 0x08,FLV_TAG_TYPE_VIDEO = 0x09,FLV_TAG_TYPE_META  = 0x12,

    size = get_be24(s->pb);//
获取tag的长度

    dts = get_be24(s->pb);
    dts |= get_byte(s->pb) << 24; //
计算tagtimestamp也就是dts信息

    ……
    if (type == FLV_TAG_TYPE_AUDIO) { //
判断是否为audio tag

       ……
         } else if (type == FLV_TAG_TYPE_VIDEO) {//
判断是否为video tag

       ……
               if ((flags & 0xf0) == 0x50) /* video info / command frame */
            goto skip;
    } else {
        if (type == FLV_TAG_TYPE_META && size > 13+1+4)//
判断是否为meta tag,如果是meta信息则会将信息存放在一个map表中。

         ……

}

 

常用的FLV封装命令

MP4封装为FLV

ffmpeg -vcodec copy -acodec copy -i *.mp4 -f flv test.flv

aac音频和h264视频混流封装FLV
ffmpeg -i <video file> -vcodec copy -i <audio file> -acodec copy test.flv

你可能感兴趣的:(header,video,byte,flv,audio)