解码流程
using namespace std;
extern “C” {
include “libavcodec/avcodec.h”
include “libavutil/avutil.h”
include “libavutil/opt.h”
include “libavutil/channel_layout.h”
include “libavdevice/avdevice.h”
include “libswscale/swscale.h”
include “libswresample/swresample.h”
include “libavutil/samplefmt.h”
}
define V_WIDTH 640
define V_HEIGHT 480
/**
- @brief xxxx
- @param[in] width
- @param[in] height
@return AVFrame / static AVFrame create_frame(int width, int height, AVPixelFormat pix_fmt) { int ret = 0; AVFrame frame = NULL;
frame = av_frame_alloc(); if (!frame) {
printf("Error, No Memory!\n");
goto __ERROR;
}
//设置参数 frame->width = width; frame->height = height; frame->format = pix_fmt;
//alloc inner memory ret = av_frame_get_buffer(frame, 32); //按32位对齐 【视频必须是32位对齐】 if (ret < 0) {
printf("Error, Failed to alloc buffer for frame!\n");
goto __ERROR;
}
return frame; __ERROR: if (frame) {
av_frame_free(&frame);
} return NULL; }
static int open_decoder(int width, int height, AVCodecContext* enc_ctx) { int ret = 0; AVCodec codec = NULL;
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec)
{
printf("Codec libx264 not found\n");
exit(1);
}
*enc_ctx = avcodec_alloc_context3(codec);
if (!enc_ctx)
{
printf("Counld out allocate video codec context\n\n");
exit(1);
}
//设置分辨率
(*enc_ctx)->width = width;
(*enc_ctx)->height = height;
//YUV格式
(*enc_ctx)->pix_fmt = AV_PIX_FMT_YUV420P;
ret = avcodec_open2((*enc_ctx), codec, NULL);
if (ret < 0)
{
//printf("Counld not open codec: %s\n", av_err2str(ret));
printf("Counld not open codec: %d\n", ret);
exit(1);
}
}
int main() { int ret = 0; const char out_filename = “yuv420.yuv”; string in_filename = “out.h264”; AVFormatContext fmt_ctx = NULL; AVPacket pkt = NULL; AVCodecContext codec_ctx = NULL; AVFrame frame = NULL; FILE yuv_outfile = NULL;
yuv_outfile = fopen(out_filename, "wb+");
ret = avformat_open_input(&fmt_ctx, in_filename.c_str(), NULL, NULL);
if (ret != 0)
{
printf("ERROR, Failed to open file :%s!\n", in_filename.c_str());
goto ERROR__;
}
//打开解码器
open_decoder(V_WIDTH, V_HEIGHT, &codec_ctx);
pkt = av_packet_alloc();
av_init_packet(pkt);
frame = create_frame(V_WIDTH, V_HEIGHT, AV_PIX_FMT_YUV420P);
if (!frame)
{
printf("ERROR. Failed to create frame!\n");
goto ERROR__;
}
while (!av_read_frame(fmt_ctx, pkt))
{
//av_parse_parse2();
int ret = avcodec_send_packet(codec_ctx, pkt);
if (ret < 0)
{
}
while (ret >= 0)
{
ret = avcodec_receive_frame(codec_ctx, frame);
//编码器数据不足时,返回EAGAIN,或者到数据结尾时返回AVERROR_EOF
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
if (ret < 0) {
printf("error, failed to encode.\n");
exit(1);
}
//outfile输出h264的编码
fwrite(frame->data[0], 1, V_WIDTH*V_HEIGHT, yuv_outfile);
fwrite(frame->data[1], 1, V_WIDTH*V_HEIGHT/4, yuv_outfile);
fwrite(frame->data[2], 1, V_WIDTH*V_HEIGHT/4, yuv_outfile);
}
av_packet_unref(pkt);//减少newpkt的引用计数
av_init_packet(pkt);
}
ERROR__: if (frame) { av_frame_free(&frame); frame = NULL; } if (pkt) { av_packet_free(&pkt); pkt = NULL; } std::cout << “Hello World!\n”;
return 0;
}
```