live555 关于使用ffmpeg扩展文件格式
2012-01-09 13:42
531 查看
live555目前只mpg、mkv、webM等少数几种音视频混合的文件,可以使用ffmpeg来扩展live555所支持的文件格式。花了一个多月的时间,
终于可以支持mp4和avi了,媒体格式支持mpeg4、h264、mp3、aac。主要是参考了live555中mpg的实现。
1.扩展mediaServer的主要步骤
1)定义一个RTSP Server类MyRTSPServer,继承自DynamicRTSPServer。作用是重新实现lookupServerMediaSession函数,在其中添加对avi、mp4的支持代码。
2)参考mpg的实现,定义以下几个类
MyDemux->Mdeium:
调用ffmpeg中的函数,完成文件的解析,分离出文件中媒体流的数据。每一个客户端连接将对应一个MyDemux实例。
MyDemuxedElementaryStream->FramedSource:
这个类作为source,实际上会调用MyDemux实例获取所需的数据。每一个流将对应一个MyDemuxedElementaryStream实例。
MyServerDemux->Medium:
这个一个服务类,主要是辅助创建MyDemux、MyDemuxedElementaryStream及subsession实例。
3)subsession
对于每一种媒体格式,都需要实现一个subsession,并重新实现虚函数createNewStreamSource以创建自己的source。
h264,处理h264的subsession从H264VideoFileServerMediaSubsession继承,将从packet中可以获取h264的es流,直接交给H264VideoStreamFramer处理即可。
mpeg4,subsession从MPEG4VideoFileServerMediaSubsession继承,另外需要注意的是,从packet中获取到的数据并不是严格的ES流。与处理mpeg4 es流相关的类有两个,MPEG4VideoStreamFramer与MPEG4VideoStreamDiscreteFramer,这里应选择MPEG4VideoStreamDiscreteFramer。具体可以参考前面的文章"live555
关于mpeg4的处理"
mp3, subsession从MP3AudioFileServerMediaSubsession继承。注意还需要实现seekStreamSource函数,函数体可以为空。在创建MP3AudioFileServerMediaSubsession时,传递的参数中generateADUs应为False, interleaving为空。
aac, subsession从FileServerMediaSubsession继承。要实现createNewStreamSource及createNewRTPSink。createNewRTPSink的实现,可以参考live555对Matroska中aac的处理。
2.处理avi、mp4文件文件的一些注意事项
通过ffmpeg获取的数据一般保存在packet中。 对于avi文件,处理比较简单,直接将packet中的数据提取出来,进行后续处理即可。对于mp4文件,则稍复杂。
从mp4中提取h264数据时, packet中不会包含SPS及PPS信息,这些信息储存在***CodecContext的extradata数据域中,通过流过滤器"h264_mp4toannexb"可以得到标准的sps及pps。另外packet中的数据并不是标准nalu单元,需要将前4个字节替成开始符。详情见"ffmpeg 从mp4上提取H264的nalu"。
关于mp4中的mpeg4, 获取的packet中,只包含vop层次(0x000001B5)的数据,vos(0x000001B0)则储存在在***CodecContext的extradata数据域中,所以只需要将extradata中的数据添加到流的开始处即可。
对于mp4中的音频aac来讲,音频配置信息config,也是保存在extradata。
3.aac音频的配置信息config
mpeg4中的aac是交给MPEG4GenericRTPSink的,需要关注一下传递的参数,来看Matroska文件中是怎么处理的
创建MPEG4GenericRTPSink时,fConfigStr就是aac的帧配置信息,它表示AAC帧的配置信息。其实config有两种传输方式,包含在RTP负载称为带内传输,否则称为带外传输,这时就必需在SDP中传输config信息了。显然使用带外传输可以节约带宽。 config是一个16进制的8位字节串,可表示ISO/IEC 14496-3 [5] 定义的MPEG-4音频负载配置数据"StreamMuxConfig"。SDP中还有一个cpresent属性, 一个布尔值参数,表示音频负载配置数据是否已经复用到一个RTP负载中。0表示尚未复用,1表示已经复用。该参数的缺省值为1。即缺省情况下为带外传输。
在MPEG4GenericRTPSink构造函数中可以看到这个配置信息是如何保存到sdp中的。
ffmpeg获取到的config信息保存在***CodecContext.extradata中,占用两个字节。对于44khz的音频,这两个字节顺序为0x12,0x10。不过需要转换成字符串后再保存到config中,所以最后config="1816"。
4.mp3、aac帧播放时间
aac每帧均为1024个采样,所以可以通过如下公式计算:
frame_duration = 1024 * 1000000 / sample_rate
例如:sample_rate = 44100HZ时, 计算出的时长为23.219ms
mp3 每帧均为1152个字节, 则:
frame_duration = 1152 * 1000000 / sample_rate
例如:sample_rate = 44100HZ时, 计算出的时长为26.122ms,这就是经常听到的mp3每帧播放时间固定为26ms的由来
附上一张mpeg音频每帧采样数表
一些问题:
这个地方有一个问题,使用vlc播放avi或者mp4中的mpeg4视频时,非常卡,cpu会达到100%,但是使用ffplay和mplayer时播放正常,
PS:
代码已上传至http://download.csdn.net/detail/gavinr/4320175
终于可以支持mp4和avi了,媒体格式支持mpeg4、h264、mp3、aac。主要是参考了live555中mpg的实现。
1.扩展mediaServer的主要步骤
1)定义一个RTSP Server类MyRTSPServer,继承自DynamicRTSPServer。作用是重新实现lookupServerMediaSession函数,在其中添加对avi、mp4的支持代码。
2)参考mpg的实现,定义以下几个类
MyDemux->Mdeium:
调用ffmpeg中的函数,完成文件的解析,分离出文件中媒体流的数据。每一个客户端连接将对应一个MyDemux实例。
MyDemuxedElementaryStream->FramedSource:
这个类作为source,实际上会调用MyDemux实例获取所需的数据。每一个流将对应一个MyDemuxedElementaryStream实例。
MyServerDemux->Medium:
这个一个服务类,主要是辅助创建MyDemux、MyDemuxedElementaryStream及subsession实例。
3)subsession
对于每一种媒体格式,都需要实现一个subsession,并重新实现虚函数createNewStreamSource以创建自己的source。
h264,处理h264的subsession从H264VideoFileServerMediaSubsession继承,将从packet中可以获取h264的es流,直接交给H264VideoStreamFramer处理即可。
mpeg4,subsession从MPEG4VideoFileServerMediaSubsession继承,另外需要注意的是,从packet中获取到的数据并不是严格的ES流。与处理mpeg4 es流相关的类有两个,MPEG4VideoStreamFramer与MPEG4VideoStreamDiscreteFramer,这里应选择MPEG4VideoStreamDiscreteFramer。具体可以参考前面的文章"live555
关于mpeg4的处理"
mp3, subsession从MP3AudioFileServerMediaSubsession继承。注意还需要实现seekStreamSource函数,函数体可以为空。在创建MP3AudioFileServerMediaSubsession时,传递的参数中generateADUs应为False, interleaving为空。
aac, subsession从FileServerMediaSubsession继承。要实现createNewStreamSource及createNewRTPSink。createNewRTPSink的实现,可以参考live555对Matroska中aac的处理。
2.处理avi、mp4文件文件的一些注意事项
通过ffmpeg获取的数据一般保存在packet中。 对于avi文件,处理比较简单,直接将packet中的数据提取出来,进行后续处理即可。对于mp4文件,则稍复杂。
从mp4中提取h264数据时, packet中不会包含SPS及PPS信息,这些信息储存在***CodecContext的extradata数据域中,通过流过滤器"h264_mp4toannexb"可以得到标准的sps及pps。另外packet中的数据并不是标准nalu单元,需要将前4个字节替成开始符。详情见"ffmpeg 从mp4上提取H264的nalu"。
关于mp4中的mpeg4, 获取的packet中,只包含vop层次(0x000001B5)的数据,vos(0x000001B0)则储存在在***CodecContext的extradata数据域中,所以只需要将extradata中的数据添加到流的开始处即可。
对于mp4中的音频aac来讲,音频配置信息config,也是保存在extradata。
3.aac音频的配置信息config
mpeg4中的aac是交给MPEG4GenericRTPSink的,需要关注一下传递的参数,来看Matroska文件中是怎么处理的
RTPSink* AACAudioMatroskaFileServerMediaSubsession ::createNewRTPSink(Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource* /*inputSource*/) { MatroskaTrack* track = fOurDemux.lookup(fTrackNumber); return MPEG4GenericRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic, track->samplingFrequency, //采样频率 "audio", "AAC-hbr", fConfigStr, track->numChannels); //通道数 }
创建MPEG4GenericRTPSink时,fConfigStr就是aac的帧配置信息,它表示AAC帧的配置信息。其实config有两种传输方式,包含在RTP负载称为带内传输,否则称为带外传输,这时就必需在SDP中传输config信息了。显然使用带外传输可以节约带宽。 config是一个16进制的8位字节串,可表示ISO/IEC 14496-3 [5] 定义的MPEG-4音频负载配置数据"StreamMuxConfig"。SDP中还有一个cpresent属性, 一个布尔值参数,表示音频负载配置数据是否已经复用到一个RTP负载中。0表示尚未复用,1表示已经复用。该参数的缺省值为1。即缺省情况下为带外传输。
在MPEG4GenericRTPSink构造函数中可以看到这个配置信息是如何保存到sdp中的。
MPEG4GenericRTPSink ::MPEG4GenericRTPSink(UsageEnvironment& env, Groupsock* RTPgs, u_int8_t rtpPayloadFormat, u_int32_t rtpTimestampFrequency, char const* sdpMediaTypeString, char const* mpeg4Mode, char const* configString, unsigned numChannels) : MultiFramedRTPSink(env, RTPgs, rtpPayloadFormat, rtpTimestampFrequency, "MPEG4-GENERIC", numChannels), fSDPMediaTypeString(strDup(sdpMediaTypeString)), fMPEG4Mode(strDup(mpeg4Mode)), fConfigString(strDup(configString)) { // Check whether "mpeg4Mode" is one that we handle: if (mpeg4Mode == NULL) { env << "MPEG4GenericRTPSink error: NULL \"mpeg4Mode\" parameter\n"; } else if (strcmp(mpeg4Mode, "AAC-hbr") != 0) { //说明必需使用"AAC-hbr"模式 env << "MPEG4GenericRTPSink error: Unknown \"mpeg4Mode\" parameter: \"" << mpeg4Mode << "\"\n"; } // Set up the "a=fmtp:" SDP line for this stream: char const* fmtpFmt = "a=fmtp:%d " "streamtype=%d;profile-level-id=1;" "mode=%s;sizelength=13;indexlength=3;indexdeltalength=3;" "config=%s\r\n"; //config属性 unsigned fmtpFmtSize = strlen(fmtpFmt) + 3 /* max char len */ + 3 /* max char len */ + strlen(fMPEG4Mode) + strlen(fConfigString); //注意 char* fmtp = new char[fmtpFmtSize]; sprintf(fmtp, fmtpFmt, rtpPayloadType(), strcmp(fSDPMediaTypeString, "video") == 0 ? 4 : 5, fMPEG4Mode, fConfigString); //注意 fFmtpSDPLine = strDup(fmtp); delete[] fmtp; }
ffmpeg获取到的config信息保存在***CodecContext.extradata中,占用两个字节。对于44khz的音频,这两个字节顺序为0x12,0x10。不过需要转换成字符串后再保存到config中,所以最后config="1816"。
4.mp3、aac帧播放时间
aac每帧均为1024个采样,所以可以通过如下公式计算:
frame_duration = 1024 * 1000000 / sample_rate
例如:sample_rate = 44100HZ时, 计算出的时长为23.219ms
mp3 每帧均为1152个字节, 则:
frame_duration = 1152 * 1000000 / sample_rate
例如:sample_rate = 44100HZ时, 计算出的时长为26.122ms,这就是经常听到的mp3每帧播放时间固定为26ms的由来
附上一张mpeg音频每帧采样数表
一些问题:
这个地方有一个问题,使用vlc播放avi或者mp4中的mpeg4视频时,非常卡,cpu会达到100%,但是使用ffplay和mplayer时播放正常,
PS:
代码已上传至http://download.csdn.net/detail/gavinr/4320175
相关文章推荐
- live555 关于使用ffmpeg扩展文件格式
- live555 关于使用ffmpeg扩展文件格式
- live555 关于使用ffmpeg扩展文件格式
- live555 关于使用ffmpeg扩展文件格式
- live555使用ffmpeg扩展(mp4)文件格式
- 关于asp.net C# 导出Excel文件 打开Excel文件格式与扩展名指定格式不一致的解决办法
- php视频格式转换---------ffmpeg-php扩展与ffmpeg.exe安装与使用
- 使用ffmpeg转换文件格式,及ffmpeg参数说明
- 关于asp.net C# 导出Excel文件 打开Excel文件格式与扩展名指定格式不一致的解决办法
- 关于缓存文件格式(单文件文件柜)是否适合使用伙伴算法的讨论
- 关于使用NetBeans无法使用编码utf-8(NetBeans默认编码格式)安全地打开文件的问题
- 关于Java Web 使用 iText 将数据库中的 表 的数据 生成 PDF 格式文件(升級版本)
- 关于asp.net C# 导出Excel文件打开Excel文件格式与扩展名指定格式不一致的解决办法
- 关于asp.net C# 导出Excel文件 打开Excel文件格式与扩展名指定格式不一致的解决办法
- 使用ffmpeg转换文件格式,及ffmpeg参数说明
- echarts地图扩展文件使用geoJson格式。
- 使用ffmpeg将mp4文件中的h264码流转为raw h264文件格式或ts文件格式
- 使用ffmpeg解码音频文件到PCM格式
- 使用FFMPEG编码保存MPEG-1/MPEG-2文件格式
- 使用ffmpeg转换文件格式,及ffmpeg参数说明(转)