C++FFmpeg:H 264、MJPEG回転YUYV、RGB
まずコードを貼って、暇があれば補充します.
H264ToRGB
H 264はフレーム間符号化であり、AVCodecContextに連続マルチフレームフィードデータを供給してから正しく復号する必要がある.
MJPEGToRGB
MJPEGはイントラエンコーディングであり、MJPEGフレーム毎に対応するRGBフレームを復号することができる.
H264ToRGB
H 264はフレーム間符号化であり、AVCodecContextに連続マルチフレームフィードデータを供給してから正しく復号する必要がある.
void H264ToRGB(unsigned char* data, unsigned int dataSize, unsigned char* outBuffer)
{
// 1. packet
AVPacket* avPkt = av_packet_alloc();
avPkt->size = dataSize;
avPkt->data = data;
static AVCodecContext* codecCtx = nullptr;
if (codecCtx == nullptr) {
// 2. codecContext
AVCodec* h264Codec = avcodec_find_decoder(AV_CODEC_ID_H264);
codecCtx = avcodec_alloc_context3(h264Codec);
avcodec_get_context_defaults3(codecCtx, h264Codec);
avcodec_open2(codecCtx, h264Codec, nullptr);
}
// 3.
//avcodec_decode_video2(codecCtx, &outFrame, &lineLength, &avPkt); // ,
auto ret = avcodec_send_packet(codecCtx, avPkt);
if (ret >= 0) {
AVFrame* YUVFrame = av_frame_alloc();
ret = avcodec_receive_frame(codecCtx, YUVFrame);
if (ret >= 0) {
// 4.YUV RGB24
AVFrame* RGB24Frame = av_frame_alloc();
struct SwsContext* convertCxt = sws_getContext(
YUVFrame->width, YUVFrame->height, AV_PIX_FMT_YUV420P,
YUVFrame->width, YUVFrame->height, AV_PIX_FMT_RGB24,
SWS_POINT, NULL, NULL, NULL
);
// outBuffer RGB24Frame->data,AV_PIX_FMT_RGB24 RGB24Frame->data[0]
av_image_fill_arrays(
RGB24Frame->data, RGB24Frame->linesize, outBuffer,
AV_PIX_FMT_RGB24, YUVFrame->width, YUVFrame->height,
1
);
sws_scale(convertCxt, YUVFrame->data, YUVFrame->linesize, 0, YUVFrame->height, RGB24Frame->data, RGB24Frame->linesize);
// 5. /context ->
// free context and avFrame
sws_freeContext(convertCxt);
av_frame_free(&RGB24Frame);
// RGB24Frame.
}
// free context and avFrame
av_frame_free(&YUVFrame);
}
// free context and avFrame
av_packet_unref(avPkt);
av_packet_free(&avPkt);
// avcodec_free_context(&codecCtx);
}
MJPEGToRGB
MJPEGはイントラエンコーディングであり、MJPEGフレーム毎に対応するRGBフレームを復号することができる.
void MJPEGToRGB(unsigned char *data, unsigned int dataSize, unsigned char *outBuffer)
{
// 1. packet
AVPacket *avPkt = av_packet_alloc();
avPkt->size = dataSize;
avPkt->data = data;
// 2. codecContext
AVCodec *mjpegCodec = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
AVCodecContext* codecCtx = avcodec_alloc_context3(mjpegCodec);
avcodec_get_context_defaults3(codecCtx, mjpegCodec);
avcodec_open2(codecCtx, mjpegCodec, nullptr);
// 3.
//avcodec_decode_video2(codecCtx, &outFrame, &lineLength, &avPkt); // ,
auto ret = avcodec_send_packet(codecCtx, avPkt);
if (ret >=0) {
AVFrame* YUVFrame = av_frame_alloc();
ret = avcodec_receive_frame(codecCtx, YUVFrame);
if (ret >= 0) {
// 4.YUV RGB24
AVFrame* RGB24Frame = av_frame_alloc();
struct SwsContext* convertCxt = sws_getContext(
YUVFrame->width, YUVFrame->height, AV_PIX_FMT_YUV420P,
YUVFrame->width, YUVFrame->height, AV_PIX_FMT_RGB24,
SWS_POINT, NULL, NULL, NULL
);
// outBuffer RGB24Frame->data,AV_PIX_FMT_RGB24 RGB24Frame->data[0]
av_image_fill_arrays(
RGB24Frame->data, RGB24Frame->linesize, outBuffer,
AV_PIX_FMT_RGB24, YUVFrame->width, YUVFrame->height,
1
);
sws_scale(convertCxt, YUVFrame->data, YUVFrame->linesize, 0, YUVFrame->height, RGB24Frame->data, RGB24Frame->linesize);
// 5. /context ->
// free context and avFrame
sws_freeContext(convertCxt);
av_frame_free(&RGB24Frame);
// RGB24Frame.
}
// free context and avFrame
av_frame_free(&YUVFrame);
}
// free context and avFrame
av_packet_unref(avPkt);
av_packet_free(&avPkt);
avcodec_free_context(&codecCtx);
}