ffmpeg dav转mp4 cpp示例
时间: 2023-10-08 10:13:44 浏览: 137
使用ffmpeg进行视频格式转换的简单例子.docx
以下是将dav文件转换为mp4文件的示例代码,使用了FFmpeg库:
```cpp
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstdio>
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libavutil/error.h>
}
using namespace std;
int main(int argc, char* argv[])
{
AVFormatContext* pFormatCtx = NULL;
AVCodecContext* pCodecCtxOrig = NULL;
AVCodecContext* pCodecCtx = NULL;
AVCodec* pCodec = NULL;
AVFrame* pFrame = NULL;
AVPacket* packet = NULL;
int videoStream = -1;
int frameFinished = 0;
int numBytes;
uint8_t* buffer = NULL;
struct SwsContext* sws_ctx = NULL;
if (argc != 3)
{
cout << "Usage: " << argv[0] << " <input_file.dav> <output_file.mp4>" << endl;
return 1;
}
// Register all formats and codecs
av_register_all();
// Open input file
if (avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) != 0)
{
cout << "Could not open input file: " << argv[1] << endl;
return 1;
}
// Retrieve stream information
if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
{
cout << "Could not retrieve stream information" << endl;
return 1;
}
// Dump information about file onto standard error
av_dump_format(pFormatCtx, 0, argv[1], 0);
// Find the first video stream
for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoStream = i;
break;
}
}
if (videoStream == -1)
{
cout << "Could not find a video stream" << endl;
return 1;
}
// Get a pointer to the codec context for the video stream
pCodecCtxOrig = pFormatCtx->streams[videoStream]->codec;
// Find the decoder for the video stream
pCodec = avcodec_find_decoder(pCodecCtxOrig->codec_id);
if (pCodec == NULL)
{
cout << "Unsupported codec" << endl;
return 1;
}
// Copy context
pCodecCtx = avcodec_alloc_context3(pCodec);
if (avcodec_copy_context(pCodecCtx, pCodecCtxOrig) != 0)
{
cout << "Could not copy codec context" << endl;
return 1;
}
// Open codec
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
cout << "Could not open codec" << endl;
return 1;
}
// Allocate video frame
pFrame = av_frame_alloc();
// Allocate an AVPacket
packet = av_packet_alloc();
// Determine required buffer size and allocate buffer
numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width,
pCodecCtx->height, 32);
buffer = (uint8_t*)av_malloc(numBytes * sizeof(uint8_t));
// Assign appropriate parts of buffer to image planes in pFrameRGB
av_image_fill_arrays(pFrame->data, pFrame->linesize, buffer,
AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);
// Initialize SWS context for software scaling
sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
AV_PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL);
// Open output file
FILE* f = fopen(argv[2], "wb");
if (f == NULL)
{
cout << "Could not open output file: " << argv[2] << endl;
return 1;
}
// Write header
AVFormatContext* pOutFormatCtx = NULL;
avformat_alloc_output_context2(&pOutFormatCtx, NULL, NULL, argv[2]);
AVOutputFormat* pOutputFmt = pOutFormatCtx->oformat;
if (pOutputFmt->video_codec == AV_CODEC_ID_NONE)
{
cout << "Output format does not support video encoding" << endl;
return 1;
}
AVStream* pOutStream = avformat_new_stream(pOutFormatCtx, NULL);
if (pOutStream == NULL)
{
cout << "Failed to allocate output stream" << endl;
return 1;
}
AVCodecContext* pOutCodecCtx = avcodec_alloc_context3(NULL);
if (pOutCodecCtx == NULL)
{
cout << "Failed to allocate output codec context" << endl;
return 1;
}
pOutCodecCtx->codec_id = pOutputFmt->video_codec;
pOutCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
pOutCodecCtx->width = pCodecCtx->width;
pOutCodecCtx->height = pCodecCtx->height;
pOutCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
pOutCodecCtx->time_base = pCodecCtx->time_base;
if (pOutFormatCtx->oformat->flags & AVFMT_GLOBALHEADER)
{
pOutCodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
AVCodec* pOutCodec = avcodec_find_encoder(pOutCodecCtx->codec_id);
if (pOutCodec == NULL)
{
cout << "Failed to find encoder for output codec" << endl;
return 1;
}
if (avcodec_open2(pOutCodecCtx, pOutCodec, NULL) < 0)
{
cout << "Failed to open output codec" << endl;
return 1;
}
if (avcodec_parameters_from_context(pOutStream->codecpar, pOutCodecCtx) < 0)
{
cout << "Failed to copy codec parameters to output stream" << endl;
return 1;
}
av_dump_format(pOutFormatCtx, 0, argv[2], 1);
if (!(pOutputFmt->flags & AVFMT_NOFILE))
{
if (avio_open(&pOutFormatCtx->pb, argv[2], AVIO_FLAG_WRITE) < 0)
{
cout << "Failed to open output file" << endl;
return 1;
}
}
if (avformat_write_header(pOutFormatCtx, NULL) < 0)
{
cout << "Failed to write header to output file" << endl;
return 1;
}
int frameCount = 0;
int got_picture;
// Read frames and write to file
while (av_read_frame(pFormatCtx, packet) >= 0)
{
// Is this a packet from the video stream?
if (packet->stream_index == videoStream)
{
// Decode video frame
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, packet);
// Did we get a video frame?
if (frameFinished)
{
// Convert the image from its native format to RGB
sws_scale(sws_ctx, (uint8_t const* const*)pFrame->data,
pFrame->linesize, 0, pCodecCtx->height, pFrame->data,
pFrame->linesize);
// Encode the RGB image to the output format
AVPacket avpkt;
av_init_packet(&avpkt);
avpkt.data = NULL;
avpkt.size = 0;
avcodec_encode_video2(pOutCodecCtx, &avpkt, pFrame, &got_picture);
if (got_picture)
{
avpkt.stream_index = pOutStream->index;
av_write_frame(pOutFormatCtx, &avpkt);
av_packet_unref(&avpkt);
}
frameCount++;
}
}
// Free the packet that was allocated by av_read_frame
av_packet_unref(packet);
}
// Write trailer
av_write_trailer(pOutFormatCtx);
// Clean up
fclose(f);
avcodec_close(pCodecCtx);
avcodec_close(pOutCodecCtx);
av_free(pCodecCtx);
av_free(pFrame);
av_free(buffer);
avformat_close_input(&pFormatCtx);
avformat_free_context(pOutFormatCtx);
av_packet_free(&packet);
return 0;
}
```
需要注意的是,此示例中的编码器使用的是H264,如果您需要使用其他编码器,则需要相应更改代码。
此外,为了支持输出MP4格式,您还需要安装FFmpeg的依赖库x264和libfdk_aac,以及将FFmpeg编译时配置为包括这些库。
阅读全文