视频解码后格式转换
YUV->RGBA
#include <iostream>
#include <thread>
extern "C" {
#include "libavutil/avutil.h"
#include "libavcodec/avcodec.h "
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
}
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "swscale.lib")
#pragma warning(disable:4996)
using namespace std;
void Xsleep(int ms)
{
chrono::milliseconds du(ms);
this_thread::sleep_for(du);
}
static double r2d(AVRational in)
{
return (in.den == 0) ? 0 : ((double)in.num / (double)in.den);
}
int main()
{
av_register_all();
avformat_network_init();
avcodec_register_all();
const char *path = "zxy10.mp4";
AVFormatContext *ic = NULL;
int ret = avformat_open_input(&ic, path, NULL, NULL);
if (ret != 0)
{
char buf[1024] = { 0 };
av_strerror(ret, buf, sizeof(buf) - 1);
av_log(NULL, AV_LOG_ERROR, "open file erro %s\n:", buf);
getchar();
return -1;
}
cout << "open file :" << ic->filename << " success" << endl;
avformat_find_stream_info(ic, NULL);
cout << "file time is " << ic->duration / AV_TIME_BASE << endl;
av_dump_format(ic, 0, path, 0);
int audioStream = 0;
int videostream = 0;
#if 0
{
for (int i = 0; i < ic->nb_streams; i++)
{
AVStream *as = ic->streams[i];
if (as->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
videostream = i;
cout << "视频信息 stream :" << videostream << endl;
cout << "height :" << as->codecpar->height << endl;
cout << "weith :" << as->codecpar->width << endl;
cout << "codec_id :" << as->codecpar->codec_id << endl;
cout << "format :" << as->codecpar->format << endl;
cout << "frame_size :" << as->codecpar->frame_size << endl;
cout << "fps : " << r2d(as->avg_frame_rate) << endl;
}
else if (as->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
{
audioStream = i;
cout << endl;
cout << "音频信息,stream " << audioStream << endl;
cout << "codec_id :" << as->codecpar->codec_id << endl;
cout << "channels :" << as->codecpar->channels << endl;
cout << "sample_rate :" << as->codecpar->sample_rate << endl;
cout << "format :" << as->codecpar->format << endl;
cout << "frame_size :" << as->codecpar->frame_size << endl;
cout << "fps : " << r2d(as->avg_frame_rate) << endl;
}
}
}
#endif
videostream = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
if (videostream < 0)
{
char buf[1024] = { 0 };
av_strerror(videostream, buf, sizeof(buf) - 1);
av_log(NULL, AV_LOG_ERROR, "Not find Video Stream : %s\n:", buf);
if (ic)
{
avformat_close_input(&ic);
}
getchar();
return -1;
}
else
{
cout << endl;
cout << "视频信息 stream :" << videostream << endl;
cout << "height :" << ic->streams[videostream]->codecpar->height << endl;
cout << "weith :" << ic->streams[videostream]->codecpar->width << endl;
cout << "codec_id :" << ic->streams[videostream]->codecpar->codec_id << endl;
cout << "format :" << ic->streams[videostream]->codecpar->format << endl;
cout << "frame_size :" << ic->streams[videostream]->codecpar->frame_size << endl;
cout << "fps : " << r2d(ic->streams[videostream]->avg_frame_rate) << endl;
}
audioStream = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
if (audioStream < 0)
{
char buf[1024] = { 0 };
av_strerror(audioStream, buf, sizeof(buf) - 1);
av_log(NULL, AV_LOG_ERROR, "Not find Audio Stream : %s\n:", buf);
if (ic)
{
avformat_close_input(&ic);
}
getchar();
return -1;
}
else
{
cout << endl;
cout << "音频信息,stream " << audioStream << endl;
cout << "codec_id :" << ic->streams[audioStream]->codecpar->codec_id << endl;
cout << "channels :" << ic->streams[audioStream]->codecpar->channels << endl;
cout << "sample_rate :" << ic->streams[audioStream]->codecpar->sample_rate << endl;
cout << "format :" << ic->streams[audioStream]->codecpar->format << endl;
cout << "frame_size :" << ic->streams[audioStream]->codecpar->frame_size << endl;
cout << "fps : " << r2d(ic->streams[audioStream]->avg_frame_rate) << endl;
}
AVCodec * vcodec = avcodec_find_decoder(ic->streams[videostream]->codecpar->codec_id);
if (!vcodec)
{
cout << "can not find AVcodec :" << ic->streams[videostream]->codecpar->codec_id << endl;
cin.get();
return -1;
}
cout << "find avcodec successed : id is" << ic->streams[videostream]->codecpar->codec_id << endl;
AVCodecContext * vc = avcodec_alloc_context3(vcodec);
avcodec_parameters_to_context(vc, ic->streams[videostream]->codecpar);
vc->thread_count = 16;
ret = avcodec_open2(vc, 0, 0);
if (ret != 0)
{
char buf[1024] = { 0 };
av_strerror(ret, buf, sizeof(buf) - 1);
av_log(NULL, AV_LOG_ERROR, "avcodec_open2 %s\n:", buf);
getchar();
return -1;
}
cout << "video avcodec_open2 success!" << endl;
AVCodec * acodec = avcodec_find_decoder(ic->streams[audioStream]->codecpar->codec_id);
if (!acodec)
{
cout << "can not find AVcodec :" << ic->streams[audioStream]->codecpar->codec_id << endl;
cin.get();
return -1;
}
cout << "find avcodec successed : id is" << ic->streams[audioStream]->codecpar->codec_id << endl;
AVCodecContext * ac = avcodec_alloc_context3(acodec);
avcodec_parameters_to_context(ac, ic->streams[audioStream]->codecpar);
ret = avcodec_open2(ac, 0, 0);
if (ret != 0)
{
char buf[1024] = { 0 };
av_strerror(ret, buf, sizeof(buf) - 1);
av_log(NULL, AV_LOG_ERROR, "avcodec_open2 %s\n:", buf);
getchar();
return -1;
}
cout << "audio avcodec_open2 success!" << endl;
AVPacket * pkt = av_packet_alloc();
AVFrame * frame = av_frame_alloc();
SwsContext * vctx = NULL ;
unsigned char * rgb = NULL;
for (;;)
{
int ret = av_read_frame(ic, pkt);
if (ret != 0)
{
break;
}
AVCodecContext * cc = NULL;
if (pkt->stream_index == audioStream)
{
cc = ac;
cout << "音频:" << endl;
}
else if (pkt->stream_index == videostream)
{
cout << "图片:" << endl;
cc = vc;
}
ret = avcodec_send_packet(cc,pkt);
av_packet_unref(pkt);
if (ret != 0)
{
char buf[1024] = { 0 };
av_strerror(ret, buf, sizeof(buf) - 1);
av_log(NULL, AV_LOG_ERROR, "avcodec_send_packet %s\n:", buf);
continue;
}
for (;;)
{
ret = avcodec_receive_frame(cc, frame);
if (ret != 0)
{
break;
}
cout << "frame->format : " << frame->format << "linesize : "<<frame->linesize[0] <<endl;
if (cc == vc)
{
vctx = sws_getCachedContext(
vctx,
frame->width, frame->height,
(AVPixelFormat)frame->format,
frame->width, frame->height,
AV_PIX_FMT_RGBA,
SWS_BILINEAR,
0, 0, 0);
if (vctx == NULL)
{
cout << "sws_getCachedContext erro " << endl;
getchar();
}
if (vctx)
{
if (NULL == rgb)
{
rgb = new unsigned char[frame->width * frame->height * 4];
}
uint8_t * data[2] = {0};
data[0] = rgb;
int lines[2] = { 0 };
lines[0] = frame->width * 4;
ret = sws_scale(vctx,
frame->data,
frame->linesize,
0,
frame->height,
data,
lines
);
cout << "sws_scale : " << ret<< endl;
}
}
}
}
av_frame_free(&frame);
av_packet_free(&pkt);
if (ic)
{
avformat_close_input(&ic);
}
#ifdef _WIN32
#ifdef _WIN64
#else
#endif
#else
#endif
cin.get();
return 0;
}
```