01 音视频格式简介、编解码、音视频同步

配套哔哩哔哩视频主页:才鲸嵌入式

配套gitee源码仓库:才鲸 

音视频格式简介

1. 文件格式

苹果原始QuicTime协议地址

  • .mp3 一种音频编码与压缩格式,全称MPEG-1 or MPEG-2 Audio Layer III,ISO/IEC 13818-3 or ISO/IEC 11172-3 CSDN下载地址 需要下载积分

  • .jpg/.jpeg JFIF格式的文件,JPEG压缩方法,协议ISO/IEC 10918-1 协议pdf下载地址 官网免费下载 CSDN下载地址 需要下载积分(与上面的文件一致)

  • .mjpg/.mjpeg 格式RFC 2435 ITU T.81 在线阅读 下载地址见前面.jpeg

2. 编码格式

  • mp3 MPEG-1 or MPEG-2 Audio Layer III ISO/IEC 13818-3 or ISO/IEC 11172-3 协议下载地址见前面.mp3

  • aac AAC由国际标准化组织及国际电工委员会标准化为MPEG-2及MPEG-4规格的一部分。 .aac使用MPEG-2 Audio Transport Stream容器 MPEG-2 AAC和MPEG-4 AAC ISO/IEC 13818-7 or ISO/IEC 14496-3 (HE-AAC/aac+) 13818-7下载地址 需要下载积分 14496-3下载地址 需要下载积分

  • h264 全称MPEG-4 Part 10, Advanced Video Coding,ISO/IEC 14496-10:2004 协议pdf下载地址 下载速度很慢,但是可以下载成功

  • mpeg2 ISO/IEC 13818-1 音视频同步与复用 13818-1中文版下载地址 需要下载积分 ISO/IEC 13818-2 视频 138181~3中文版下载地址 需要一个下载积分 13818-2英文版下载地址 需要下载积分

  • jpeg 协议ISO/IEC 10918-1 or ITU T.81 下载地址见前面.jpeg

3. 开源编解码器

  • ffmpeg 官网 Git仓库 WiKi 压缩编码的视频数据输出成为非压缩的颜色数据,例如 YUV420P,RGB 等等;压缩编码的音频数据输出成为非压缩的音频抽样数据,例如 PCM 数据。

  • bilibili网页播放器 flv.js Github仓库

  • bilibili苹果安卓播放器 ijkplayer Github仓库

  • ffserver ffserver wiki地址

  • ffplay ffplay 官网 使用the FFmpeg libraries and the SDL library。 MediaInfo查看媒体文件信息 官网 源码

4. 参考资料

5. ffplay源码分析

    // 获取文件封装格式
    main() --> stream_open() --> read_thread() --> avformat_open_input() --> init_input()
    --> av_probe_input_buffer2() --> av_probe_input_format2() --> av_probe_input_format3()
    --> for(){ score = fmt1->read_probe() } // 选出封装格式,如mp4、mkv // AVInputFormat *fmt1
    // mp4的read_probe() 是 mov_probe()
    // 解封装,获取基础的流信息
    main() --> stream_open() --> read_thread() --> avformat_open_input()
    --> s->iformat->read_header(s) // 获取基本的流信息,如有多少音频和视频,音视频是什么格式
    // mp4的read_header() 是 mov_read_header()
    // 获取流里面的帧
    --> ff_read_packet()
    --> s->iformat->read_packet(s, pkt)
    // mp4的read_packet() 是 mov_read_packet()
    // 解码
    AVCodec *codec
    video_thread() --> get_video_frame() --> decoder_decode_frame() --> packet_queue_get() --> avcodec_receive_frame()
    --> decode_receive_frame_internal() --> decode_simple_receive_frame() --> decode_simple_internal()
    --> avctx->codec->decode()
    ffmpeg/libavcodec/mpegaudiodec_float.c   decode_frame()
    ffmpeg/libavcodec/h264dec.c   h264_decode_frame()
    // 文件操作
    //最终的读数据接口 url.h URLProtocol 将数据读到 AVIOContext
    main() --> stream_open() --> read_thread() --> avformat_alloc_context()
    --> avformat_get_context_defaults() --> io_open_default()
    --> ffio_open_whitelist() --> ffurl_open_whitelist()
    --> ffurl_connect() --> uc->prot->url_open()
    //实际调用的地方是:
    read_thread() --> avformat_open_input() --> init_input()
    --> s->io_open()
    //读取的数据放到AVIOContext中的buffer中
    url_open            = file_open, //file.c
    ffurl_read()  ffio_geturlcontext()  AVIOContext中read_packet()
    //数据流通过程
    read_probe(AVProbeData.buf) <-- avio_read(AVIOContext.buf_ptr, 2k) <-- AVFormatContext.pb
    //h264 hevc转码
    main() --> transcode() --> transcode_step() --> process_input() --> process_input_packet()
    --> do_streamcopy() --> output_packet() --> write_packet() --> av_interleaved_write_frame()
    --> write_packets_common() --> write_packet_common() --> write_packet() --> ff_raw_write_packet()
    --> avio_write() --> memcpy()
    //mpeg4转码
    main() --> transcode() --> transcode_step() --> process_input() --> process_input_packet()
    --> decode_video --> decode --> avcodec_send_packet --> avcodec_receive_frame
    --> av_bsf_send_packet
    main() --> transcode() --> transcode_step() --> reap_filters
    -->av_buffersink_get_frame_flags --> get_frame_internal
    --> ff_inlink_consume_frame --> ff_framequeue_take
    (从队列里取出帧FFFrameQueue AVFilterLink AVFilterContex->inputs[0] OutputStream
    output_streams)
    //--> return_or_keep_frame --> av_frame_ref<frame.c>
    //--> do_video_out --> avcodec_send_frame --> do_encode
    //--> do_video_out--> avcodec_receive_packet<encode.c> --> av_packet_move_ref 执行完之后得到mpeg4视频流

6. 额外的网页资料

7. ffmpeg源码分析

    //打开文件
    main() --> ffmpeg_parse_options() --> open_files() -->
    --> open_input_file() --> avformat_open_input() --> AVFormatContext *ic
    //处理流
    --> choose_decoder() --> avformat_find_stream_info()
    --> add_input_streams() --> transcode() --> transcode_step()
    --> transcode_step() --> transcode_from_filter()

8. 音视频同步

mp4 mdat中存储的视频帧顺序不是按显示顺序存放的,是按解码顺序放的!但是要用elecardstreameyetools工具分析h264流文件才能看出来,普通的工具不行!然后能够看出ctts的值是对的,因为ctts的值不能为负数,所以第一个ctts值是整体的偏移值!

9. dts/pts在mp4文件的获取

	mov.c
	//dts的计算
	mov_read_packet() --> dts = timestamp; 	mov_read_trak() --> mov_build_index() --> timestamp = current_dts{in stsc box}; current_dts += stts_data.duration{in stts box} --> 
	//需要调整的时候--> mov_fix_index() --> add_index_entry()
	//pts的计算
	//没有b帧时
	pts = dts
	//有b帧时
	pts = dts + dts_shift + ctts_data.duration;
	dts_shift: mov_update_dts_shift() --> ctts_duration{ctts box存放dts pts差值}

10. 音视频同步流程

    /* 音频播放流程 */
    ffplay.c
    main() --> stream_open() --> read_thread() --> stream_component_open() --> audio_open() --> sdl_audio_callback()
    --> SDL_OpenAudioDevice() --> SDL_PauseAudioDevice()
    /* 视频播放流程 */
    main() --> event_loop() --> refresh_loop_wait_event() --> video_refresh() --> video_display() --> video_image_display()

11. 音视频同步的时间轴获取流程

	mov.c
		mp4解封装获取pkt->pts

	decode.c 
		ff_decode_frame_props()  frame->pts = pkt->pts;

	decoder_decode_frame() -->
		音频:frame->pts //这里的frame->pts和原始的mov.c中mp4的pkt->pts一致
		视频:frame->pts

	//获取Frame中af->pts(float,以秒为单位)
	audio_thread()  or video_thread()-->
		af->pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb); //从累计数据量转换为时间轴实际秒数

	//获取VideoState中的audio_clock
	//=====================
	struct Frame --> double af->pts; double duration; //实测为当前帧从0开始的相对秒数
	audio_decode_frame() -->
	struct VideoState --> double audio_clock; //实测为从零开始,当前帧播完时的相对秒数(浮点型,精确到毫秒)
		is->audio_clock = af->pts + (double) af->frame->nb_samples / af->frame->sample_rate; //l2493

	调整时间轴时间 //获取Clock中的pts
	//======================
	sdl_audio_callback() -->
		set_clock_at(&is->audclk, ...) --> Clock audclk; --> .pts --> get form "is->audio_clock"

12. 使用ffmepg中的libavcodec编解码库,解封装自己做,解码mpeg1视频流的官方例子 decode_video.c decode_audio.c

13. 使用sdl2 api,自己播放音视频的官方用例 (官方的示例不太实用,还是百度上的示例有用)

Playing Sounds

14 .一些FFMPEG转码命令

  • ffmpeg mp4转pcm,播放PCM ffmpeg -i 1.mp4 -vn -ar 44100 -ac 2 -f s16le out.pcm ffplay -ac 2 -ar 44100 -f s16le out.pcm

  • ffmpeg mkv转mp4 ffmpeg -i input.mkv -c:v copy -c:a copy output.mp4

  • ffmpeg 转mpeg2 mpeg4纯视频流

转mpeg4 mpeg2: -vcodec mpeg4, -vcodec mpeg2video

转码其它: -c:v copy out.m2v/m4v/h264/hevc/mpeg

【注意!】要生成纯mpeg4视频流文件,需要先./configure --disable-muxer=ipod 再make,取消掉ffmpeg的ipod m4v格式,这个格式实际上是mp4 然后ffmpeg -i input.mp4 output.m4v 直接ffmpeg -i in.mp4 -vcodec mpeg4 mpeg4.mp4生成的mpeg4.mp4将packet直接拷贝成.m4v文件并不能播放 而用ffmpeg -i mkv.mkv -i in.mp4 -c:v copy -c:a copy -map 0✌️0 -map 1🅰️0 match_m4v.mp4生成的mp4文件才将视频流直接拷贝成.m4v后能播放 生成m4v文件时需要指定编码器-vcodec mpeg4,直接copy不能播放

  • Merge video and audio of two files:

ffmpeg -i s720-128_96-44100_2.mp4 -i a11025.aac -c:v copy -c:a aac -strict experimental -map 0✌️0 -map 1🅰️0 output.mp4

ffmpeg -i 128_96_44100-movie.mp4 -i ShenTouNaiBa3.mp4 -c:v copy -c:a copy -map 0✌️0 -map 1🅰️0 movie_test1.mp4

ffmpeg have not libxh264 and libmp3lame Compress movie -s 320*240 -ar 44100 -ac 1 or 2

  • mp4 MDAT put in the head -movflags faststart
  • Download SDL2-2.0.4.rar in csdn ffplay使用sdl2播放音视频

./configure;

make;

and make install or can install libsdl2-dev The ffplay can't play video:

make clean;

change -lW to -lSDL2 in EXTRALIBS of ffbuild/config.mak

Use media codes, add -L/usr/lib/i386-linux-gnu -lSDL2 in line 120 of scripts/gcclink.sh

  • ffmpeg command Mp4 to yuv:

ffmpeg -i ~/video_files/s320.mp4 -s 640480 -pix_fmt yuv420p out.yuv ffplay -video_size 640480 -i out.yuv

  • 从某一时间开始截取一定长度音视频 -ss 7 -t 1 //从第7秒开始截取1s
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值