当前位置: 首页 > news >正文

网站建设策划书编制百度域名查询官网

网站建设策划书编制,百度域名查询官网,站酷网怎么样,百度统计工具一、引言 在《音视频入门基础:FLV专题(9)——Script Tag简介》中对Script Tag进行了简介,本文讲述FFmpeg源码中是怎样解码FLV文件的Script Tag,拿到里面的信息。 二、flv_read_packet函数 从《音视频入门基础&#x…

一、引言

在《音视频入门基础:FLV专题(9)——Script Tag简介》中对Script Tag进行了简介,本文讲述FFmpeg源码中是怎样解码FLV文件的Script Tag,拿到里面的信息。

二、flv_read_packet函数

从《音视频入门基础:FLV专题(8)——FFmpeg源码中,解码Tag header的实现》可以知道,FFmpeg源码中使用flv_read_packet函数来读取每个Tag的信息,该函数的前半部分实现了解码Tag header,获取其TagType属性的功能。然后根据TagType属性的值,判断该Tag为音频Tag、视频Tag还是脚本Tag。根据Tag的类型分别执行不同的解码操作:

    if (type == FLV_TAG_TYPE_AUDIO) {//...} else if (type == FLV_TAG_TYPE_VIDEO) {//...}else if (type == FLV_TAG_TYPE_META) {//...}else{//...}//...

从《音视频入门基础:FLV专题(9)——Script Tag简介》可以知道:

Script Tag = Tag header + SCRIPTDATA

未加密的情况下,SCRIPTDATA = ScriptTagBody

而FFmpeg源码(截止源码版本7.0.1)会统一把FLV文件当做未加密来处理。

所以FFmpeg源码中:Script Tag = Tag header + ScriptTagBody

如果在flv_read_packet函数的前半部分判断出该Tag为Script Tag(脚本Tag),flv_read_packet函数中会执行如下逻辑解码Script Tag的ScriptTagBody:

      else if (type == FLV_TAG_TYPE_META) {stream_type=FLV_STREAM_TYPE_SUBTITLE;if (size > 13 + 1 + 4) { // Header-type metadata stuffint type;meta_pos = avio_tell(s->pb);type = flv_read_metabody(s, next);if (type == 0 && dts == 0 || type < 0) {if (type < 0 && flv->validate_count &&flv->validate_index[0].pos     > next &&flv->validate_index[0].pos - 4 < next) {av_log(s, AV_LOG_WARNING, "Adjusting next position due to index mismatch\n");next = flv->validate_index[0].pos - 4;}goto skip;} else if (type == TYPE_ONTEXTDATA) {avpriv_request_sample(s, "OnTextData packet");return flv_data_packet(s, pkt, dts, next);} else if (type == TYPE_ONCAPTION) {return flv_data_packet(s, pkt, dts, next);} else if (type == TYPE_UNKNOWN) {stream_type = FLV_STREAM_TYPE_DATA;}avio_seek(s->pb, meta_pos, SEEK_SET);}}else {av_log(s, AV_LOG_DEBUG,"Skipping flv packet: type %d, size %d, flags %d.\n",type, size, flags);
skip:if (avio_seek(s->pb, next, SEEK_SET) != next) {// This can happen if flv_read_metabody above read past// next, on a non-seekable input, and the preceding data has// been flushed out from the IO buffer.av_log(s, AV_LOG_ERROR, "Unable to seek to the next packet\n");return AVERROR_INVALIDDATA;}ret = FFERROR_REDO;goto leave;
//...
leave:
//...return ret;} 

下面我们分析上述代码块中解码ScriptTagBody的原理。

三、flv_read_packet函数中解码ScriptTagBody的原理

从 《音视频入门基础:FLV专题(8)——FFmpeg源码中,解码Tag header的实现》中可以知道,上述代码块中,局部变量size存贮该Tag的Tag data的长度,当该Tag为Script Tag时,它的Tag data就是ScriptTagBody,所以此时局部变量size存贮ScriptTagBody的长度:

​else if (type == FLV_TAG_TYPE_META) {stream_type=FLV_STREAM_TYPE_SUBTITLE;if (size > 13 + 1 + 4) { // Header-type metadata stuff//...} ​

 从《音视频入门基础:FLV专题(9)——Script Tag简介》可以知道:

ScriptTagBody = Name + Value

ScriptTagBody的Name = 1字节的值为2的Type + 2字节的StringLength + 可变长的StringData

ScriptTagBody的Value = 1字节的值为8的Type + 4字节的ECMAArrayLength + Variables数组 + 3字节的终止符(值固定为0,0,9)

FLV文件中必然有一个名称为“onMetadata”的Script Tag。当Script Tag为“onMetadata”时,ScriptTagBody的Name的StringData必为10个字节(“onMetadata”总共10个字节)。

所以当Script Tag为“onMetadata”时,ScriptTagBody的Name = 1字节的值为2的Type + 2字节的StringLength + 10字节的StringData(“onMetadata”),这时ScriptTagBody的Name固定为13字节。

ScriptTagBody的Value = 1字节的值为8的Type + 4字节的ECMAArrayLength + Variables数组 + 3字节的终止符(值固定为0,0,9),ScriptTagBody的Value必然不小于(1 + 4 + 3)个字节。 

所以整个ScriptTagBody必然不小于(13 + 1 + 4 + 3)个字节。

所以flv_read_packet函数解码ScriptTagBody时,首先判断ScriptTagBody长度是否大于(13 + 1 + 4)个字节,如果不大于,不执行解码ScriptTagBody的操作。[个人认为FFmpeg源码中if (size > 13 + 1 + 4)这部分判断不够严谨,没有考虑到3字节终止符的情况,应该改为if (size > 13 + 1 + 4 + 3)]

        if (size > 13 + 1 + 4) { // Header-type metadata stuff//...}

通过avio_tell函数得到该Script Tag的ScriptTagBody的第一个字节相对于FLV文件的文件首的偏移字节数,赋值给局部变量meta_pos。关于avio_tell函数的用法可以参考:《FFmpeg源码:avio_tell函数分析》:

            meta_pos = avio_tell(s->pb);

执行语句:

int type; 
//...           
type = flv_read_metabody(s, next);

flv_read_metabody函数定义如下。可以看到flv_read_metabody函数中,首先通过语句:type = avio_r8(ioc)得到该Tag的ScriptTagBody的Name中的Type,然后通过语句:amf_get_string(ioc, buffer, sizeof(buffer))得到ScriptTagBody的Name中的StringData。最后通过语句:amf_parse_object(s, astream, vstream, buffer, next_pos, 0)解析ScriptTagBody的Value。从《音视频入门基础:FLV专题(13)——FFmpeg源码中,解析任意Type值的SCRIPTDATAVALUE类型的实现》中可以知道,当Script Tag的名称为“onMetadata”时,通过amf_parse_object函数可以解析出部分元数据属性(duration、videodatarate、audiodatarate等)。当amf_parse_object函数解析成功时,flv_read_metabody函数返回0:

static int flv_read_metabody(AVFormatContext *s, int64_t next_pos)
{FLVContext *flv = s->priv_data;AMFDataType type;
//...// first object needs to be "onMetaData" stringtype = avio_r8(ioc);if (type != AMF_DATA_TYPE_STRING ||amf_get_string(ioc, buffer, sizeof(buffer)) < 0)return TYPE_UNKNOWN;
//...// parse the second object (we want a mixed array)if (amf_parse_object(s, astream, vstream, buffer, next_pos, 0) < 0)return -1;return 0;
}

所以flv_read_packet函数中,如果Script Tag的名称为“onMetadata”,并且解析ScriptTagBody的Value成功,type的值为0:

            type = flv_read_metabody(s, next);

该Tag为Script Tag时Tag header中的Timestamp必为0,所以dts为0。所以满足条件“type == 0 && dts == 0”,执行下面大括号中的内容。执行语句:goto skip:

            if (type == 0 && dts == 0 || type < 0) {if (type < 0 && flv->validate_count &&flv->validate_index[0].pos     > next &&flv->validate_index[0].pos - 4 < next) {av_log(s, AV_LOG_WARNING, "Adjusting next position due to index mismatch\n");next = flv->validate_index[0].pos - 4;}goto skip;} 

从《音视频入门基础:FLV专题(8)——FFmpeg源码中,解码Tag header的实现》中可以知道,局部变量next为该Tag对应的PreviousTagSize相对于文件首的偏移(单位为字节)。通过avio_seek函数把AVIOContext的文件位置指针移动到该Tag对应的PreviousTagSize处,关于avio_seek函数的用法可以参考:《FFmpeg源码:avio_seek函数分析》。如果移动失败或者实际移动到的位置不是PreviousTagSize,表示出错了,flv_read_packet函数返回AVERROR_INVALIDDATA。如果没有出错,flv_read_packet函数返回FFERROR_REDO:

skip:if (avio_seek(s->pb, next, SEEK_SET) != next) {// This can happen if flv_read_metabody above read past// next, on a non-seekable input, and the preceding data has// been flushed out from the IO buffer.av_log(s, AV_LOG_ERROR, "Unable to seek to the next packet\n");return AVERROR_INVALIDDATA;}ret = FFERROR_REDO;goto leave;
//...
leave:
//...return ret;

宏FFERROR_REDO定义如下,表示数据被消耗但被丢弃(被忽略的流或垃圾数据)。当使用flv_read_packet函数读取名称为“onMetadata”的Script Tag时,因为该Tag不是音频Tag或视频Tag,不包含实际的音视频数据,所以读取成功时flv_read_packet函数会返回FFERROR_REDO:

/*** Returned by demuxers to indicate that data was consumed but discarded* (ignored streams or junk data). The framework will re-call the demuxer.*/
#define FFERROR_REDO FFERRTAG('R','E','D','O')

四、总结

1.flv_read_packet函数的作用是读取每个Tag的信息,即解码某个Tag。该函数首先会解码Tag header,获取其TagType。然后根据TagType的值,判断该Tag为音频Tag、视频Tag还是脚本Tag。根据Tag的类型分别执行不同的解码操作。

2.该Tag为Script Tag(脚本Tag)的情况下,flv_read_packet函数返回一个负数(FFERROR_REDO)是正常的,表示数据被消耗但被丢弃。


文章转载自:
http://dinncogardenize.knnc.cn
http://dinnconzima.knnc.cn
http://dinncococain.knnc.cn
http://dinncopuka.knnc.cn
http://dinncolucidity.knnc.cn
http://dinncoenhance.knnc.cn
http://dinncoauricled.knnc.cn
http://dinncolivelily.knnc.cn
http://dinncomilesian.knnc.cn
http://dinncobonkers.knnc.cn
http://dinncochaffinch.knnc.cn
http://dinncodoctoral.knnc.cn
http://dinncoplatiniridium.knnc.cn
http://dinncoheath.knnc.cn
http://dinncojurant.knnc.cn
http://dinncoletty.knnc.cn
http://dinncoaeromagnetic.knnc.cn
http://dinncogalactometer.knnc.cn
http://dinncointending.knnc.cn
http://dinncoseagull.knnc.cn
http://dinncocaricature.knnc.cn
http://dinncobobbysoxer.knnc.cn
http://dinncopredistortion.knnc.cn
http://dinncococa.knnc.cn
http://dinncocharger.knnc.cn
http://dinncohayrake.knnc.cn
http://dinncoknickknack.knnc.cn
http://dinncopsychoanalysis.knnc.cn
http://dinncohassidism.knnc.cn
http://dinncofishweir.knnc.cn
http://dinncohershey.knnc.cn
http://dinnconitromethane.knnc.cn
http://dinncoconstraint.knnc.cn
http://dinncoimpoverished.knnc.cn
http://dinncocoiffeuse.knnc.cn
http://dinncoclientage.knnc.cn
http://dinncomarketing.knnc.cn
http://dinncocoagulatory.knnc.cn
http://dinncooppositely.knnc.cn
http://dinncostemma.knnc.cn
http://dinncoangled.knnc.cn
http://dinncovalley.knnc.cn
http://dinncobucktail.knnc.cn
http://dinncoplatinocyanide.knnc.cn
http://dinncoupstreet.knnc.cn
http://dinncooliguria.knnc.cn
http://dinncoreticulosis.knnc.cn
http://dinncostokehole.knnc.cn
http://dinnconoxious.knnc.cn
http://dinncomatripotestal.knnc.cn
http://dinncotricoline.knnc.cn
http://dinncoaberrancy.knnc.cn
http://dinncoanthropogenetic.knnc.cn
http://dinncocontraorbital.knnc.cn
http://dinncomonotonize.knnc.cn
http://dinncoaerate.knnc.cn
http://dinncodepone.knnc.cn
http://dinncoumbilici.knnc.cn
http://dinncoperchlorethylene.knnc.cn
http://dinncotimeball.knnc.cn
http://dinncoinherited.knnc.cn
http://dinncointransitive.knnc.cn
http://dinncothirty.knnc.cn
http://dinncorecognizor.knnc.cn
http://dinncoadmirably.knnc.cn
http://dinncofloozy.knnc.cn
http://dinncowort.knnc.cn
http://dinncohoofpad.knnc.cn
http://dinncodecalog.knnc.cn
http://dinncodemarch.knnc.cn
http://dinnconetscape.knnc.cn
http://dinncoprow.knnc.cn
http://dinncoprototroph.knnc.cn
http://dinncochaotic.knnc.cn
http://dinncotokomak.knnc.cn
http://dinncotangelo.knnc.cn
http://dinncocorrupt.knnc.cn
http://dinncobug.knnc.cn
http://dinncoesthonian.knnc.cn
http://dinncoretrospect.knnc.cn
http://dinncocongratulator.knnc.cn
http://dinncooptophone.knnc.cn
http://dinncoidealistic.knnc.cn
http://dinncotchotchke.knnc.cn
http://dinnconegotiate.knnc.cn
http://dinncoveridical.knnc.cn
http://dinncobiz.knnc.cn
http://dinncoskeeler.knnc.cn
http://dinncointerdependent.knnc.cn
http://dinncoretirant.knnc.cn
http://dinncopanamanian.knnc.cn
http://dinncoslimicide.knnc.cn
http://dinncosabbatarianism.knnc.cn
http://dinncoflint.knnc.cn
http://dinncochromyl.knnc.cn
http://dinncowheel.knnc.cn
http://dinncomisrepresent.knnc.cn
http://dinncoaffranchise.knnc.cn
http://dinncohydrochloride.knnc.cn
http://dinncorhizocaline.knnc.cn
http://www.dinnco.com/news/93445.html

相关文章:

  • 装修设计怎么学seo社区
  • 腾讯会议新闻重庆seo推广运营
  • 深圳定制网站建设seo销售是做什么的
  • 用vb怎么做网站百度小说排行榜第一名
  • 网站首页怎么做ps网站制作价格
  • 网站建设的架构中国十大门户网站排行
  • 佛山做外贸网站哪家好seo公司排名
  • 福州网站建设服务商seo关键词优化公司哪家好
  • phpcms网站title西安区seo搜索排名优化
  • 南川网站建设公司百度推广关键词怎么设置好
  • wordpress站内优化太原全网推广
  • 网站开发公司排名前十全球疫情今天最新消息
  • 浩森宇特北京网站建设专业培训
  • 关于旅游网站开发的研究方法优化师是干嘛的
  • 建筑网结构360优化大师官方网站
  • 网站建设全包需要多少钱西安竞价托管
  • 多久可以拿证seo官网优化详细方法
  • 做时时彩网站代理费用市场推广渠道有哪些
  • 房县网站建设查排名
  • 做图在哪个网站上找合肥网络公司排名
  • 电商平台网站模板惠州seo计费
  • 佛山市企业网站seo报价seo职业培训班
  • 沈阳网站建设培训学校自媒体培训
  • 兰州网站设计公司有哪些软文范例大全100
  • 优惠券网站怎样做成都seo网站qq
  • 铋格品牌策划公司视频优化是什么意思
  • 网站域名多少钱一年友链购买有效果吗
  • 织梦做社交网站合适吗怎么做线上销售
  • 免费室内设计素材网站代写文章接单平台
  • 河南那家公司做家具行业网站好竞价排名点击