av_dump_format() 打印关于输入或输出格式的详细信息,例如持续时间,比特率,流,容器,程序,元数据,边数据,编解码器和时基。其中最后一个参数is_output选择输出或是输入,最后一个参数填0,打印输入流,最后一个参数填1,打印输出流。
#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()
{
//定义文件名称
FILE* f1 = fopen("www_y.yuv", "wb+");
FILE* f2 = fopen("www_u.yuv", "wb+");
FILE* f3 = fopen("www_v.yuv", "wb+");
//测试DLL库是否成功
printf("%s/n", avcodec_configuration());
//注册DLL
av_register_all();
//网络
avformat_network_init();
AVFormatContext* pFormat = NULL;
const char* path = "22.mp4";
//打开视频文件
int ret = avformat_open_input(&pFormat, path, NULL, NULL);
if (ret) {
printf("打开文件失败\n");
return -1;
}
printf("打开文件成功\n");
//寻找流信息
ret = avformat_find_stream_info(pFormat, NULL);
if (ret) {
printf("打开流失败\n");
return -1;
}
printf("打开流成功\n");
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);
//解码器
AVCodec* vCodec = avcodec_find_decoder(pFormat->streams[VideoStream]->codec->codec_id);
if (!vCodec) {
printf("vCodec失败\n");
return -1;
}
printf("vCodec成功\n");
//打开解码器
ret = avcodec_open2(pFormat->streams[VideoStream]->codec, vCodec, NULL);
if (ret) {
printf("解码器打开失败\n");
return -1;
}
printf("解码器打开成功\n");
//解码视频
//创建帧空间
AVFrame* frame = av_frame_alloc();
AVFrame* frameYUV = av_frame_alloc();
//拿取视频宽高
int width = pFormat->streams[VideoStream]->codec->width;
int height = pFormat->streams[VideoStream]->codec->height;
printf("%d\n", width);
printf("%d\n", height);
int fmt = pFormat->streams[VideoStream]->codec->pix_fmt;
//分配空间 进行图像转换
int nSize = avpicture_get_size(AV_PIX_FMT_YUV420P, width, height);
uint8_t* buff = NULL;
buff = (uint8_t*)av_malloc(nSize);
//一帧图像
avpicture_fill((AVPicture*)frameYUV, buff, AV_PIX_FMT_YUV420P, width, height);
AVPacket* packet = (AVPacket*)av_malloc(sizeof(AVPacket));
//转换上下文
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){
if (packet->stream_index == AVMEDIA_TYPE_VIDEO) {
ret = avcodec_decode_video2(pFormat->streams[VideoStream]->codec, frame, &go, packet);
if (ret < 0) {
printf("读帧失败\n");
return -1;
}
if (go) {
//裁剪
sws_scale(swsCtx, (const uint8_t**)frame->data, frame->linesize,
0, height, frameYUV->data, frameYUV->linesize);
//写入
fwrite(frameYUV->data[0], 1, width * height, f1);
fwrite(frameYUV->data[1], 1, width * height/4, f2);
fwrite(frameYUV->data[2], 1, width * height/4, f3);
FrameCount++;
printf("帧数据:%d\n", FrameCount);
}
}
//清除packet数据
av_free_packet(packet);
}
//关闭及释放空间
fclose(f1);
fclose(f2);
fclose(f3);
sws_freeContext(swsCtx);
av_frame_free(&frame);
av_frame_free(&frameYUV);
avformat_close_input(&pFormat);
return 0;
}