您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
10. 添加IDemux的GetVPara获取视频XParamter参数接口用IDecode的Open测试~1
发布时间:2021-06-09 16:21:37编辑:雪饮阅读()
获取视频参数的话,要在cpp/FFDemux.cpp中实现GetVPara方法:
#include "XLog.h"
extern "C"{
#include <libavformat/avformat.h>
}
//打开文件,或者流媒体 rmtp http rtsp
bool FFDemux::Open(const char *url)
{
XLOGI("Open file %s begin",url);
int re = avformat_open_input(&ic,url,0,0);
if(re != 0 )
{
char buf[1024] = {0};
av_strerror(re,buf,sizeof(buf));
XLOGE("FFDemux open %s failed!",url);
return false;
}
XLOGI("FFDemux open %s success!",url);
//读取文件信息
re = avformat_find_stream_info(ic,0);
if(re != 0 )
{
char buf[1024] = {0};
av_strerror(re,buf,sizeof(buf));
XLOGE("avformat_find_stream_info %s failed!",url);
return false;
}
//ffmpeg内部的時間單位是微秒,AVFormatContext =》duration的單位是AV_TIME_BASE
this->totalMs = ic->duration/(AV_TIME_BASE/1000);
XLOGI("total ms = %d!",totalMs);
return true;
}
//获取视频参数
XParameter FFDemux::GetVPara()
{
if (!ic) {
XLOGE("GetVPara failed! ic is NULL!");
return XParameter();
}
//获取了视频流索引
int re = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0);
if (re < 0) {
XLOGE("av_find_best_stream failed!");
return XParameter();
}
XParameter para;
para.para = ic->streams[re]->codecpar;
return para;
}
//读取一帧数据,数据由调用者清理
XData FFDemux::Read()
{
if(!ic)return XData();
XData d;
AVPacket *pkt = av_packet_alloc();
int re = av_read_frame(ic,pkt);
if(re != 0)
{
av_packet_free(&pkt);
return XData();
}
XLOGI("pack size is %d ptss %lld",pkt->size,pkt->pts);
d.data = (unsigned char*)pkt;
d.size = pkt->size;
return d;
}
FFDemux::FFDemux()
{
static bool isFirst = true;
if(isFirst)
{
isFirst = false;
//注册所有封装器
av_register_all();
//注册所有的解码器
avcodec_register_all();
//初始化网络
avformat_network_init();
XLOGI("register ffmpeg!");
}
}
这里需要注意的是,可以看到这里的函数后面都有一个等于0的声明,像是虚函数,如果后面没有加上等于0的声明,则该虚函数就仅仅只是虚函数,但是如果加了等于0的声明,则该函数就是纯虚函数。 然后在入口cpp/native-lib.cpp中调用以获取视频参数:
同样的对于魅族16T是没有问题的:
#define XPLAY_IDEMUX_H
#include "XData.h"
#include "XThread.h"
#include "IObserver.h"
#include "XParameter.h"
//解封装接口
class IDemux: public IObserver {
public:
//打开文件,或者流媒体 rmtp http rtsp
virtual bool Open(const char *url) = 0;
//获取视频参数
virtual XParameter GetVPara() = 0;
//读取一帧数据,数据由调用者清理
virtual XData Read() = 0;
//总时长(毫秒)
int totalMs = 0;
protected:
virtual void Main();
};
#endif //XPLAY_IDEMUX_H
#define XPLAY_FFDEMUX_H
#include "IDemux.h"
struct AVFormatContext;
class FFDemux: public IDemux {
public:
//打开文件,或者流媒体 rmtp http rtsp
virtual bool Open(const char *url);
//获取视频参数
virtual XParameter GetVPara();
//读取一帧数据,数据由调用者清理
virtual XData Read();
FFDemux();
private:
AVFormatContext *ic = 0;
};
#endif //XPLAY_FFDEMUX_H
#include <string>
#include "FFDemux.h"
#include "XLog.h"
#include "FFDecode.h"
class TestObs:public IObserver
{
public:
void Update(XData d)
{
XLOGI("TestObs Update data size is %d",d.size);
}
};
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_xplay_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
TestObs *tobs = new TestObs();
IDemux *de = new FFDemux();
de->AddObs(tobs);
de->Open("/sdcard/1080.mp4");
IDecode *vdecode = new FFDecode();
vdecode->Open(de->GetVPara());
de->Start();
XSleep(3000);
de->Stop();
return env->NewStringUTF(hello.c_str());
}
关键字词:GetVPara
相关文章
-
无相关信息