Ubuntu 12-04 编译ffmpeg
ffmepg版本:2.0.1
首先要安装yasm,ffmpeg中部分代码用汇编来实现,所以速度上还是比较快的。先安装 yasm,再执行 configure,最后 make和make install。
1 |
|
make install 的时候可能提示没有权限,你懂的,ubuntu下要sudo。 默认情况下的configure是不支持生成动态库的,所以上面加了–enable-shared
ffmpeg解码H264码流
-
注册支持的文件格式和编码、解码器
1
2av_register_all(); avcodec_register_all();
-
初始化网络多媒体文件格式
1
avformat_network_init();
-
打开多媒体文件
1
2AVFormatContext *input_format_context = avformat_alloc_context(); avformat_open_input(&input_format_context, media_filename, NULL, NULL);
-
获取并输出多媒体文件信息
1
2avformat_find_stream_info(input_format_context, NULL); av_dump_format(input_format_context, 0, media_filename, 0);
-
获取多媒体流/文件中的视频索引
1
2
3
4
5
6
7
8int video_stream_index = -1; for (unsigned int i = 0; i < input_format_context->nb_streams; i++) { if (input_format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { video_stream_index = i; break; } }
-
创建输出多媒体
1
2AVFormatContext *output_format_context = NULL; avformat_alloc_output_context2(&output_format_context, NULL, NULL, output_name);
-
编码器参数及时间戳参数设置
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47AVStream *stream = avformat_new_stream(output_format_context, NULL); AVCodecContext *out_codec_context = stream->codec; out_codec_context->codec_id = input_codec_context->codec_id; out_codec_context->codec_type = input_codec_context->codec_type; if (!out_codec_context->codec_tag) { unsigned int codec_tag; if ((!output_format_context->oformat->codec_tag) || (av_codec_get_id(output_format_context->oformat->codec_tag, input_codec_context->codec_tag) == out_codec_context->codec_id) || (!av_codec_get_tag2(output_format_context->oformat->codec_tag, input_codec_context->codec_id, &codec_tag))) { out_codec_context->codec_tag = input_codec_context->codec_tag; } } out_codec_context->bit_rate = input_codec_context->bit_rate; out_codec_context->rc_max_rate = input_codec_context->rc_max_rate; out_codec_context->rc_buffer_size = input_codec_context->rc_buffer_size; out_codec_context->field_order = input_codec_context->field_order; uint64_t extra_size = input_codec_context->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE; out_codec_context->extradata = av_mallocz(extra_size); memcpy(out_codec_context->extradata, input_codec_context->extradata, input_codec_context->extradata_size); out_codec_context->extradata_size= input_codec_context->extradata_size; out_codec_context->bits_per_coded_sample = input_codec_context->bits_per_coded_sample; out_codec_context->time_base = input_codec_context->time_base; out_codec_context->pix_fmt = input_codec_context->pix_fmt; out_codec_context->width = input_codec_context->width; out_codec_context->height = input_codec_context->height; out_codec_context->has_b_frames = input_codec_context->has_b_frames; output_format_context->streams[video_stream_index]->avg_frame_rate = input_format_context->streams[video_stream_index]->avg_frame_rate; out_codec_context->time_base.num *= input_codec_context->ticks_per_frame; out_codec_context->time_base.den *= 2; out_codec_context->ticks_per_frame = 2; out_codec_context->sample_aspect_ratio = input_codec_context->sample_aspect_ratio; av_dump_format(output_format_context, 0, output_name, 1);
-
打开输出视频文件
1
2
3
4
5if (!(output_format_context->flags & AVFMT_NOFILE)) { if (avio_open(&output_format_context->pb, output_name, AVIO_FLAG_WRITE) < 0) { return -1; } }
-
输出视频文件头信息
1
2
3if (avformat_write_header(output_format_context, NULL) < 0) { return -1; }
-
获取每一帧的视频数据
1
2
3AVPacket avpkt; av_read_frame(input_format_context, &avpkt); av_free_packet(&avpkt); //记得每一帧数据使用完之后要释放,否则会有内存泄漏
-
输出一帧视频信息
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
30AVPacket opkt; av_init_packet(&opkt); opkt.data = avpkt.data; opkt.size = avpkt.size; if (avpkt.pts != AV_NOPTS_VALUE) { opkt.pts = av_rescale_q(avpkt.pts, input_format_context->streams[video_stream_index]->time_base, out_codec_context->time_base); } else { opkt.pts = AV_NOPTS_VALUE; } if (avpkt.dts == AV_NOPTS_VALUE) { opkt.dts = av_rescale_q(avpkt.dts, AV_TIME_BASE_Q, out_codec_context->time_base); } else { opkt.dts = av_rescale_q(avpkt.dts, input_format_context->streams[video_stream_index]->time_base, out_codec_context->time_base); } opkt.duration = av_rescale_q(avpkt.duration, input_format_context->streams[video_stream_index]->time_base, out_codec_context->time_base); opkt.flags = avpkt.flags; av_interleaved_write_frame(output_format_context, &opkt); out_codec_context->frame_number++;
-
写入完需要的信息或者输入多媒体播放完时,要写入文件尾并关闭文件
1
2av_write_trailer(output_format_context); avio_close(output_format_context->pb);
-
释放资源
1
2
3
4
5av_free(out_codec_context->extradata); avcodec_close(input_codec_context); avcodec_close(out_codec_context); avformat_close_input(&input_format_context); avformat_free_context(output_format_context);
小结
经以上步骤,即可以获取到基于rtsp的码流(h264祼码流),得到码流后即可以根据自己的需要来处理了。我这里只是将一个支持rtsp的IPCam码流收回来作录像处理,所以在收到码流后,直接写入到相应的视频文件即可。
(注:只作使用ffmpeg接口来获取rtsp码流记录)