您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
7. 通过遍历获取AVStream音视频流信息并打印参数~1
发布时间:2021-05-31 14:15:01编辑:雪饮阅读()
调回usb调试方式
前面为了调试方便,使用了usb网络調試模式,但是此模式有一個缺點,必須電腦和手機在一個局域網且必須是同一個衝突域。
那麽這樣就會帶來一個新的問題,比如今天遇到的是不在同一個衝突域的時候就連接不上。
此時可以將usb調試模式重新調回usb模式。直接使用命令”adb usb”即可。
打印AVStream音视频流信息
在AVStream音视频流信息中一般都是有視頻和音頻流兩種信息。通過AVStream實例的codecpar->codec_type來進行判斷區別。
這裏獲取音視頻流信息將采用mp4格式,因爲mp4格式可以獲取得更多的信息。所以前面的flv這裏就先注釋了。
那麽具體實例:cpp/native-lib.cpp:
#include <jni.h>
#include <string>
#include <android/log.h>
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,"testff",__VA_ARGS__)
extern "C"{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}
static double r2d(AVRational r){
return r.num==0 | r.den==0 ? 0:(double) r.num/(double)r.den;
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_ndk_1and_141_MainActivity_stringFromJNI(JNIEnv* env,jobject) {
std::string hello = "Hello from C++";
hello+=avcodec_configuration();
//初始化解封裝
av_register_all();
//初始化網絡
avformat_network_init();
AVFormatContext *ic=NULL;
//要取一些信息,mp4格式取的比較多
char path[]="/sdcard/1080.mp4";
int re=avformat_open_input(&ic,path,0,0);
if(re!=0){
LOGW("avformat_open_input failed!:%s",av_err2str(re));
return env->NewStringUTF(hello.c_str());
}
/*
這裏需要漲點教訓,原來這裏是LOGW("avformat_open_input %s success!");
也就是多帶了一個%s,很明顯這裏語法在c中是有問題的,可是編譯過程時候沒有報錯。
日志貓中報錯信息讓我一度懷疑自己的arm64位動態鏈接庫編譯錯了呢。。。
*/
LOGW("avformat_open_input success!");
/*
duration方法:
mp4格式可以直接獲取到時長
返回類型是int64_t:
int64_t 是标准C ++类型,用于完全64位的有符号整数。 int64 不是标准类型。
第一个C ++标准没有固定宽度类型。在将 int64_t 添加到标准C ++之前,不同的编译器都实现了64位类型,但它们使用了自己的名称(例如 long long < / code>, __ int64 等。)
那麽因爲long long < / code>,所以這裏int64_t的輸出就是l ld了
*/
//對於flv來説,要先探測獲取下流信息,若不先探測,則獲取的場地可能就是如:-9223372036854775808一樣的負數
re=avformat_find_stream_info(ic,0);
if(re!=0){
LOGW("avformat_find_stream_info failed!");
}
//這裏格式化int64_t的時候千萬記住不是%lld而是%l ld
LOGW("duration=%l ld nb_streams=%d",ic->duration,ic->nb_streams);
int fps = 0;
int videoStream = 0;
int audioStream = 1;
/*
遍历获取AVStream音视频流信息并打印参数
*/
for(int i = 0; i < ic->nb_streams; i++)
{
AVStream *as = ic->streams[i];
if(as->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
LOGW("视频数据");
videoStream = i;
//avg_frame_rate:幀率,一個分數,就是fps的分數表示法,分數表示可以有效保護精度損失
fps = r2d(as->avg_frame_rate);
/*
codecpar->width,codecpar->height:视频的宽高,只有视频有
codecpar->codec_id: 獲取解碼器的id號
codecpar->format:格式。对于视频来说指的就是像素格式(YUV420,YUV422...),对于音频来说,指的就是音频的采样格式。
*/
LOGW("fps = %d,width=%d height=%d codeid=%d pixformat=%d",fps,
as->codecpar->width,
as->codecpar->height,
as->codecpar->codec_id,
as->codecpar->format
);
}
else if(as->codecpar->codec_type ==AVMEDIA_TYPE_AUDIO )
{
LOGW("音频数据");
audioStream = i;
/*
codecpar->sample_rate:樣本率
codecpar->channels:声道数
codecpar->format:格式。对于视频来说指的就是像素格式(YUV420,YUV422...),对于音频来说,指的就是音频的采样格式。
*/
LOGW("sample_rate=%d channels=%d sample_format=%d",
as->codecpar->sample_rate,
as->codecpar->channels,
as->codecpar->format
);
}
}
avformat_close_input(&ic);
return env->NewStringUTF(hello.c_str());
}
#include <string>
#include <android/log.h>
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,"testff",__VA_ARGS__)
extern "C"{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}
static double r2d(AVRational r){
return r.num==0 | r.den==0 ? 0:(double) r.num/(double)r.den;
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_ndk_1and_141_MainActivity_stringFromJNI(JNIEnv* env,jobject) {
std::string hello = "Hello from C++";
hello+=avcodec_configuration();
//初始化解封裝
av_register_all();
//初始化網絡
avformat_network_init();
AVFormatContext *ic=NULL;
//要取一些信息,mp4格式取的比較多
char path[]="/sdcard/1080.mp4";
int re=avformat_open_input(&ic,path,0,0);
if(re!=0){
LOGW("avformat_open_input failed!:%s",av_err2str(re));
return env->NewStringUTF(hello.c_str());
}
/*
這裏需要漲點教訓,原來這裏是LOGW("avformat_open_input %s success!");
也就是多帶了一個%s,很明顯這裏語法在c中是有問題的,可是編譯過程時候沒有報錯。
日志貓中報錯信息讓我一度懷疑自己的arm64位動態鏈接庫編譯錯了呢。。。
*/
LOGW("avformat_open_input success!");
/*
duration方法:
mp4格式可以直接獲取到時長
返回類型是int64_t:
int64_t 是标准C ++类型,用于完全64位的有符号整数。 int64 不是标准类型。
第一个C ++标准没有固定宽度类型。在将 int64_t 添加到标准C ++之前,不同的编译器都实现了64位类型,但它们使用了自己的名称(例如 long long < / code>, __ int64 等。)
那麽因爲long long < / code>,所以這裏int64_t的輸出就是l ld了
*/
//對於flv來説,要先探測獲取下流信息,若不先探測,則獲取的場地可能就是如:-9223372036854775808一樣的負數
re=avformat_find_stream_info(ic,0);
if(re!=0){
LOGW("avformat_find_stream_info failed!");
}
//這裏格式化int64_t的時候千萬記住不是%lld而是%l ld
LOGW("duration=%l ld nb_streams=%d",ic->duration,ic->nb_streams);
int fps = 0;
int videoStream = 0;
int audioStream = 1;
/*
遍历获取AVStream音视频流信息并打印参数
*/
for(int i = 0; i < ic->nb_streams; i++)
{
AVStream *as = ic->streams[i];
if(as->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
LOGW("视频数据");
videoStream = i;
//avg_frame_rate:幀率,一個分數,就是fps的分數表示法,分數表示可以有效保護精度損失
fps = r2d(as->avg_frame_rate);
/*
codecpar->width,codecpar->height:视频的宽高,只有视频有
codecpar->codec_id: 獲取解碼器的id號
codecpar->format:格式。对于视频来说指的就是像素格式(YUV420,YUV422...),对于音频来说,指的就是音频的采样格式。
*/
LOGW("fps = %d,width=%d height=%d codeid=%d pixformat=%d",fps,
as->codecpar->width,
as->codecpar->height,
as->codecpar->codec_id,
as->codecpar->format
);
}
else if(as->codecpar->codec_type ==AVMEDIA_TYPE_AUDIO )
{
LOGW("音频数据");
audioStream = i;
/*
codecpar->sample_rate:樣本率
codecpar->channels:声道数
codecpar->format:格式。对于视频来说指的就是像素格式(YUV420,YUV422...),对于音频来说,指的就是音频的采样格式。
*/
LOGW("sample_rate=%d channels=%d sample_format=%d",
as->codecpar->sample_rate,
as->codecpar->channels,
as->codecpar->format
);
}
}
avformat_close_input(&ic);
return env->NewStringUTF(hello.c_str());
}
編譯部署到如魅族16T上可以看到視頻流和音頻流的相關信息就成功輸出到日志貓上了
关键字词:AVStream
相关文章
-
无相关信息