笔者在使用自行编译的ffmplay调试播放网络流过种中遇到无HTTP header返回的问题,日志打印级别为TRACE,如下:
pening 'http://10.48.144.87:8100/MPEG-DASH/MP4_ONDEMAND_SegmentBase_MutilBitrate/MP4_ONDEMAND_SegmentBase.mpd
' for reading
Setting default whitelist 'http,https,tls,rtp,tcp,udp,crypto,httpproxy'
Original list of addresses:
Address 10.48.144.87 port 8100
Interleaved list of addresses:
Address 10.48.144.87 port 8100
Starting connection attempt to 10.48.144.87 port 8100
Successfully connected to 10.48.144.87 port 8100
request: GET /MPEG-DASH/MP4_ONDEMAND_SegmentBase_MutilBitrate/MP4_ONDEMAND_SegmentBase.mpd
HTTP/1.1
User-Agent: Lavf/58.29.100
Accept: */*
Range: bytes=0-
Connection: close
Host: 10.48.144.87:8100
Icy-MetaData: 1
header='<?xml version="1.0"?>'
http_code=0
header='<!-- MPD file Generated with GPAC version 0.5.2-DEV-rev322-gf6fed6c-master at 2015-05-13T01:20:55.664Z-->'
header='<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" minBufferTime="PT1.500S" type="static" mediaPresentationDuration="PT0H15M37.045S" maxSegmentDuration="PT0H0M9.968S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011">'
header=' <ProgramInformation moreInformationURL="http://gpac.sourceforge.net">'
header=' <Title>H264_AAC_dash.mpd generated by GPAC</Title>'
header=' </ProgramInformation>'
header=''
Unable to parse 'http://10.48.144.87:8100/MPEG-DASH/MP4_ONDEMAND_SegmentBase_MutilBitrate/MP4_ONDEMAND_SegmentBase.mpd
' - missing root node
播放流的MPD文件如下:
<?xml version="1.0"?>
<!-- MPD file Generated with GPAC version 0.5.2-DEV-rev322-gf6fed6c-master at 2015-05-13T01:20:55.664Z-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" minBufferTime="PT1.500S" type="static" mediaPresentationDuration="PT0H15M37.045S" maxSegmentDuration="PT0H0M9.968S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011">
<ProgramInformation moreInformationURL="http://gpac.sourceforge.net">
<Title>H264_AAC_dash.mpd generated by GPAC</Title>
</ProgramInformation>
<Period duration="PT0H15M37.045S">
<AdaptationSet segmentAlignment="true" maxWidth="1920" maxHeight="1080" maxFrameRate="24000/1001" par="16:9" lang="eng" subsegmentAlignment="true" subsegmentStartsWithSAP="1">
<ContentComponent id="1" contentType="video" />
<ContentComponent id="2" contentType="audio" />
<Representation id="1" mimeType="video/mp4" codecs="avc1.4d0029,mp4a.40.2" width="1920" height="1080" frameRate="24000/1001" sar="1:1" audioSamplingRate="48000" startWithSAP="1" bandwidth="6161839">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>H264_AAC_dashinit.mp4</BaseURL>
<SegmentBase indexRangeExact="true" indexRange="1297-2528">
<Initialization range="0-1296"/>
</SegmentBase>
</Representation>
<Representation id="2" mimeType="video/mp4" codecs="avc1.4d0029,mp4a.40.2" width="1280" height="720" frameRate="24000/1001" sar="1:1" audioSamplingRate="48000" startWithSAP="1" bandwidth="2162498">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>H264_AAC_1_dashinit.mp4</BaseURL>
<SegmentBase indexRangeExact="true" indexRange="1294-2525">
<Initialization range="0-1293"/>
</SegmentBase>
</Representation>
<Representation id="3" mimeType="video/mp4" codecs="avc1.4d0029,mp4a.40.2" width="720" height="406" frameRate="24000/1001" sar="1:1" audioSamplingRate="48000" startWithSAP="1" bandwidth="662884">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>H264_AAC_2_dashinit.mp4</BaseURL>
<SegmentBase indexRangeExact="true" indexRange="1294-2525">
<Initialization range="0-1293"/>
</SegmentBase>
</Representation>
</AdaptationSet>
</Period>
</MPD>
播放流DASH在播放过程中找不到root结点,播放失败,失败的代码如下图所示:
filesize = avio_read(in, buffer, filesize);
if (filesize <= 0) {
av_log(s, AV_LOG_ERROR, "Unable to read to offset '%s'\n", url);
ret = AVERROR_INVALIDDATA;
} else {
LIBXML_TEST_VERSION
doc = xmlReadMemory(buffer, filesize, c->base_url, NULL, 0);
root_element = xmlDocGetRootElement(doc);
node = root_element;
if (!node) {
ret = AVERROR_INVALIDDATA;
av_log(s, AV_LOG_ERROR, "Unable to parse '%s' - missing root node\n", url);
goto cleanup;
}
追踪avio_read发现从网络中读取的MPD数据是从<Period duration="PT0H15M37.045S">这个位置开始。同时TRACE日志也显示,软件通过如下过程 init_input ->io_open_default->ffio_open_whitelist->ffurl_open_whitelist->ffurl_connect->http_open->http_open_cnx->http_open_cnx_internal->http_connect->http_read_header->http_get_line->http_getc->ffurl_read->retry_transfer_wrapper->tcp_read发送了tcp请求:
request: GET /MPEG-DASH/MP4_ONDEMAND_SegmentBase_MutilBitrate/MP4_ONDEMAND_SegmentBase.mpd
HTTP/1.1
User-Agent: Lavf/58.29.100
Accept: */*
Range: bytes=0-
Connection: close
Host: 10.48.144.87:8100
Icy-MetaData: 1
对比正常运行的日志记录,软件并未返回HTTP响应却返回了MPD文件的内容,导致http在get_line的时候,把MPD数据的头部给丢掉了,直到遇到了下一个新的空行。这是问题所在,但原因是什么呢?wireshark抓包显示未发送HTTP请求,也没有HTTP响应,正常交互信息如下:
调试windows上的send及revc函数没有返回错误。使用google chrome浏览器抓包情况也是无HTTP HEADER响应,但可以下载到MPD文件,后来发现,http://10.48.144.87:8100/MPEG-DASH/MP4_ONDEMAND_SegmentBase_MutilBitrate/MP4_ONDEMAND_SegmentBase.mpd地址是从其他地方复制而来,复制地址的时候,后面多了一个回车换行符,就是这个符号导致的错误。第一次接收到的数据实际上是未发生HTTP的GET请求的情况下,读取到的数据。如下是FFPLAY正常连接的日志:
Successfully connected to 10.48.144.87 port 8100
request: GET /MPEG-DASH/MP4_ONDEMAND_SegmentBase_MutilBitrate/MP4_ONDEMAND_SegmentBase.mpd HTTP/1.1
User-Agent: Lavf/58.29.100
Accept: */*
Range: bytes=0-
Connection: close
Host: 10.48.144.87:8100
Icy-MetaData: 1
header='HTTP/1.1 206 Partial Content'
http_code=206
header='Content-Type: application/vnd.ms-project'
header='Last-Modified: Wed, 13 May 2015 01:20:56 GMT'
header='Accept-Ranges: bytes'
header='ETag: "04ca7f1b8dd01:0"'
header='Server: Microsoft-IIS/7.5'
header='X-Powered-By: ASP.NET'
header='Date: Mon, 29 Apr 2024 10:15:32 GMT'
header='Connection: close'
header='Content-Length: 2383'
header='Content-Range: bytes 0-2382/2383'
header=''