sudo add-apt-repository ppa:kirillshkrogalev/ffmpeg-next
sudo apt-get update
sudo apt-get install ffmpeg
sudo apt-get install libavcodec-ffmpeg-dev
1. 包含头文件,C++中,需要extern "C"起来
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h> //如果不做图像处理时,不需要包含
#include <libavutil/imgutils.h> //如果不做图像处理时,不需要包含
};
2. 声明变量
AVCodec* codec;
AVCodecParserContext *parser;
AVCodecContext* context;
AVFrame* frame;
AVPacket* pkt;
//如果需要做图像处理,比如需要转换成位图,再声明两个变量。
SwsContext* img_convert_ctx; //图像处理上下文
AVFrame* rgb_frame; //转换后的图片数据
bool is_init_output_buffer = false;
3. 初始化
int Init()
{
avcodec_register_all();
pkt = av_packet_alloc();
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec) {
fprintf(stderr, "Codec not found\n");
return -1;
}
parser = av_parser_init(codec->id);
if (!parser) {
fprintf(stderr, "parser not found\n");
return -1;
}
context = avcodec_alloc_context3(codec);
if (!context) {
fprintf(stderr, "Could not allocate video codec context\n");
exit(1);
}
if (avcodec_open2(context, codec, NULL) < 0) {
fprintf(stderr, "Could not open codec\n");
return -1;
}
frame = av_frame_alloc();
rgb_frame = av_frame_alloc();
if (!frame || !rgb_frame) {
fprintf(stderr, "Could not allocate video frame\n");
return -1;
}
}
4. 解码
int decode(unsigned char* data, int data_size)
{
while (data_size > 0) {
int ret = av_parser_parse2(parser, context, &pkt->data, &pkt->size,
data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
if (ret < 0) {
fprintf(stderr, "Error while parsing\n");
return -1;
}
data += ret;
data_size -= ret;
if (pkt->size) {
ret = avcodec_send_packet(context, pkt);
if (ret < 0) {
fprintf(stderr, "Error sending a packet for decoding\n");
return -1;
}
while (ret >= 0) {
ret = avcodec_receive_frame(context, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0) {
fprintf(stderr, "Error during decoding\n");
return -1;
}
//至此解码已经成功,下面进行YUV到RGB的转换
if (!is_init_output_buffer) {
//初试化转换后的图像数据buffer,只要初始化一次就行。
uint8_t *out_buffer = (unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_RGB24, context->width, context->height, 1));
av_image_fill_arrays(rgb_frame->data, rgb_frame->linesize, out_buffer, AV_PIX_FMT_RGB24, context->width, context->height, 1);
is_init_output_buffer = true;
}
//获取图像转换上下文
img_convert_ctx = sws_getCachedContext(img_convert_ctx, context->width, context->height,
context->pix_fmt, context->width, context->height, AV_PIX_FMT_RGB24,
SWS_X, NULL, NULL, NULL);
//图像转换
sws_scale(img_convert_ctx, frame->data, frame->linesize, 0, context->height, rgb_frame->data, rgb_frame->linesize);
//下面是3种数据的获取方式
//YUV数据
int y_size = context->width * context->height;
fwrite(rgb_frame->data[0], 1, y_size, fp_yuv); //Y
fwrite(rgb_frame->data[1], 1, y_size / 4, fp_yuv); //U
fwrite(rgb_frame->data[2], 1, y_size / 4, fp_yuv); //V
// RGB数据
fwrite(rgb_frame->data[0], (context->width) * (context->height) * 3, 1, fp);
// UYVY数据
//fwrite(rgb_frame->data[0], (context->width) * (context->height), 2, fp);
}
}
}
return 0;
}
5. 编译包含的库
LIBS += /usr/local/lib/libavcodec.a /usr/local/lib/libavutil.a /usr/local/lib/libswresample.a /usr/local/lib/libswscale.a -lz -ldl
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。