c++中使用解码器将mp4文件转化为avi文件
时间: 2023-06-17 11:05:14 浏览: 268
c++ bmp2avi
要将MP4文件转换为AVI文件,您需要使用视频编解码器和音频编解码器将MP4文件解码为原始视频和音频流,然后使用AVI编码器将它们重新编码为AVI格式。以下是C++中使用FFmpeg解码器将MP4文件转换为AVI文件的示例代码:
```cpp
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
using namespace std;
int main(int argc, char *argv[])
{
AVFormatContext *pFormatCtx = NULL;
AVCodecContext *pCodecCtx = NULL;
AVCodec *pCodec = NULL;
AVFrame *pFrame = NULL;
AVPacket packet;
int videoStream, numBytes;
uint8_t *buffer = NULL;
struct SwsContext *sws_ctx = NULL;
AVOutputFormat *pOutputFormat = NULL;
AVFormatContext *pOutputFormatCtx = NULL;
AVStream *pOutStream = NULL;
AVCodecContext *pOutCodecCtx = NULL;
AVCodec *pOutCodec = NULL;
uint8_t *outBuffer = NULL;
int outBufferSize;
int frameFinished;
int width, height, fps, bitrate;
if (argc < 3)
{
cout << "Usage: " << argv[0] << " input.mp4 output.avi" << endl;
return -1;
}
av_register_all();
if (avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) != 0)
{
cout << "Error: Couldn't open input file." << endl;
return -1;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
{
cout << "Error: Couldn't find stream information." << endl;
return -1;
}
av_dump_format(pFormatCtx, 0, argv[1], 0);
videoStream = -1;
for (int i = 0; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoStream = i;
break;
}
}
if (videoStream == -1)
{
cout << "Error: Couldn't find video stream." << endl;
return -1;
}
pCodecCtx = avcodec_alloc_context3(NULL);
if (pCodecCtx == NULL)
{
cout << "Error: Couldn't allocate codec context." << endl;
return -1;
}
if (avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoStream]->codecpar) < 0)
{
cout << "Error: Couldn't copy codec parameters to codec context." << endl;
return -1;
}
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL)
{
cout << "Error: Couldn't find codec." << endl;
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
cout << "Error: Couldn't open codec." << endl;
return -1;
}
pFrame = av_frame_alloc();
if (pFrame == NULL)
{
cout << "Error: Couldn't allocate frame." << endl;
return -1;
}
numBytes = av_image_get_buffer_size(AV_PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height, 1);
buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
av_image_fill_arrays(pFrame->data, pFrame->linesize, buffer, AV_PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height, 1);
pOutputFormat = av_guess_format("avi", NULL, NULL);
if (pOutputFormat == NULL)
{
cout << "Error: Couldn't guess output format." << endl;
return -1;
}
if (avformat_alloc_output_context2(&pOutputFormatCtx, pOutputFormat, NULL, argv[2]) < 0)
{
cout << "Error: Couldn't allocate output context." << endl;
return -1;
}
pOutCodec = avcodec_find_encoder(pOutputFormat->video_codec);
if (pOutCodec == NULL)
{
cout << "Error: Couldn't find output codec." << endl;
return -1;
}
pOutStream = avformat_new_stream(pOutputFormatCtx, pOutCodec);
if (pOutStream == NULL)
{
cout << "Error: Couldn't allocate output stream." << endl;
return -1;
}
pOutCodecCtx = avcodec_alloc_context3(pOutCodec);
if (pOutCodecCtx == NULL)
{
cout << "Error: Couldn't allocate output codec context." << endl;
return -1;
}
width = pCodecCtx->width;
height = pCodecCtx->height;
fps = (int)round(av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate));
bitrate = pCodecCtx->bit_rate;
pOutCodecCtx->codec_tag = 0;
pOutCodecCtx->codec_id = pOutputFormat->video_codec;
pOutCodecCtx->bit_rate = bitrate;
pOutCodecCtx->width = width;
pOutCodecCtx->height = height;
pOutCodecCtx->time_base.num = 1;
pOutCodecCtx->time_base.den = fps;
pOutCodecCtx->gop_size = 10;
pOutCodecCtx->max_b_frames = 1;
pOutCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
if (pOutputFormatCtx->oformat->flags & AVFMT_GLOBALHEADER)
{
pOutCodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
if (avcodec_open2(pOutCodecCtx, pOutCodec, NULL) < 0)
{
cout << "Error: Couldn't open output codec." << endl;
return -1;
}
if (avcodec_parameters_from_context(pOutStream->codecpar, pOutCodecCtx) < 0)
{
cout << "Error: Couldn't copy codec parameters to output stream." << endl;
return -1;
}
av_dump_format(pOutputFormatCtx, 0, argv[2], 1);
if (!(pOutputFormat->flags & AVFMT_NOFILE))
{
if (avio_open(&pOutputFormatCtx->pb, argv[2], AVIO_FLAG_WRITE) < 0)
{
cout << "Error: Couldn't open output file." << endl;
return -1;
}
}
if (avformat_write_header(pOutputFormatCtx, NULL) < 0)
{
cout << "Error: Couldn't write output file header." << endl;
return -1;
}
sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pOutCodecCtx->width, pOutCodecCtx->height, pOutCodecCtx->pix_fmt, SWS_BILINEAR, NULL, NULL, NULL);
while (av_read_frame(pFormatCtx, &packet) >= 0)
{
if (packet.stream_index == videoStream)
{
avcodec_send_packet(pCodecCtx, &packet);
while (avcodec_receive_frame(pCodecCtx, pFrame) == 0)
{
sws_scale(sws_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrame->data, pFrame->linesize);
pFrame->width = pOutCodecCtx->width;
pFrame->height = pOutCodecCtx->height;
pFrame->format = pOutCodecCtx->pix_fmt;
av_init_packet(&packet);
if (avcodec_send_frame(pOutCodecCtx, pFrame) >= 0)
{
while (avcodec_receive_packet(pOutCodecCtx, &packet) == 0)
{
av_packet_rescale_ts(&packet, pOutCodecCtx->time_base, pOutStream->time_base);
packet.stream_index = pOutStream->index;
av_write_frame(pOutputFormatCtx, &packet);
av_packet_unref(&packet);
}
}
}
}
av_packet_unref(&packet);
}
av_write_trailer(pOutputFormatCtx);
if (pOutCodecCtx != NULL)
{
avcodec_close(pOutCodecCtx);
avcodec_free_context(&pOutCodecCtx);
}
if (pOutStream != NULL)
{
avcodec_parameters_free(&pOutStream->codecpar);
avformat_free_context(pOutputFormatCtx);
}
if (pFrame != NULL)
{
av_frame_free(&pFrame);
av_free(buffer);
}
avcodec_close(pCodecCtx);
avcodec_free_context(&pCodecCtx);
avformat_close_input(&pFormatCtx);
avformat_free_context(pFormatCtx);
return 0;
}
```
该代码使用FFmpeg库进行解码和编码,并将最终的AVI文件写入磁盘。请注意,该代码可能需要进行一些调整以适应您的输入视频文件。
阅读全文