#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
extern "C"
{
#include <libavcodec\avcodec.h>
#include <libavformat\avformat.h>
#include <libavutil\opt.h>
#include <libswscale\swscale.h>
}
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"swscale.lib")
int main()
{
// 创建三个文件,分别用来存放y数据,u数据,v数据
FILE* f1 = fopen("11_yuv_y.y","wb+");
FILE* f2 = fopen("11_yuv_u.y","wb+");
FILE* f3 = fopen("11_yuv_v.y","wb+");
//打印编解码器的信息
printf("%s\n",avcodec_configuration());
// 注册DLL
av_register_all();
// 初始化网络文件
avformat_network_init();
// 格式上下文
AVFormatContext* pFormat = NULL;
const char* path = "11.mp4";
//http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8
//const char* path = "http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8";
//打开网络文件用的结构体
AVDictionary* opt=NULL;
av_dict_set(&opt, "rtsp_transport", "tcp", 0); // 使用TCP协议打开网络流文件
av_dict_set(&opt, "max_delay", "550", 0); // 延迟小于550毫秒
int ret = avformat_open_input(&pFormat,path,NULL, &opt); // 打开文件
if (ret)
{
printf(" avformat_open_input failed\n");
return -1;
}
printf(" avformat_open_input success\n");
// H264 width height
ret = avformat_find_stream_info(pFormat,NULL); // 查找流信息
if (ret)
{
printf(" avformat_find_stream_info failed\n");
return -1;
}
printf(" avformat_find_stream_info success\n");
int time = pFormat->duration; // 得到视频的时长
int mbittime = (time / 1000000)/60;
int mmintime = (time / 1000000)%60;
printf("&%d·Ö:%dÃë\n", mbittime, mmintime);
av_dump_format(pFormat,NULL,path,0); // 打印视频信息 编码格式。。
//
int VideoStream = -1, AudioStream = -1;
VideoStream = av_find_best_stream(pFormat,AVMEDIA_TYPE_VIDEO,-1,-1,NULL,NULL); // 查找视频流
//AudioStream = av_find_best_stream(pFormat, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, NULL); // 查找音频流
AVCodec* vCodec = avcodec_find_decoder(pFormat->streams[VideoStream]->codec->codec_id); // 查找解码器
if (!vCodec)
{
printf(" avcodec_find_decoder failed\n");
return -1;
}
printf(" avcodec_find_decoder success\n");
ret = avcodec_open2(pFormat->streams[VideoStream]->codec, // 打开解码器
vCodec,NULL);
if (ret)
{
printf(" avcodec_open2 failed\n");
return -1;
}
printf(" avcodec_open2 success\n");
//
//
AVFrame* frame = av_frame_alloc(); // 分配内存空间
AVFrame* frameYUV = av_frame_alloc();
int width = pFormat->streams[VideoStream]->codec->width; // 将视频流的宽赋值给width
int height = pFormat->streams[VideoStream]->codec->height;
int fmt = pFormat->streams[VideoStream]->codec->pix_fmt; // 将视频流的pix_fmt复制给fmt
//
int nSize = avpicture_get_size(AV_PIX_FMT_YUV420P, // 得到YUV420P文件的大小
width, height);
uint8_t* buff = NULL;
buff =(uint8_t*)av_malloc(nSize);
avpicture_fill((AVPicture*)frameYUV, buff, AV_PIX_FMT_YUV420P, width, height);
//av_malloc µÈ¼ÛÓÚ malloc()
AVPacket* packet = (AVPacket*)av_malloc(sizeof(AVPacket));
//swsCtx = sws_getCachedContext(swsCtx,XXXX)
SwsContext * swsCtx = NULL; // 视频转换上下文
swsCtx = sws_getContext(width, height, (AVPixelFormat)fmt,
width, height, AV_PIX_FMT_YUV420P,SWS_BICUBIC,NULL,NULL,NULL);
//¶ÁÖ¡
int go = 0;
int FrameCount = 0;
while (av_read_frame(pFormat, packet)>=0) // 读取每一帧数据
{
//ÅжÏstream_index
if (packet->stream_index == AVMEDIA_TYPE_VIDEO) // 如果packet中的索引是 VIDEO 的话
{
//vCodec pFormat->streams[VideoStream]->codec
ret = avcodec_decode_video2(pFormat->streams[VideoStream]->codec,frame,&go,packet); // 进行解码
if (ret<0) // 小于0 报错停止运行
{
printf(" avcodec_decode_video2 failed\n");
return -1;
}
if (go) // 如果 等于 0 的话就继续运行
{
sws_scale(swsCtx, // 进行重采样 重采样上下文
(const uint8_t**)frame->data, //
frame->linesize,
0,
height,
frameYUV->data,
frameYUV->linesize
);
fwrite(frameYUV->data[0],1,width*height,f1); // 写入Y 数据
fwrite(frameYUV->data[1],1,width*height/4, f2); // 写入U 数据
fwrite(frameYUV->data[2],1,width*height/4, f3); // 写入V 数据
// fwrite(frameYUV->data[0],1,width*height,f1); 写入到一个文件
// fwrite(frameYUV->data[1],1,width*height,f1);
// fwrite(frameYUV->data[2],1,width*height,f1);
FrameCount++;
printf("frame index:%d \n", FrameCount++); // 给个提示 提示程序一直在跑
}
}
av_free_packet(packet); // 释放 packet
}
fclose(f1);
fclose(f2);
fclose(f3);
// fclose(f1);
sws_freeContext(swsCtx); // 释放重采样的上下文
av_frame_free(&frame); // 释放frame
av_frame_free(&frameYUV); // 释放frame
avformat_close_input(&pFormat); // 关闭格式上下文
return 0;
}
ffmpeg API 视频解码
于 2021-07-01 09:02:44 首次发布