C++可以通过调用FFmpeg的API来对H264文件进行编码和解码。下面是一个简单的例子。
首先需要在代码中包含FFmpeg的头文件:
c
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
然后需要初始化FFmpeg库:
c
av_register_all();
avformat_network_init();
对于编码,需要创建一个AVCodecContext和AVCodec:
c
AVCodec *codec;
AVCodecContext *codecContext;
codec = avcodec_find_encoder(AV_CODEC_ID_H264);
codecContext = avcodec_alloc_context3(codec);
// 设置编码参数
codecContext->codec_type = AVMEDIA_TYPE_VIDEO;
codecContext->bit_rate = 400000;
codecContext->width = 640;
codecContext->height = 480;
codecContext->time_base = (AVRational){1, 25};
codecContext->gop_size = 10;
codecContext->max_b_frames = 1;
avcodec_open2(codecContext, codec, NULL);
接下来可以将图片数据转换为AVFrame,然后进行编码:
c
AVFrame *frame;
AVPacket packet;
// 分配AVFrame对象
frame = av_frame_alloc();
frame->format = AV_PIX_FMT_YUV420P;
frame->width = codecContext->width;
frame->height = codecContext->height;
// 分配内存
av_image_alloc(frame->data, frame->linesize, codecContext->width, codecContext->height, AV_PIX_FMT_YUV420P, 1);
// 将RGB数据转换为YUV420P
struct SwsContext *swsContext;
swsContext = sws_getContext(codecContext->width, codecContext->height, AV_PIX_FMT_RGB24,
codecContext->width, codecContext->height, AV_PIX_FMT_YUV420P,
SWS_BILINEAR, NULL, NULL, NULL);
uint8_t *inputData[1] = {rgbData}; // rgbData为输入图片数据
int inputLineSize[1] = {codecContext->width * 3}; // RGB数据每行字节数
sws_scale(swsContext, inputData, inputLineSize, 0, codecContext->height, frame->data, frame->linesize);
// 编码
int gotPacket = 0;
av_init_packet(&packet);
packet.data = NULL;
packet.size = 0;
avcodec_encode_video2(codecContext, &packet, frame, &gotPacket);
对于解码,需要创建一个AVCodecContext和AVCodecParserContext:
c
AVCodec *codec;
AVCodecContext *codecContext;
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
codecContext = avcodec_alloc_context3(codec);
// 设置解码参数
avcodec_open2(codecContext, codec, NULL);
AVCodecParserContext *parserContext;
parserContext = av_parser_init(AV_CODEC_ID_H264);
接下来将输入数据(例如H264文件)分割成一帧一帧的数据,并解码:
c
uint8_t *inputData = // 输入数据
int inputSize = // 输入数据大小
while (inputSize > 0) {
int parsedSize = av_parser_parse2(parserContext, codecContext, &packet.data, &packet.size,
inputData, inputSize, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
inputSize -= parsedSize;
inputData += parsedSize;
if (packet.size > 0) {
int frameFinished = 0;
avcodec_decode_video2(codecContext, frame, &frameFinished, &packet);
if (frameFinished) {
// 处理解码后的数据
}
}
}
以上是一个简单的例子,实际使用中还需要进行一些错误处理和内存管理等操作。因此建议参考FFmpeg的官方文档和示例代码进行开发。