extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
#include <libswresample/swresample.h>
#include <libavutil/pixfmt.h>
#include <libswscale/swscale.h>
};
#include <opencv/cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#define MAX_AUDIO_FRAME_SIZE 192000
#define SAMPLE_PRT(fmt...) \
do {\
printf("[%s]-%d: ", __FUNCTION__, __LINE__);\
printf(fmt);\
}while(0)
//'1': Use H.264 Bitstream Filter
#define USE_H264BSF 1
void save_pnm(AVFrame *pFrame, int w, int h,int index)
{
FILE *fl;
char szFilename[32];
int y;
// Open file
sprintf(szFilename, "%d.pnm", index);
fl=fopen(szFilename, "wb");
if(fl==NULL)
return;
fprintf(fl, "P6\n%d %d\n255\n", w, h); // 加入pnm文件头
// Write pixel data
for(y=0; y<h; y++)
{
fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, w*3, fl);
}
// Close file
fclose(fl);
}
int main(int argc, char *argv[])
{
char *file_path = "/home/wangchong.wc/video/30_0.mp4";
AVFormatContext *pFormatCtx;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame, *pFrameRGB;
AVPacket *packet;
uint8_t *out_buffer;
static struct SwsContext *img_convert_ctx;
int videoStream, i, numBytes;
int ret, got_picture;
av_register_all(); //初始化FFMPEG 调用了这个才能正常适用编码器和解码器
//Allocate an AVFormatContext.
pFormatCtx = avformat_alloc_context();
if (avformat_open_input(&pFormatCtx, file_path, NULL, NULL) != 0) {
SAMPLE_PRT("open file error\n");
return -1;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
SAMPLE_PRT("Could't find stream infomation\n");
return -1;
}
videoStream = -1;
for (i = 0; i < pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStream = i;
}
}
if (videoStream == -1) {
SAMPLE_PRT("no find vedio_stream");
return -1;
}
///查找解码器
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
SAMPLE_PRT(" not found decodec.\n");
return -1;
}
///打开解码器
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
SAMPLE_PRT("Could not open decodec.");
return -1;
}
pFrame = av_frame_alloc();
pFrameRGB = av_frame_alloc();
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
numBytes = avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width,pCodecCtx->height);
// --------------------------------------------------------------------------
int size = avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
uint8_t* picture_buf = (uint8_t*)(av_malloc(size));
AVFrame* pic = av_frame_alloc();
avpicture_fill((AVPicture *) pic, picture_buf, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
// ----------------------------------------------------------------------------------------------
out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
avpicture_fill((AVPicture *) pFrameRGB, out_buffer, AV_PIX_FMT_YUV420P,
pCodecCtx->width, pCodecCtx->height);
packet = av_packet_alloc();
av_dump_format(pFormatCtx, 0, file_path, 0); //输出视频信息
int index = 0;
while (av_read_frame(pFormatCtx, packet) >=0){
if (packet->stream_index == videoStream) {
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture,packet);
if (ret < 0) {
SAMPLE_PRT("decode error.");
return -1;
}
if (got_picture) {
sws_scale(img_convert_ctx,
(uint8_t const * const *) pFrame->data,
pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data,
pFrameRGB->linesize);
//save_pnm(pFrameRGB, pCodecCtx->width,pCodecCtx->height,index++); // 保存图片
cv::Mat *pCvMat = new cv::Mat();
if (pCvMat->empty()) {
pCvMat->create(cv::Size(pCodecCtx->width, pCodecCtx->height), CV_8UC3);
}
memcpy(pCvMat->data, pFrameRGB->data[0], numBytes);
// cv::Mat mRGB(cv::Size(pCodecCtx->width, pCodecCtx->height), CV_8UC3);
// mRGB.data =(uchar*)pFrameRGB->data[0];
//mRGB.data = out_buffer;
// ---------------------------------------
int width = pCodecCtx->width, height = pCodecCtx->height;
cv::Mat tmp_img = cv::Mat::zeros( height*3/2, width, CV_8UC1 );
memcpy( tmp_img.data, pFrameRGB->data[0], width*height );
memcpy( tmp_img.data + width*height, pFrameRGB->data[1], width*height/4 );
memcpy( tmp_img.data + width*height*5/4, pFrameRGB->data[2], width*height/4 );
cv::Mat bgr;
cv::cvtColor( tmp_img, bgr, CV_YUV2BGR_I420 );
cv::imwrite("lenna_gray3.png", bgr);
pCvMat->release();
if (index++ > 0) {av_packet_unref(packet); break;} //100张
}
}
av_packet_unref(packet);
}
av_packet_free(&packet);
av_free(out_buffer);
av_frame_free(&pFrame);
av_frame_free(&pFrameRGB);
avformat_close_input(&pFormatCtx);
return 0;
}
testffmpeg+opencv
最新推荐文章于 2023-07-29 15:40:08 发布
该代码示例演示了如何使用FFmpeg库打开、解码视频文件,并将解码后的帧转换为OpenCV图像矩阵。通过`avformat_open_input`、`avcodec_open2`等函数进行文件读取和解码,然后利用`sws_scale`进行色彩空间转换,最后使用`cv::Mat`保存图像数据。整个过程涉及视频解码、色彩空间转换和OpenCV图像处理。
2万+

被折叠的 条评论
为什么被折叠?



