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

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

FLV文件结构解析

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

FLV Header

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

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

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

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

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

FLV Body

FLV body就是由很多tag组成的,一个tag包括下列信息:

previoustagsize 4bytes 前一个tag的长度,第一个tag就是0

tag类型1byte 共分为三类:

* 8 -- 音频tag

* 9 -- 视频tag

* 18 -- 脚本tag

数据区长度3bytes 时间戳3bytes 单位毫秒同时还有1bytes的扩展时间戳,放在最高位,大部分时间时间戳为媒体的dts信息,如果是脚本tag就是0

streamsID 3bytes 总是0(不知道干啥用)

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

脚本tag :

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

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

从中可以看出其type为18。time stamp为0.data size为33638.

metadata tag data信息解析后为:

其中有一些媒体信息:

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

音频的tag信息:

音频的tag信息如下图:

其中time stamp 为0是因为其为第一个音频tag.

视频tag

这是文件中的第6个tag所以其time stamp不为0。因为其为视频tag所以其type为9。

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);//读出flv的video和audio 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)){
    pos = url_ftell(s->pb);
    type = get_byte(s->pb); //获取tag的类型,前面已经提到flv的tag大概有以下三种 :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; //计算tag的timestamp也就是dts信息

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

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

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

}

版权所有:博水。转载请注明出处:http://www.cnblogs.com/qingquan/

(转)媒体格式分析之flv -- 基于FFMPEG的更多相关文章

  1. 媒体格式分析之flv -- 基于FFMPEG

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

  2. 最简单的基于FFMPEG的转码程序

    本文介绍一个简单的基于FFmpeg的转码器.它可以将一种视频格式(包括封转格式和编码格式)转换为另一种视频格式.转码器在视音频编解码处理的程序中,属于一个比较复杂的东西.因为它结合了视频的解码和编码. ...

  3. 最简单的基于FFMPEG的封装格式转换器(无编解码)

    本文介绍一个基于FFMPEG的封装格式转换器.所谓的封装格式转换,就是在AVI,FLV,MKV,MP4这些格式之间转换(相应.avi,.flv,.mkv,.mp4文件).须要注意的是,本程序并不进行视 ...

  4. 最简单的基于FFmpeg的移动端例子:IOS 视频转码器

    ===================================================== 最简单的基于FFmpeg的移动端例子系列文章列表: 最简单的基于FFmpeg的移动端例子:A ...

  5. 最简单的基于FFmpeg的移动端例子:IOS 推流器

    转至:http://blog.csdn.net/leixiaohua1020/article/details/47072519   ================================== ...

  6. 最简单的基于FFmpeg的推流器(以推送RTMP为例)

    ===================================================== 最简单的基于FFmpeg的推流器系列文章列表: <最简单的基于FFmpeg的推流器(以 ...

  7. iOS平台基于ffmpeg的视频直播技术揭秘

    现在非常流行直播,相信很多人都跟我一样十分好奇这个技术是如何实现的,正好最近在做一个ffmpeg的项目,发现这个工具很容易就可以做直播,下面来给大家分享下技术要点: 首先你得编译出ffmpeg运行所需 ...

  8. 基于ffmpeg网络播放器的教程与总结

    基于ffmpeg网络播放器的教程与总结   一.         概述 为了解决在线无广告播放youku网上的视频.(youku把每个视频切换成若干个小视频). 视频资源解析可以从www.flvcd. ...

  9. 基于ffmpeg的C++播放器1

    基于ffmpeg的C++播放器 (1) 2011年12月份的时候发了这篇博客 http://blog.csdn.net/qq316293804/article/details/7107049 ,博文最 ...

随机推荐

  1. struct中长度为0的数组用途与原理

    前言 在标准C和C++中,长度为0的数组是被禁止使用的.不过在GNUC中,存在一个非常奇怪的用法,那就是长度为0的数组,比如Array[0]; 很多人可能觉得不可思议,长度为0的数组是没有什么意义的, ...

  2. python抓取链家房源信息(三)

    之前写过一个链家网北京二手房的数据抓取,然后本来今天想着要把所有的东西弄完,但是临时有事出去了一趟,耽搁了一下,然后现在是想着把北京的二手房的信息都进行抓取,并且存储在mongodb中, 首先是通过' ...

  3. html学习-js

    1.js介绍 JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏览器可以解释并做出相应的处理.js能使 ...

  4. IEEEXtreme 10.0 - Mysterious Maze

    这是 meelo 原创的 IEEEXtreme极限编程大赛题解 Xtreme 10.0 - Mysterious Maze 题目来源 第10届IEEE极限编程大赛 https://www.hacker ...

  5. list列表常用方法

    列表是Python中常用的功能,我们知道,列表可以用来存储很多信息,掌握列表的功能有助于我们处理更多的问题,下面来看看列表都具有那些属性:     1.append(self,p_object) de ...

  6. 【51nod】1340 地铁环线

    今天头非常疼,躲在家里没去机房 反正都要颓废了,然后花了一上午研究了一下这道神题怎么做-- 题解 首先我们发现,如果我们设\(dis[i]\)为从\(0\)节点走到\(i\)节点的距离 那么题目中给出 ...

  7. 基于ZooKeeper实现——分布式锁与实现

    引言 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提 ...

  8. shell-sed命令详解(转)

    (转自http://blog.csdn.net/wl_fln/article/details/7281986) Sed简介 sed是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时 ...

  9. 百度地图API详解之自定义地图类型

    http://blog.csdn.net/sup_heaven/article/details/8461586 今天的文章主要介绍如何利用地图API实现自定义地图. 百度地图API目前默认支持两种地图 ...

  10. 2017-2018-1 20179202《Linux内核原理与分析》第五周作业

    一.系统调用实验: 1.知识准备: (1)系统调用的三层皮:xyz()(API).system_call(所有系统调用的入口) . sys_xyz()(中断服务程序) (2)API是程序员在用户空间下 ...