visual studio dav转mp4用ffmpeg的cpp代码
时间: 2023-12-20 07:07:45 浏览: 231
以下是使用FFmpeg进行DAV转MP4的C++代码示例:
```cpp
#include <iostream>
#include <string>
#define __STDC_CONSTANT_MACROS
#ifdef _WIN32
// Windows
extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/opt.h"
#include "libavutil/imgutils.h"
#include "libavutil/avutil.h"
}
#else
// Linux...
#ifdef __cplusplus
extern "C" {
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
#include <libavutil/avutil.h>
#ifdef __cplusplus
}
#endif
#endif
using namespace std;
int main(int argc, char* argv[]) {
AVFormatContext *pFormatCtx = NULL;
AVCodecContext *pCodecCtx = NULL;
AVCodec *pCodec = NULL;
AVFrame *pFrame = NULL, *pFrameRGB = NULL;
AVPacket packet;
int videoStream = -1;
int frameFinished;
int numBytes;
uint8_t* buffer = NULL;
int width, height;
string inputFilePath = "test.dav";
string outputFilePath = "test.mp4";
av_register_all();
if (avformat_open_input(&pFormatCtx, inputFilePath.c_str(), NULL, NULL) != 0) {
cout << "Couldn't open input file." << endl;
return -1;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
cout << "Couldn't find stream information." << endl;
return -1;
}
av_dump_format(pFormatCtx, 0, inputFilePath.c_str(), 0);
for (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 << "Couldn't find a video stream." << endl;
return -1;
}
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
cout << "Codec not found." << endl;
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
cout << "Could not open codec." << endl;
return -1;
}
pFrame = av_frame_alloc();
pFrameRGB = av_frame_alloc();
if (pFrameRGB == NULL) {
return -1;
}
numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);
buffer = (uint8_t*)av_malloc(numBytes * sizeof(uint8_t));
av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);
SwsContext* sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL);
AVFormatContext* pOutFormatCtx = NULL;
int ret = avformat_alloc_output_context2(&pOutFormatCtx, NULL, NULL, outputFilePath.c_str());
if (ret < 0) {
cout << "Could not allocate output format context." << endl;
return -1;
}
AVStream* pOutStream = avformat_new_stream(pOutFormatCtx, NULL);
if (!pOutStream) {
cout << "Failed allocating output stream." << endl;
return -1;
}
pOutStream->codecpar->codec_tag = 0;
avcodec_parameters_from_context(pOutStream->codecpar, pCodecCtx);
if (!(pOutFormatCtx->oformat->flags & AVFMT_NOFILE)) {
if (avio_open(&pOutFormatCtx->pb, outputFilePath.c_str(), AVIO_FLAG_WRITE) < 0) {
cout << "Could not open output file." << endl;
return -1;
}
}
ret = avformat_write_header(pOutFormatCtx, NULL);
if (ret < 0) {
cout << "Error occurred when opening output file." << endl;
return -1;
}
else {
cout << "Opened output file successfully." << endl;
}
int frameCount = 0;
while (av_read_frame(pFormatCtx, &packet) >= 0) {
if (packet.stream_index == videoStream) {
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if (frameFinished) {
sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
pFrameRGB->width = pCodecCtx->width;
pFrameRGB->height = pCodecCtx->height;
pFrameRGB->format = AV_PIX_FMT_RGB24;
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
int got_packet = 0;
AVCodecContext* pOutCodecCtx = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(pOutCodecCtx, pCodecCtx->codecpar);
pOutCodecCtx->codec_tag = 0;
pOutCodecCtx->codec_id = AV_CODEC_ID_H264;
pOutCodecCtx->width = pCodecCtx->width;
pOutCodecCtx->height = pCodecCtx->height;
pOutCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
avcodec_open2(pOutCodecCtx, pCodec, NULL);
int ret = avcodec_encode_video2(pOutCodecCtx, &pkt, pFrameRGB, &got_packet);
if (ret < 0) {
cout << "Error encoding video frame." << endl;
return -1;
}
if (got_packet) {
av_packet_rescale_ts(&pkt, pCodecCtx->time_base, pOutStream->time_base);
pkt.stream_index = pOutStream->index;
av_interleaved_write_frame(pOutFormatCtx, &pkt);
av_packet_unref(&pkt);
}
avcodec_free_context(&pOutCodecCtx);
frameCount++;
}
}
av_packet_unref(&packet);
}
av_write_trailer(pOutFormatCtx);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
if (buffer != NULL) {
av_free(buffer);
}
if (pFrameRGB != NULL) {
av_free(pFrameRGB);
}
if (pFrame != NULL) {
av_free(pFrame);
}
if (pOutFormatCtx != NULL) {
if (!(pOutFormatCtx->oformat->flags & AVFMT_NOFILE)) {
avio_close(pOutFormatCtx->pb);
}
avformat_free_context(pOutFormatCtx);
}
return 0;
}
```
需要注意的是,这里使用的是FFmpeg库,因此需要在项目中添加FFmpeg的头文件和库文件,并且需要指定FFmpeg库的链接路径。具体使用方法可以参考FFmpeg的官方文档。另外,代码中的输入文件路径和输出文件路径需要根据实际情况修改。
阅读全文