// FFmpegDemo1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include<iostream>
#include<output>
using namespace xiuye;
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
//#include <ffmpeg/swscale.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
}
//保存的ppm文件 无法显示!!!
void SaveFrame(AVFrame* pFrame, int width, int height, int iFrame) {
FILE* pFile;
char szFilename[32];
int y;
// Open file
sprintf_s(szFilename, "frame%d.ppm", iFrame);
fopen_s(&pFile,szFilename, "wb");
if (pFile == NULL)
return;
// Write header
fprintf(pFile, "P6\n%d %d\n255\n", width, height);
// Write pixel data
for (y = 0; y < height; y++)
fwrite(pFrame->data[0] + y * pFrame->linesize[0], 1, width * 3, pFile);
// Close file
fclose(pFile);
}
int main(int argc, char* argv[]) {
//新的ffmpeg库不需要集中初始化的组建
//::av_register_all();
AVFormatContext* pFormatCtx = NULL;
//文件工作路径是项目路径 并不是输出debug 或者 release的路径OK!!!
if (avformat_open_input(&pFormatCtx, "D:/codes/windows/FFmpegDemo1/x64/Release/888.mp4", nullptr, nullptr) != 0) {
std::cout << "failed to open input" << std::endl;
return -1;
}
if (avformat_find_stream_info(pFormatCtx, nullptr) < 0) {
std::cout << "failed to find stream info" << std::endl;
return -2;
}
//if (argc < 2) {
// println("input parameters less than 2");
// return -1;
//}
println(argv[0]);
//log(argv[1]);
// Dump information about file onto standard error
av_dump_format(pFormatCtx, 0, argv[1], 0);
int i;
AVCodecContext* pCodecCtxOrig = NULL;
AVCodecParameters* pCodecCtx = NULL;
// Find the first video stream
int videoStream = -1;
for (i = 0; i < pFormatCtx->nb_streams; i++)
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStream = i;
break;
}
if (videoStream == -1)
return -1; // Didn't find a video stream
// Get a pointer to the codec context for the video stream
pCodecCtx = pFormatCtx->streams[videoStream]->codecpar;
AVCodec* pCodec = NULL;
// Find the decoder for the video stream
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
fprintf(stderr, "Unsupported codec!\n");
return -1; // Codec not found
}
// Copy context
AVCodecContext* pCodecCtx2 = avcodec_alloc_context3(pCodec);
//if (avcodec_copy_context(pCodecCtx, pCodecCtxOrig) != 0) {
//if (avcodec_parameters_to_context(pCodecCtxOrig,pCodecCtx) != 0) {//这一句有问题,原因待查!
// fprintf(stderr, "Couldn't copy codec context");
// return -1; // Error copying codec context
//}
// Open codec
if (avcodec_open2(pCodecCtx2, pCodec,nullptr) < 0)
return -1; // Could not open codec
AVFrame* pFrame = NULL;
// Allocate video frame
pFrame = av_frame_alloc();
// Allocate an AVFrame structure
AVFrame* pFrameRGB = av_frame_alloc();
if (pFrameRGB == NULL)
return -1;
uint8_t* buffer = NULL;
int numBytes;
// Determine required buffer size and allocate buffer
//numBytes = avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width,
numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width,pCodecCtx->height,1);
buffer = (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
/* avpicture_fill((AVPicture*)pFrameRGB, buffer, AV_PIX_FMT_RGB24,
pCodecCtx->width, pCodecCtx->height);*/
av_image_fill_arrays(
pFrameRGB->data,
pFrameRGB->linesize,
buffer, AV_PIX_FMT_RGB24,
pCodecCtx->width,
pCodecCtx->height,
1);
struct SwsContext* sws_ctx = NULL;
int frameFinished;
AVPacket packet;
// initialize SWS context for software scaling
sws_ctx = sws_getContext(pCodecCtx->width,
pCodecCtx->height,
AVPixelFormat(pCodecCtx->format),
pCodecCtx->width,
pCodecCtx->height,
AV_PIX_FMT_RGB24,
SWS_BILINEAR,
NULL,
NULL,
NULL
);
i = 0;
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);
frameFinished = av_read_frame(pFormatCtx, &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,
pFrameRGB->data, pFrameRGB->linesize);
// Save the frame to disk
if (++i <= 5)
SaveFrame(pFrameRGB, pCodecCtx->width,
pCodecCtx->height, i);
}
}
// Free the packet that was allocated by av_read_frame
//av_free_packet(&packet);//old
av_packet_unref(&packet);
}
// Free the RGB image
av_free(buffer);
av_free(pFrameRGB);
// Free the YUV frame
av_free(pFrame);
// Close the codecs
//av_free(pCodecCtx);
//avcodec_close(pCodecCtx);
avcodec_close(pCodecCtxOrig);
// Close the video file
avformat_close_input(&pFormatCtx);
std::cout << "Hello World!\n";
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件