倪是一个IT民工 2022-05-05 10:03
浏览 55
已结题

vlc-android 如何回调视频PCM数据

问题遇到的现象和发生背景

想要通过vlc-android 获取到pcm数据对音频进行后续处理,但是我写的回调方法无法获取到正确的PCM数据,下面是我写的回调方法

问题相关代码,请勿粘贴截图

//自己添加的方法-音频回调

static pthread_mutex_t myMutexForAudio = PTHREAD_MUTEX_INITIALIZER;

//设置音频格式
void
Java_org_videolan_libvlc_MediaPlayer_nativeSetAudioFormat(JNIEnv *env, jobject thiz,
jstring format, jint rate, jint channels) {

//获取到VLC单例
vlcjni_object *p_obj=VLCJniObject_getInstance(env,thiz);

//判断是否为空,如果为空证明播放器未初始化或已经被释放
if (!p_obj)
{
    return;
}

//通过jni将string转为char 
const char *formatStr=(*env)->GetStringUTFChars(env,format,NULL);

//设置音频格式的方法
libvlc_audio_set_format(p_obj->u.p_mp,formatStr,rate,channels);

//释放资源
(*env)->ReleaseStringUTFChars(env,format,formatStr);

}

struct myfieldForAudio {
jclass mediaPlayerClazz;
jmethodID onDisplayCallback;
jobject thiz;
void *buffer;
} myfieldForAudio;

//处理回调数据的方法
static void displayForAudio(void *data, const void *samples,unsigned count,int64_t pts) {
JavaVM jvm = fields.jvm; //这个地方需要修改 "utils.h" 中的struct fields,增加成员JavaVM jvm,并且在libvlcjni.c的中进行赋值
JNIEnv *env;
int stat = (*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2);
if (stat == JNI_EDETACHED) {
if ((*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL) != 0) {
return;
}
} else if (stat == JNI_OK) {

} else if (stat == JNI_EVERSION) {
return;
}

//将音频数据传递
samples=myfieldForAudio.buffer;

//它在这里特意加个锁大概率就是别的地方写,它才特意要确保传进这个函数的时候你自己把buffer保存起来

pthread_mutex_lock(&myMutexForAudio);

if (myfieldForAudio.thiz != NULL) {
//将数据回调
(*env)->CallVoidMethod(env, myfieldForAudio.thiz, myfieldForAudio.onDisplayCallback);
}

pthread_mutex_unlock(&myMutexForAudio);

(*jvm)->DetachCurrentThread(jvm);
}

//回调音频的native方法
void
Java_org_videolan_libvlc_MediaPlayer_nativeSetAudioBuffer(JNIEnv *env, jobject thiz,jobject buffer) {

//获取到VLC单例
vlcjni_object *p_obj=VLCJniObject_getInstance(env,thiz);

//获取媒体播放器对象
libvlc_media_player_t *mp=p_obj->u.p_mp;

//判断是否为空,如果为空证明播放器未初始化或已经被释放
if (!mp)
{
    return;
}

//如果java层传递来的buffer缓存区对象为空时,释放资源
if (buffer == NULL)
{
    (*env)->DeleteGlobalRef(env,myfieldForAudio.mediaPlayerClazz);
    pthread_mutex_lock(&myMutexForAudio);
    (*env)->DeleteGlobalRef(env,myfieldForAudio.thiz);
    myfieldForAudio.thiz=NULL;
    pthread_mutex_unlock(&myMutexForAudio);
    return;
}

//通过反射获取到MediaPlayer类的字节马
myfieldForAudio.mediaPlayerClazz= (*env)->FindClass(env,"org/videolan/libvlc/MediaPlayer");
//创建一个MediaPlayer类
myfieldForAudio.mediaPlayerClazz=(jclass)(*env)->NewGlobalRef(env,myfieldForAudio.mediaPlayerClazz);
//设置回调方法
myfieldForAudio.onDisplayCallback=(*env)->GetMethodID(env,myfieldForAudio.mediaPlayerClazz,"onAudioFrameCallBack","()V");
myfieldForAudio.thiz=(*env)->NewGlobalRef(env,thiz);
//获取到java传来的biffer的地址
myfieldForAudio.buffer=(*env)->GetDirectBufferAddress(env,buffer);

//回调音频数据的方法
libvlc_audio_set_callbacks(mp,displayForAudio,NULL,NULL,NULL,NULL,NULL);

}

//自己创建的方法-结束

运行结果及报错内容

没有收到报错信息

我的解答思路和尝试过的方法

有可能是回调方法写错了,c代码还是不熟练

我想要达到的结果

能够正确回调PCM数据

  • 写回答

0条回答 默认 最新

    报告相同问题?

    问题事件

    • 系统已结题 5月13日
    • 创建了问题 5月5日

    悬赏问题

    • ¥15 报酬10000,做一个简单的换汇网站
    • ¥15 关于#vue.js#的问题:word excel和ppt预览问题语言-javascript)
    • ¥15 Apache显示系统错误3该如何解决?
    • ¥30 uniapp小程序苹果手机加载gif图片不显示动效?
    • ¥20 js怎么实现跨域问题
    • ¥15 C++dll二次开发,C#调用
    • ¥15 请教,如何使用C#加载本地摄像头进行逐帧推流
    • ¥15 Python easyocr无法顺利执行,如何解决?
    • ¥15 为什么会突然npm err!啊
    • ¥15 java服务连接es读取列表数据,服务连接本地es获取数据时的速度很快,但是换成远端的es就会非常慢,这是为什么呢