cpp dav转mp4 ffmpeg库代码
时间: 2023-10-17 09:08:12 浏览: 43
以下是使用FFmpeg库将DAV文件转换为MP4文件的C++代码示例:
```cpp
#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
int main(int argc, char* argv[])
{
AVFormatContext* pFormatCtx = nullptr;
AVCodecContext* pCodecCtx = nullptr;
AVCodec* pCodec = nullptr;
AVPacket packet;
AVFrame* pFrame = nullptr;
AVFrame* pFrameRGB = nullptr;
if (argc < 3)
{
std::cout << "Usage: " << argv[0] << " <input.dav> <output.mp4>" << std::endl;
return 1;
}
const std::string inputFileName = argv[1];
const std::string outputFileName = argv[2];
// Register all formats and codecs
av_register_all();
// Open input file
if (avformat_open_input(&pFormatCtx, inputFileName.c_str(), nullptr, nullptr) != 0)
{
std::cerr << "Could not open input file: " << inputFileName << std::endl;
return 1;
}
// Retrieve stream information
if (avformat_find_stream_info(pFormatCtx, nullptr) < 0)
{
std::cerr << "Could not find stream information" << std::endl;
return 1;
}
// Find the first video stream
int videoStreamIndex = -1;
for (unsigned int i = 0; i < pFormatCtx->nb_streams; ++i)
{
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoStreamIndex = i;
break;
}
}
if (videoStreamIndex == -1)
{
std::cerr << "Could not find video stream" << std::endl;
return 1;
}
// Get a pointer to the codec context for the video stream
pCodecCtx = avcodec_alloc_context3(nullptr);
if (!pCodecCtx)
{
std::cerr << "Failed to allocate codec context" << std::endl;
return 1;
}
if (avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoStreamIndex]->codecpar) < 0)
{
std::cerr << "Failed to copy codec parameters to codec context" << std::endl;
return 1;
}
// Find the decoder for the video stream
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (!pCodec)
{
std::cerr << "Failed to find codec" << std::endl;
return 1;
}
// Open codec
if (avcodec_open2(pCodecCtx, pCodec, nullptr) < 0)
{
std::cerr << "Failed to open codec" << std::endl;
return 1;
}
// Allocate video frames
pFrame = av_frame_alloc();
if (!pFrame)
{
std::cerr << "Failed to allocate frame" << std::endl;
return 1;
}
pFrameRGB = av_frame_alloc();
if (!pFrameRGB)
{
std::cerr << "Failed to allocate RGB frame" << std::endl;
return 1;
}
// Determine required buffer size and allocate buffer
const int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 16);
uint8_t* buffer = static_cast<uint8_t*>(av_malloc(numBytes * sizeof(uint8_t)));
// Assign appropriate parts of buffer to image planes in pFrameRGB
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVPicture
av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);
// Allocate SwsContext for RGB conversion
SwsContext* swsCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
// Open output file
AVFormatContext* pOutFormatCtx = nullptr;
if (avformat_alloc_output_context2(&pOutFormatCtx, nullptr, nullptr, outputFileName.c_str()) < 0)
{
std::cerr << "Failed to allocate output format context" << std::endl;
return 1;
}
AVOutputFormat* outputFormat = pOutFormatCtx->oformat;
// Open output file for writing
if (!(outputFormat->flags & AVFMT_NOFILE))
{
if (avio_open(&pOutFormatCtx->pb, outputFileName.c_str(), AVIO_FLAG_WRITE) < 0)
{
std::cerr << "Failed to open output file" << std::endl;
return 1;
}
}
// Write output file header
if (avformat_write_header(pOutFormatCtx, nullptr) < 0)
{
std::cerr << "Failed to write header to output file" << std::endl;
return 1;
}
// Write video stream to output file
AVStream* pOutStream = avformat_new_stream(pOutFormatCtx, nullptr);
if (!pOutStream)
{
std::cerr << "Failed to allocate output stream" << std::endl;
return 1;
}
if (avcodec_parameters_copy(pOutStream->codecpar, pCodecCtx->codecpar) < 0)
{
std::cerr << "Failed to copy codec parameters to output stream" << std::endl;
return 1;
}
pOutStream->codecpar->codec_tag = 0;
// Encode frames and write to output file
int frameCount = 0;
while (av_read_frame(pFormatCtx, &packet) >= 0)
{
// Is this a packet from the video stream?
if (packet.stream_index == videoStreamIndex)
{
// Decode the video frame
int response = avcodec_send_packet(pCodecCtx, &packet);
if (response < 0)
{
std::cerr << "Failed to decode packet" << std::endl;
return 1;
}
while (response >= 0)
{
response = avcodec_receive_frame(pCodecCtx, pFrame);
if (response == AVERROR(EAGAIN) || response == AVERROR_EOF)
{
break;
}
else if (response < 0)
{
std::cerr << "Failed to decode frame" << std::endl;
return 1;
}
// Convert the image from its native format to RGB
sws_scale(swsCtx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
// Write the converted frame to the output file
AVPacket outPacket;
av_init_packet(&outPacket);
outPacket.data = nullptr;
outPacket.size = 0;
int response = avcodec_send_frame(pCodecCtx, pFrameRGB);
if (response < 0)
{
std::cerr << "Failed to send frame for encoding" << std::endl;
return 1;
}
while (response >= 0)
{
response = avcodec_receive_packet(pCodecCtx, &outPacket);
if (response == AVERROR(EAGAIN) || response == AVERROR_EOF)
{
break;
}
else if (response < 0)
{
std::cerr << "Failed to encode packet" << std::endl;
return 1;
}
outPacket.stream_index = pOutStream->index;
av_interleaved_write_frame(pOutFormatCtx, &outPacket);
av_packet_unref(&outPacket);
}
++frameCount;
}
}
av_packet_unref(&packet);
}
// Write output file trailer
av_write_trailer(pOutFormatCtx);
// Clean up resources
avcodec_free_context(&pCodecCtx);
avformat_close_input(&pFormatCtx);
av_frame_free(&pFrame);
av_frame_free(&pFrameRGB);
av_free(buffer);
avio_close(pOutFormatCtx->pb);
avformat_free_context(pOutFormatCtx);
sws_freeContext(swsCtx);
std::cout << "Converted " << frameCount << " frames." << std::endl;
return 0;
}
```
注意,这段代码依赖于FFmpeg库,需要在编译时将其链接到可执行文件中。例如,在Linux系统中,可以使用以下命令进行编译:
```bash
g++ -o dav_to_mp4 dav_to_mp4.cpp -lavcodec -lavformat -lavutil -lswscale
```
其中,`dav_to_mp4.cpp`是上面的代码文件名称。在Windows系统中,也可以使用类似的命令进行编译,只是链接的库文件名称可能不同。