目录
前言:
现在很多网上的代码,由于不是最新的ffmpeg库,导致很多不能运行。这里发一下自己运行过的最新的ffmpeg软解码代码。
环境:
ffmpeg库代码:ffmpeg6.1.1
qt环境
windows系统
代码
#include <QCoreApplication>
#include <QDebug>
extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavformat/avio.h"
#include "libavdevice/avdevice.h"
#include "libavutil/imgutils.h"
#include "libavutil/audio_fifo.h"
#include "libavutil/time.h"
#include "libavutil/mathematics.h"
#include "libavutil/channel_layout.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
#include "libavutil/opt.h"
#include "libavutil/mem.h"
#include "libavutil/buffer.h"
#include "libavutil/error.h"
#include "libavutil/hwcontext.h"
#include "libavutil/hwcontext_qsv.h"
#define HAVE_STRUCT_TIMESPEC
//#include "pthread.h"
}
AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height)
{
AVFrame *picture;
int ret;
picture = av_frame_alloc();
if (!picture)
return NULL;
picture->format = pix_fmt;
picture->width = width;
picture->height = height;
/* allocate the buffers for the frame data */
ret = av_frame_get_buffer(picture, 4);
if (ret < 0)
{
qCritical()<<__FUNCTION__<<__LINE__<<"Could not allocate frame data.";
return NULL;
}
return picture;
}
int getRotateAngle(AVStream* avStream)
{
AVDictionaryEntry *tag = NULL;
int m_Rotate = -1;
tag = av_dict_get(avStream->metadata, "rotate", tag, 0);
if (tag == NULL)
{
m_Rotate = 0;
}
else
{
int angle = atoi(tag->value);
angle %= 360;
m_Rotate = angle;
}
return m_Rotate;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString filename = "1.mp4";
/*描述一个媒体文件或媒体流的构成和基本信息的结构体*/
AVFormatContext *avFormatContext = nullptr;
int res = avformat_open_input(&avFormatContext,filename.toUtf8().data(), NULL, NULL);//打开文件
if (res < 0) {
qCritical()<<__FUNCTION__<<__LINE__<<"error "<<res<<"in avformat_open_input";
return res;
}
res = avformat_find_stream_info(avFormatContext, nullptr);//取出流信息
if (res < 0)
{
return res;
}
//查找视频流和音频流
av_dump_format(avFormatContext, 0,filename.toUtf8().data(), 0);//列出输入文件的相关流信息
int video_index= -1;
int m_width = 0;
int m_height = 0;
for (unsigned int i = 0; i < avFormatContext->nb_streams; i++)
{
if (avFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
if(video_index==-1)
{
video_index = i;
}
}
}
m_width = avFormatContext->streams[video_index]->codecpar->width;
m_height = avFormatContext->streams[video_index]->codecpar->height;
const AVCodec* m_codec = nullptr;/*解码器*/
AVCodecContext *avCodecContext = nullptr;/*解码器上下文*/
m_codec = avcodec_find_decoder(avFormatContext->streams[video_index]->codecpar->codec_id);
avCodecContext = avcodec_alloc_context3(m_codec);
avcodec_parameters_to_context(avCodecContext, avFormatContext->streams[video_index]->codecpar);
if (avcodec_open2(avCodecContext, m_codec, nullptr) < 0)
{
qCritical()<<__FUNCTION__<<__LINE__<<"Init_Soft_DecoderCodec error";
return false;
}
struct SwsContext *img_convert_ctx = nullptr;
AVFrame *bgrFrame = NULL;
AVFrame *avFrame = nullptr;
AVPacket *avPacket;
avPacket = av_packet_alloc();
avFrame = av_frame_alloc();
img_convert_ctx = sws_getContext(
m_width,
m_height,
avCodecContext->pix_fmt,
m_width,
m_height,
AV_PIX_FMT_BGRA,
SWS_BICUBIC,
NULL, NULL, NULL);
bgrFrame = alloc_picture(
AV_PIX_FMT_BGRA,
m_width,
m_height);
while (true)
{
int ret = av_read_frame(avFormatContext, avPacket);
if (ret < 0){
qDebug()<< "read end";
break;
}
else if (avPacket->stream_index == video_index){
int ret = avcodec_send_packet(avCodecContext, avPacket);
if (ret < 0) {
char error[1024];
av_strerror(ret, error, 1024);
qDebug() << "发送解码失败:" << error;
}
while (true)
{
ret = avcodec_receive_frame(avCodecContext, avFrame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
{
//qDebug() << "avcodec_receive_frame end:" << ret;
break;
}
else if (ret < 0)
{
//qDebug()<< "获取解码数据失败"<<ret;
return ret;
}
else
{
int m_rotat = getRotateAngle(avFormatContext->streams[video_index]);
sws_scale(img_convert_ctx,
(const unsigned char* const*)avFrame->data,
avFrame->linesize, 0,
avFrame->height,
bgrFrame->data,
bgrFrame->linesize);
av_frame_unref(avFrame);
}
}
}
av_packet_unref(avPacket);
}
if(bgrFrame)
{
av_frame_free(&bgrFrame);
bgrFrame= nullptr;
}
m_codec = nullptr;
if(avPacket)
{
av_packet_free(&avPacket);
avPacket = nullptr;
}
if(avFrame)
{
av_frame_free(&avFrame);
avFrame = nullptr;
}
if(img_convert_ctx)
{
sws_freeContext(img_convert_ctx);
img_convert_ctx = nullptr;
}
if(avCodecContext != nullptr)
{
avcodec_close(avCodecContext);
avCodecContext = nullptr;
}
if(avFormatContext != nullptr)
{
avformat_free_context(avFormatContext);
}
qDebug()<<"=========end========";
return a.exec();
}
结论:
上面的代码用c语言写的,下次整一个c++的代码,可以更方便的来使用。