FFmpeg如何下载,简介,如何使用:
雷神代码用的FFmpeg版本比较老,在编译的时候一直弹被声明无效,这里将函数换成新的。
// FFmpegTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#define __SIDC_CONSTANT_MACROS
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
}
int main()
{
AVFormatContext* pFormatCtx;
int i, videoindex;
AVCodecContext* pCodeccCxt;
AVCodec* pCodec;
uint8_t* out_buffer;
AVPacket* packet;
AVFrame* pFrame, * pFrameYUV;
int y_size;
int ret, got_picture;
struct SwsContext* img_convert_ctx;
//输入文件路径
char filepath[] = "Titanic.ts";
int frame_cnt;
avformat_network_init();
pFormatCtx = avformat_alloc_context();//分配一个 AVFormatContext
int rets = avformat_open_input(&pFormatCtx, filepath, NULL, NULL);
if ( rets!= 0)
{
printf("Couldn't open input stream.rets = %d\r\n", rets);
return 0;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
printf("Couldn't find stream information.\n");
return -1;
}
videoindex = -1;
for (i = 0; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoindex = i;
break;
}
}
if (videoindex == -1) {
printf("Didn't find a video stream.\n");
return -1;
}
pCodeccCxt = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(pCodeccCxt, pFormatCtx->streams[videoindex]->codecpar);
pCodec = avcodec_find_decoder(pCodeccCxt->codec_id);//查找解码器
if (pCodec == NULL)
{
printf("Didn't find a video stream.\n");
return -1;
}
if (avcodec_open2(pCodeccCxt, pCodec, NULL) < 0) {
printf("Couldn't open codec.\n");
return -1;
}
pFrame = av_frame_alloc();
pFrameYUV = av_frame_alloc();
out_buffer = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodeccCxt->width, pCodeccCxt->height,1));
//ptr指向的数据填充到picture内,但并没有拷贝,只是将picture结构内的data指针指向了ptr的数据。
av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize,out_buffer, AV_PIX_FMT_YUV420P, pCodeccCxt->width, pCodeccCxt->height,1);
packet = (AVPacket*)av_malloc(sizeof(AVPacket));
printf("--------------- File Information ----------------\n");
av_dump_format(pFormatCtx, 0, filepath, 0);
printf("-------------------------------------------------\n");
img_convert_ctx = sws_getContext(pCodeccCxt->width, pCodeccCxt->height, pCodeccCxt->pix_fmt,
pCodeccCxt->width, pCodeccCxt->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
FILE* pfileYUV;
fopen_s(&pfileYUV, "fileYUV.yuv", "wb+");
FILE* pfileH264;
fopen_s(&pfileH264,"fileH264.h264", "wb+");
frame_cnt = 0;
while (av_read_frame(pFormatCtx,packet) >= 0)//packet存放
{
if (packet->stream_index == videoindex)
{
/*
* 在此处添加输出H264码流的代码
* 取自于packet,使用fwrite()
*/
fwrite(packet->data, packet->size, 1, pfileH264);
int ret = avcodec_send_packet(pCodeccCxt, packet);
if (ret < 0)
{
printf("Decode Error.\n");
return -1;
}
while(avcodec_receive_frame(pCodeccCxt, pFrame) == 0) {
//读取到一帧音频或者视频
//处理解码后音视频 frame
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodeccCxt->height,
pFrameYUV->data, pFrameYUV->linesize);
printf("Decoded frame index: %d\n", frame_cnt);
/*
* 在此处添加输出YUV的代码
* 取自于pFrameYUV,使用fwrite()
*/
fwrite(pFrameYUV->data[0], pCodeccCxt->width * pCodeccCxt->height, 1, pfileYUV);
fwrite(pFrameYUV->data[1], pCodeccCxt->width * pCodeccCxt->height/4, 1, pfileYUV);
fwrite(pFrameYUV->data[2], pCodeccCxt->width * pCodeccCxt->height/4, 1, pfileYUV);
frame_cnt++;
av_packet_unref(packet);
}
}
}
sws_freeContext(img_convert_ctx);
fclose(pfileH264);
fclose(pfileYUV);
av_frame_free(&pFrameYUV);
av_frame_free(&pFrame);
avcodec_close(pCodeccCxt);
avformat_close_input(&pFormatCtx);
return 0;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件