0%

FFmpeg(三)

FFmpeg-安装及基本概念
FFmpeg-命令
FFmpeg-demo源码地址
这里记录通过 C语言 操作FFmpeg对多媒体文件的处理

Log

常用日志级别(级别由高到底排列)
1.AV_LOFG_ERROR
2.AV_LOG_WARNING
3.AV_LOG_INFO

启用步骤

1
2
3
include <libavutil/log.h>
av_log_set_level(AV_LOG_DEBUG) #只有该级别以及该级别之上的日志才会打印
av_log(NULL,AV_LOG_INFO,"hello world:%s\n","op" )
1
2
3
4
➜  FFmpeg-demo git:(master) clang -g -o ffmpeg_log ffmpeg_log.c -lavutil
➜ FFmpeg-demo git:(master) ✗ ./ffmpeg_log
hello world!
➜ FFmpeg-demo git:(master) ✗

文件的删除&重命名

avpriv_io_move("111.txt","222.txt");重命名
avpriv_io_delete("./mytestfile.txt");删除

1
2
3
➜  FFmpeg-demo git:(master) ✗ clang -g -o ffmpeg_del ffmpeg_file.c `pkg-config --libs libavformat`
➜ FFmpeg-demo git:(master) ✗ pkg-config --libs libavformat #这一命令的作用时:在系统中寻找到libavformat库所在的位置
-L/usr/local/Cellar/ffmpeg/4.2.2_2/lib -lavformat

操作目录

avio_open_dir
avio_read_dir
avio_free_directory_entry
avio_close_dir

1
2
3
av_log(NULL, AV_LOG_INFO, "%12"PRId64"%s \n",entry->size,entry->name);

# PRId64 是ffmpeg里面定义的一个宏,ffmpeg里面读取的文件也是64位的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
➜  FFmpeg-demo git:(master) ✗ clang -g -o list ffmpeg_list.c `pkg-config --libs libavformat libavutil`
➜ FFmpeg-demo git:(master) ✗ ./list
186ffmpeg_log.c
2442build_ffmpeg_for_android.sh
4433list.c
818ffmpeg_list.c
96list.dSYM
96ffmpeg_del.dSYM
5209encode_audio.c
1051read_file.c
11151extr_video.c
11027avmerge.c
9532decode_video.c
5747cutvideo.c
8760ffmpeg_del
4265encode_video.c
8760ffmpeg_log
6500extr_audio.c
9380list
96android
1073mediainfo.c
7020decode_audio.c
541ffmpeg_file.c
5132remuxing.c
448.git
96ffmpeg_log.dSYM
803write_file.c
5066extra_audio_ffapi.c
288player

打印音视频meta信息

av_register_all
avformat_open_input
av_dump_format(fmt_ctx, 0, "./test.mp4", 0/**输入信息*/);

输入信息 填0
输入信息 填1

avformat_close_input

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
➜  FFmpeg-demo git:(master) ✗ clang -g -o mediainfo mediainfo.c `pkg-config --libs libavutil libavformat`
mediainfo.c:17:5: warning: 'av_register_all' is deprecated [-Wdeprecated-declarations]
av_register_all();
^
/usr/local/include/libavformat/avformat.h:2049:1: note: 'av_register_all' has been explicitly marked deprecated here
attribute_deprecated
^
/usr/local/include/libavutil/attributes.h:94:49: note: expanded from macro 'attribute_deprecated'
# define attribute_deprecated __attribute__((deprecated))
^
1 warning generated.
➜ FFmpeg-demo git:(master) ✗ ./mediainfo
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from './test.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: isommp42
creation_time : 2020-03-19T07:15:55.000000Z
Duration: 00:00:55.51, start: 0.000000, bitrate: 8422 kb/s
Stream #0:0(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 380 kb/s (default)
Metadata:
creation_time : 2020-03-19T07:15:55.000000Z
handler_name : Mainconcept MP4 Sound Media Handler
Stream #0:1(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], 8040 kb/s, 50 fps, 50 tbr, 50k tbn, 100 tbc (default)
Metadata:
creation_time : 2020-03-19T07:15:55.000000Z
handler_name : Mainconcept MP4 Video Media Handler
encoder : AVC Cod

抽取多媒体中的音频数据

av_init_packet(&pkt);

av_find_best_stream

av_read_frame/av_packet_unref

1
2
3
clang -g -o extr_audio  extr_audio.c `pkg-config --libs libavutil libavformat`
./extr_audio ./test.mp4 ./test.aac
ffplay test.aac

抽取多媒体中的H264视频数据

先要知道的三点:
1.将多媒体中的H264视频数据抽取后,它其实是由一帧一帧压缩后的视频帧组成的,如何区分这一帧一帧的视频帧呢?两种方法:

  • 在每一帧的长度前面加一个真的长度,当读取第一帧的时候先读取这一帧的长度,根据这一帧的长度在读取帧的数据长度,依次下去。。。
  • 在每一帧的前面加关键字(特征码),只要遇到特征码就知道这一帧开始了,上一帧结束了。

2.SPS/PPS(它只有几个字节,不会增加网络负担)
解码的视频参数,以及视频帧的宽高(也就是常说的视频分辨率),等等都是存在于SPS/PPS。

视频播放时,每次切换分辨率都要更新SPS/PPS。

而在视频直播时,在每个关键帧里面都会有一个SPS/PPS。

3.ffmpeg如何获取SPS/PPS?
codec->extradata

1
2
3
clang -g -o extr_video  extr_video.c `pkg-config --libs libavutil libavformat`
./extr_video ./test.mp4 test.h264
ffplay test.h264

mp4转flv

1
2
3
4
5
6
7
8
9
10
11
avformat_alloc_output_context2/avformat_free_context

avformat_new_stream

avcodec_parameters_copy

avformat_write_header #头

av_interleaved_write_frame #头数据

av_write_trailer #尾
1
2
3
clang -g -o remuxing  remuxing.c `pkg-config --libs  libavformat`
./remuxing ./test.mp4 test.flv
ffplay test.flv

音视频裁剪

av_seek_frame

1
2
3
clang -g -o cutvideo  cutvideo.c `pkg-config --libs  libavformat  libavcodec`
./cutvideo 10 20 ./test.mp4 cutvideo.mp4
ffplay cutvideo.mp4

FFmpeg编解码概括

类型:

  • H264解码
  • H264编码
  • AAC解码
  • AAC编码

用到的头文件:

  • libavcodec/avcodec.h

用到的结构体:

  • AVCodec编解码结构体
  • AVCodecContext 编解码器上下文
  • AVFrame 解码后的帧

结构体内存的分配和释放API:

  • av_frame_alloc/av_frame_free()
  • avcodec_alloc_context3()
  • avcodec_free_context()

解码步骤:

  • avcodec_find_decoder查找解码器
  • avcodec_open2打开解码器
  • avcodec_decode_video2解码,得到RGB或者YUV数据

H264编码

步骤:

  • avcodec_find_encoder_by_name查看编码器
  • avcodec_open2设置编码参数,并打开编码器
  • avcodec_encode_video2编码
1
2
3
4
5
➜  FFmpeg-demo git:(master) ✗ clang -g -o encode_video  encode_video.c `pkg-config --libs  libavcodec` 
➜ FFmpeg-demo git:(master) ✗ ./encode_video
Usage: ./encode_video <output file> <codec name>
➜ FFmpeg-demo git:(master) ✗ ./encode_video encode_video.h264 libx264
➜ FFmpeg-demo git:(master) ✗ ffplay encode_video.h264

视频转图片

1
2
➜  FFmpeg-demo git:(master) ✗ clang -g -o decode_video  decode_video.c `pkg-config --libs  libavformat libavutil libavcodec libswscale`
➜ FFmpeg-demo git:(master) ✗ ./decode_video ./test.mp4 ./

AAC编码

avcodec_encodec_audio2

1
2
3
clang -g -o encode_audio encode_audio.c `pkg-config --libs libavcodec`
./encode_audio encode_audio.aac
ffplay encode_audio.aac