配套哔哩哔哩视频主页:才鲸嵌入式
配套gitee源码仓库:才鲸
音视频格式简介
1. 文件格式
- .mkv 一种容器和文件格式,和AVI MP4 ASF类似 matroska官网 协议pdf下载地址
- .mp4 一种容器格式,全名MPEG-4第14部分,协议ISO/IEC 14496-14:2003 mpeg官网 (速度很慢,无法下载协议文档) 协议pdf下载地址 注册以后即可下载,无需下载积分
苹果原始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. 参考资料
- 如何用ffplay播放视频 ISO/IEC 14496-12:2015(ISO格式) 官网可免费下载
- ffplay read_thread获取文件信息流程
- ffplay avformat_open_input解封装流程
- fplay probe探测文件格式流程
- mp4文件格式详解
- mkv文件格式详解
- ffplay 视频显示流程
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. 额外的网页资料
- mp4数据流结构 《[音视频]mp4相比m3u8第一帧加载较慢的原因?》
- mp4大部分box详细介绍《mp4封装格式各box类型讲解及IBP帧计算》
- mkv大部分element详细介绍 《【多媒体封装格式详解】---MKV》cluster/block
- 《H.264编码格式简单分析》
- 《【H264/AVC 句法和语义详解】(二):h264码流格式与NALU详解一》
- 《H264码流和Mp4结构详解》 《H.264码流结构解析》
- !!!《H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流》
- !!!《MP4中提取H.264码流》
- !!《【VS开发】MP4与H.264》
- 《用ffmpeg从MP4中提取h.264码流》
- 《H264(NAL简介与I帧判断)》
- 《区分mp4格式里面mdat中的音频和视频数据》
- !!!《MP4 mdat box解析》
- 测试视频下载 《Mpeg MP4 Container》
- !!!《mp4所有box详解》
- !!!《H264码流详细说明》
- 《H264码流分析》
- AAC 音频格式详解
- 【多媒体封装格式详解】---MP4【4】
- mp4文件格式解析 ffmpeg命令大全 (保存流)
- Matroska文件解析之SimpleBlock
- FFmpeg简易播放器的实现5-音视频同步
- Fmpeg图解:结构体关系链接图
- FFMPEG】关于硬解码和软解码
- FFmpeg硬件解码-HWAccelIntro
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. 音视频同步
- 关于音视频同步 ffplay的同步方式解析
- 如何实现音视频同步 (live555)
- 播放器技术分享(3):音画同步
- 音视频同步原理及实现
- 即时通讯——详解音视频同步技术
- 音视频同步(播放)原理
- WebRTC音视频同步详解
- 视频解码研究之PTS(2)Mp4格式,AVI格式和MKV格式
- 视频解码研究之PTS(1)TS格式和FLV格式
- TS流的PCR PTS DTS时间戳计算
- mkv block解析
- 如何在H264数据中获取PTS
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