作者:虛壞叔叔
博客:https://xuhss.com
早餐店不會開到晚上,想吃的人早就來了!
XFFmpeg.h
添加成員變量
解碼器上下文:AVCodecContext *vcodec
添加Close函數
用於釋放上下文:
void Close();
完整代碼如下
#pragma once
struct AVFormatContext;
struct AVPacket;
struct AVCodecContext;
class XFFmpeg
{
public:
// 打開視頻
bool Open(const char *url);
// 讀取一陣視頻 在內部存儲
bool Read();
void Close();
XFFmpeg();
~XFFmpeg();
int totalms = 0;
protected:
// 解封裝上下文
AVFormatContext *ic = 0;
// 讀取視頻幀
AVPacket *pkt = 0;
// 解碼器上下文
AVCodecContext *vcodec = 0;
};
XFFmpeg.cpp添加open和close函數的實現
open函數的實現
bool XFFmpeg::Open(const char *url)
{
printf("XFFmpeg::open %s\n", url);
// 打開視頻 解封裝
int re =avformat_open_input(&ic, url, 0, 0);
if (re != 0)
{
char buf[1024] = {
0 };
av_strerror(re, buf, 1023);
printf("avformat open fail:%s\n", buf);
return false;
}
// 獲取流
avformat_find_stream_info(ic, 0);
// 獲取視頻總時長
this->totalms = ic->duration / (AV_TIME_BASE / 1000);
printf("Total Ms =%d\n", totalms);
// 打開解碼器 0視頻 1音頻
AVCodecParameters *para = ic->streams[0]->codecpar;
// 找到解碼器
AVCodec * codec = avcodec_find_decoder(para->codec_id);
if (!codec)
{
printf("avcodec_find_decoder %d failed!\n", para->codec_id);
}
// 分配解碼器上下文
vcodec = avcodec_alloc_context3(codec);
// 配置解碼器上下文
avcodec_parameters_to_context(vcodec, para);
// 多線程解碼
vcodec->thread_count = 8;
// 打開上下文
re = avcodec_open2(vcodec, 0, 0);
if (re != 0)
{
avcodec_free_context(&vcodec);
char buf[1024];
av_strerror(re, buf, sizeof(buf) - 1);
printf("avcodec_open2 failec:%s!\n", buf);
}
printf("avcodec_open2 successed \n");
return true;
}
Close函數實現那:
void XFFmpeg::Close()
{
printf("XFFmpeg::Close\n");
if (ic)
{
avformat_close_input(&ic);
}
if (vcodec)
{
avcodec_free_context(&vcodec);
}
if (pkt)
{
av_packet_free(&pkt);
}
}
完整代碼如下
#include "XFFmpeg.h"
#include <stdio.h>
extern "C" {
#include "libavformat\avformat.h"
}
void XFFmpeg::Close()
{
printf("XFFmpeg::Close\n");
if (ic)
{
avformat_close_input(&ic);
}
if (vcodec)
{
avcodec_free_context(&vcodec);
}
if (pkt)
{
av_packet_free(&pkt);
}
}
bool XFFmpeg::Open(const char *url)
{
printf("XFFmpeg::open %s\n", url);
// 打開視頻 解封裝
int re =avformat_open_input(&ic, url, 0, 0);
if (re != 0)
{
char buf[1024] = {
0 };
av_strerror(re, buf, 1023);
printf("avformat open fail:%s\n", buf);
return false;
}
// 獲取流
avformat_find_stream_info(ic, 0);
// 獲取視頻總時長
this->totalms = ic->duration / (AV_TIME_BASE / 1000);
printf("Total Ms =%d\n", totalms);
// 打開解碼器 0視頻 1音頻
AVCodecParameters *para = ic->streams[0]->codecpar;
// 找到解碼器
AVCodec * codec = avcodec_find_decoder(para->codec_id);
if (!codec)
{
printf("avcodec_find_decoder %d failed!\n", para->codec_id);
}
// 分配解碼器上下文
vcodec = avcodec_alloc_context3(codec);
// 配置解碼器上下文
avcodec_parameters_to_context(vcodec, para);
// 多線程解碼
vcodec->thread_count = 8;
// 打開上下文
re = avcodec_open2(vcodec, 0, 0);
if (re != 0)
{
avcodec_free_context(&vcodec);
char buf[1024];
av_strerror(re, buf, sizeof(buf) - 1);
printf("avcodec_open2 failec:%s!\n", buf);
}
printf("avcodec_open2 successed \n");
return true;
}
bool XFFmpeg::Read()
{
if (!ic)
return false;
// 視頻幀的存儲空間
if (!pkt)
{
// 分配對象空間
pkt = av_packet_alloc();
}
else
{
// 引用計數 -1 清理視頻幀
av_packet_unref(pkt);
}
int re = 0;
bool isFindVideo = false;
// 音頻數據丟掉
for (int i = 0; i < 20; i++)
{
// 讀取一幀數據
re = av_read_frame(ic, pkt);
// 讀取失敗或者讀取到文件結尾
if (re != 0)
{
return false;
}
// 是否是視頻幀
if (pkt->stream_index == 0)
{
isFindVideo = true;
break;
}
// 音頻幀 清理packet
av_packet_unref(pkt);
}
return isFindVideo;
}
XFFmpeg::XFFmpeg()
{
printf("Create XFFmpeg\n");
}
XFFmpeg::~XFFmpeg()
{
printf("Delete XFFmpeg\n");
}
PyFFmpeg.cpp中添加Close函數的調用:
void PyFFmpeg::Close(PyFFmpeg*self)
{
printf("PyFFmpeg::Close\n");
self->ff->Close();
delete self->ff;
Py_TYPE(self)->tp_free(self);
}
運行後,你會發現,解碼器上下文加載成功
點贊
收藏
轉發
一波哦,博主也支持為鐵粉絲制作專屬動態壁紙哦~關注下面卡片即刻獲取更多編程知識,包括各種語言學習資料,上千套PPT模板和各種游戲源碼素材等等資料。更多內容可自行查看哦!