您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
17. 完成了播放进度的显示并修正了硬解码参数传递错误~1
发布时间:2021-06-14 14:28:23编辑:雪饮阅读()
首先在cpp/IPlayer.cpp中實現播放定位:
#include "IDemux.h"
#include "IDecode.h"
#include "IAudioPlay.h"
#include "IVideoView.h"
#include "IResample.h"
#include "XLog.h"
IPlayer *IPlayer::Get(unsigned char index)
{
static IPlayer p[256];
return &p[index];
}
void IPlayer::Main()
{
while (!isExit)
{
mux.lock();
if(!audioPlay|| !vdecode)
{
mux.unlock();
XSleep(2);
continue;
}
//同步
//获取音频的pts 告诉视频
int apts = audioPlay->pts;
//XLOGE("apts = %d",apts);
vdecode->synPts = apts;
mux.unlock();
XSleep(2);
}
}
void IPlayer::Close()
{
mux.lock();
//2 先关闭主体线程,再清理观察者
//同步线程
XThread::Stop();
//解封装
if(demux)
demux->Stop();
//解码
if(vdecode)
vdecode->Stop();
if(adecode)
adecode->Stop();
//2 清理缓冲队列
if(vdecode)
vdecode->Clear();
if(adecode)
adecode->Clear();
if(audioPlay)
audioPlay->Clear();
//3 清理资源
if(audioPlay)
audioPlay->Close();
if(videoView)
videoView->Close();
if(vdecode)
vdecode->Close();
if(adecode)
adecode->Close();
if(demux)
demux->Close();
mux.unlock();
}
double IPlayer::PlayPos()
{
double pos = 0.0;
mux.lock();
int total = 0;
if(demux)
total = demux->totalMs;
if(total>0)
{
if(vdecode)
{
pos = (double)vdecode->pts/(double)total;
}
}
mux.unlock();
return pos;
}
bool IPlayer::Open(const char *path)
{
Close();
mux.lock();
//解封装
if(!demux || !demux->Open(path))
{
mux.unlock();
XLOGE("demux->Open %s failed!",path);
return false;
}
//解码 解码可能不需要,如果是解封之后就是原始数据
if(!vdecode || !vdecode->Open(demux->GetVPara(),isHardDecode))
{
XLOGE("vdecode->Open %s failed!",path);
//return false;
}
if(!adecode || !adecode->Open(demux->GetAPara()))
{
XLOGE("adecode->Open %s failed!",path);
//return false;
}
//重采样 有可能不需要,解码后或者解封后可能是直接能播放的数据
//if(outPara.sample_rate <= 0)
outPara = demux->GetAPara();
if(!resample || !resample->Open(demux->GetAPara(),outPara))
{
XLOGE("resample->Open %s failed!",path);
}
mux.unlock();
return true;
}
bool IPlayer::Start()
{
mux.lock();
if(vdecode)
vdecode->Start();
if(!demux || !demux->Start())
{
mux.unlock();
XLOGE("demux->Start failed!");
return false;
}
if(adecode)
adecode->Start();
if(audioPlay)
audioPlay->StartPlay(outPara);
XThread::Start();
mux.unlock();
return true;
}
void IPlayer::InitView(void *win)
{
if(videoView)
{
videoView->Close();
videoView->SetRender(win);
}
}
在cpp/IPlayerPorxy.cpp中實現:
在cpp/IPlayerPorxy.h中聲明:
在cpp/native-lib.cpp入口中也要實現播放定位,調用上面代理模式的播放定位:
#define XPLAY_IPLAYER_H
#include <mutex>
#include "XThread.h"
#include "XParameter.h"
class IDemux;
class IAudioPlay;
class IVideoView;
class IResample;
class IDecode;
class IPlayer : public XThread
{
public:
static IPlayer *Get(unsigned char index=0);
virtual bool Open(const char *path);
virtual void Close();
virtual bool Start();
virtual void InitView(void *win);
//获取当前的播放进度 0.0 ~ 1.0
virtual double PlayPos();
//是否视频硬解码
bool isHardDecode = true;
//音频输出参数配置
XParameter outPara;
IDemux *demux = 0;
IDecode *vdecode = 0;
IDecode *adecode = 0;
IResample *resample = 0;
IVideoView *videoView = 0;
IAudioPlay *audioPlay = 0;
protected:
//用作音视频同步
void Main();
std::mutex mux;
IPlayer(){};
};
#endif //XPLAY_IPLAYER_H
#include "FFPlayerBuilder.h"
void IPlayerPorxy::Close()
{
mux.lock();
if(player)
player->Close();
mux.unlock();
}
void IPlayerPorxy::Init(void *vm)
{
mux.lock();
if(vm)
{
FFPlayerBuilder::InitHard(vm);
}
if(!player)
player = FFPlayerBuilder::Get()->BuilderPlayer();
mux.unlock();
}
//获取当前的播放进度 0.0 ~ 1.0
double IPlayerPorxy::PlayPos()
{
double pos = 0.0;
mux.lock();
if(player)
{
pos = player->PlayPos();
}
mux.unlock();
return pos;
}
bool IPlayerPorxy::Open(const char *path)
{
bool re = false;
mux.lock();
if(player)
{
player->isHardDecode = isHardDecode;
re = player->Open(path);
}
mux.unlock();
return re;
}
bool IPlayerPorxy::Start()
{
bool re = false;
mux.lock();
if(player)
re = player->Start();
mux.unlock();
return re;
}
void IPlayerPorxy::InitView(void *win)
{
mux.lock();
if(player)
player->InitView(win);
mux.unlock();
}
#define XPLAY_IPLAYERPORXY_H
#include "IPlayer.h"
#include <mutex>
class IPlayerPorxy: public IPlayer
{
public:
static IPlayerPorxy*Get()
{
static IPlayerPorxy px;
return &px;
}
void Init(void *vm = 0);
virtual bool Open(const char *path);
virtual void Close();
virtual bool Start();
virtual void InitView(void *win);
//获取当前的播放进度 0.0 ~ 1.0
virtual double PlayPos();
protected:
IPlayerPorxy(){}
IPlayer *player = 0;
std::mutex mux;
};
#endif //XPLAY_IPLAYERPORXY_H #include <jni.h>
#include <string>
#include <android/native_window_jni.h>
#include "XLog.h"
#include "IPlayerPorxy.h"
extern "C"
JNIEXPORT
jint JNI_OnLoad(JavaVM *vm,void *res)
{
IPlayerPorxy::Get()->Init(vm);
/*IPlayerPorxy::Get()->Open("/sdcard/v1080.mp4");
IPlayerPorxy::Get()->Start();
IPlayerPorxy::Get()->Open("/sdcard/1080.mp4");
IPlayerPorxy::Get()->Start();*/
return JNI_VERSION_1_4;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_xplay_XPlay_InitView(JNIEnv *env, jobject instance, jobject surface) {
// TODO
ANativeWindow *win = ANativeWindow_fromSurface(env,surface);
IPlayerPorxy::Get()->InitView(win);
}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_xplay_MainActivity_stringFromJNI(JNIEnv *env, jobject thiz) {
// TODO: implement stringFromJNI()
}extern "C"
JNIEXPORT void JNICALL
Java_com_example_xplay_OpenUrl_Open(JNIEnv *env, jobject thiz, jstring url_) {
const char *url = env->GetStringUTFChars(url_, 0);
IPlayerPorxy::Get()->Open(url);
IPlayerPorxy::Get()->Start();
env->ReleaseStringUTFChars(url_, url);
}extern "C"
JNIEXPORT jdouble JNICALL
Java_com_example_xplay_MainActivity_PlayPos(JNIEnv *env, jobject thiz) {
return IPlayerPorxy::Get()->PlayPos();
}在MainActivity.java中要實現多綫程:
package com.example.xplay;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements Runnable{
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
private Button bt;
private SeekBar seek;
private Thread th;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt = findViewById( R.id.open_button );
bt.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.e("XPlay","open button click!");
//打开选择路径窗口
Intent intent = new Intent();
intent.setClass( MainActivity.this ,OpenUrl.class);
startActivity( intent );
}
} );
}
//播放进度显示
@Override
public void run() {
for(;;)
{
seek.setProgress((int)(PlayPos()*1000));
try {
Thread.sleep( 40 );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public native double PlayPos();
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
}
关键字词:硬解碼