【音视频】FFmpeg打开视频 | 保存图片
1、初始化FFmpeg
av_register_all(); //初始化FFMPEG 调用了这个才能正常使用编码器和解码器
但是这个函数如今已经没什么用了,它的就是把你定义和系统初始化的编码器和解码器连接起来而已,然后就没有了。
现在解码器和编码器的初始化都是通过定义全局变量来初始化的。与原来相比,唯一的改变就是使用数组替换链表完成解码器和编码器的初始化。
2、分配一个AVFormatContext,FFMPEG所有的操作都要通过这个AVFormatContext数据结构来进行
AVFormatContext *pFormatCtx = avformat_alloc_context();
AVFormatContext是一个贯穿始终的数据结构,很多函数都要用到它作为参数。
此结构包含了一个视频流的格式内容:AVInputFormat(or AVOutputFormat同一时间AVFormatContext内只能存在其中一个),和AVStream、AVPacket这几个重要的数据结构以及一些其他的相关信息,比如title,author,copyright等。还有一些可能在编解码中会用到的信息,诸如:duration, file_size, bit_rate等。
3、打开视频文件:
char *file_path = "./movie/ifwithoutu.mp4"; avformat_open_input(&pFormatCtx, file_path, NULL, NULL);
4、视频打开之后,查找文件中的视频流
///循环查找视频中包含的流信息,直到找到视频类型的流 ///便将其记录下来 保存到videoStream变量中 ///这里我们现在只处理视频流 音频流先不管他 for (i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; } } ///如果videoStream为-1 说明没有找到视频流 if (videoStream == -1) { printf("Didn't find a video stream."); return -1; }
5、根据视频流,打开一个解码器来解码
///查找解码器 pCodecCtx = pFormatCtx->streams[videoStream]->codec; pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if (pCodec == NULL) { printf("Codec not found."); return -1; } ///打开解码器 if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { printf("Could not open codec."); return -1; }
FFmpeg可以让我们根据查找到的视频流信息获取到解码器,不需要知道实际用到的是什么解码器
6、读取视频
int y_size = pCodecCtx->width * pCodecCtx->height; AVPacket *packet = (AVPacket *) malloc(sizeof(AVPacket)); //分配一个packet av_new_packet(packet, y_size); //分配packet的数据 if (av_read_frame(pFormatCtx, packet) < 0) { break; //这里认为视频读取完了 }
av_read_frame读取的是一帧视频,并存入一个AVPacket的结构中
7、视频里的数据是经过编码压缩的,需要将其解码
if (packet->stream_index == videoStream) { ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture,packet); if (ret < 0) { printf("decode error."); return -1; } }
8、解码器解码之后得到的图像数据都是YUV420格式的,需要将其保存成图片文件,因此需要转换为RGB格式
if (got_picture) { sws_scale( img_convert_ctx, (uint8_t const * const *) pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize
); }
9、将RGB图片写入
SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, index++
);
错误:
(1):改成 AV_PIX_FMT_RGB24