#include
#include
#include
#include
#include
#include
#include
#include
#include
#include"FFDemux.h"
#include"ChaoLog.h"
#include"ChaoDecode.h"
#include"FFDecode.h"
#include"ChaoVideoView.h"
#include"ChaoEGL.h"
#include"ChaoShader.h"
#include"GLVideoView.h"
#include"ChaoResample.h"
#include"FFResample.h"
#include"ChaoAudioPlay.h"
#include"SLAudioPlay.h"
#defineLOGW(...) __android_log_print(ANDROID_LOG_WARN,"ChaoPlayer", __VA_ARGS__)
#defineLOGE(...) __android_log_print(ANDROID_LOG_ERROR,"ChaoPlayer", __VA_ARGS__)
#defineLOGI(...) __android_log_print(ANDROID_LOG_INFO,"ChaoPlayer", __VA_ARGS__)
#defineLOGD(...) __android_log_print(ANDROID_LOG_DEBUG,"ChaoPlayer", __VA_ARGS__)
extern"C"{
#include
#include
#include
#include
#include
}
#include
usingnamespacestd;
//把分?jǐn)?shù)轉(zhuǎn)換成浮點(diǎn)型
staticdoubler2d(AVRational r) {
returnr.num==0|| r.den==0?0: (double)r.num/ (double)r.den;
}
//當(dāng)前時(shí)間戳 clock
longlongGetNowMs() {
structtimevaltv;
gettimeofday(&tv,NULL);
intsec = tv.tv_sec%360000;
longlongt = sec *1000+ tv.tv_usec/1000;
returnt;
}
/*********************音頻播放OpenSLES ****************************/
//1.創(chuàng)建引擎
staticSLObjectItf engineSL =NULL;
SLEngineItfCreateSL() {
? ? SLresult re;
? ? SLEngineItf en;
re =slCreateEngine(&engineSL,0,0,0,0,0);//創(chuàng)建引擎對象
if(re != SL_RESULT_SUCCESS)//失敗
returnNULL;
re = (*engineSL)->Realize(engineSL, SL_BOOLEAN_FALSE);//成功? 等待對象創(chuàng)建
if(re != SL_RESULT_SUCCESS)
returnNULL;
re = (*engineSL)->GetInterface(engineSL, SL_IID_ENGINE, &en);//獲取接口
if(re != SL_RESULT_SUCCESS)
returnNULL;
returnen;
}
//播放Pcm音頻文件
voidPcmCall(SLAndroidSimpleBufferQueueItf bf,void*context) {
LOGI("PcmCall");
staticFILE*fp =NULL;
staticchar*buf =NULL;
if(!buf) {
buf =newchar[1024*1024];
? ? }
if(!fp) {
fp =fopen("/sdcard/Music/test.pcm","rb");
? ? }
if(!fp)
return;
if(feof(fp) ==0) {//打開成功
intlen =fread(buf,1,1024, fp);
if(len >0)
(*bf)->Enqueue(bf, buf, len);//發(fā)送音頻
? ? }
}
//頂點(diǎn)著色器glsl
#defineGET_STR(x) #x
staticconstchar*vertexShader = GET_STR(
attribute vec4 aPosition;//頂點(diǎn)坐標(biāo)
attribute vec2 aTexCoord;//材質(zhì)頂點(diǎn)坐標(biāo)
varying vec2 vTexCoord;//輸出的材質(zhì)坐標(biāo)
voidmain(){
vTexCoord =vec2(aTexCoord.x,1.0- aTexCoord.y);
gl_Position = aPosition;//顯示頂點(diǎn)
? ? ? ? }
);
//片元著色器,軟解碼和部分x86硬解碼
staticconstchar*fragYUV420P = GET_STR(
precision mediumpfloat;//精度
varying vec2 vTexCoord;//頂點(diǎn)著色器傳遞的坐標(biāo)
uniform sampler2D yTexture;//輸入的材質(zhì)(不透明灰度,單像素)
? ? ? ? uniform sampler2D uTexture;
? ? ? ? uniform sampler2D vTexture;
voidmain(){
? ? ? ? ? ? vec3 yuv;
? ? ? ? ? ? vec3 rgb;
yuv.r=texture2D(yTexture,vTexCoord).r;
yuv.g=texture2D(uTexture,vTexCoord).r-0.5;
yuv.b=texture2D(vTexture,vTexCoord).r-0.5;
rgb =mat3(1.0,1.0,1.0,
0.0,-0.39465,2.03211,
1.13983,-0.58060,0.0)*yuv;
//輸出像素顏色
gl_FragColor =vec4(rgb,1.0);
? ? ? ? }
);
GLintInitShader(constchar*code, GLint type) {
//創(chuàng)建shader
GLint sh =glCreateShader(type);
if(sh ==0) {
LOGD("glCreateShader %d failed!", type);
return0;
? ? }
//加載shader
glShaderSource(sh,
1,//shader數(shù)量
&code,//shader代碼
0);//代碼長度
//編譯shader
glCompileShader(sh);
//獲取編譯情況
? ? GLint status;
glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
if(status ==0) {
LOGD("glCompileShader failed!");
return0;
? ? }
LOGD("glCompileShader success!");
returnsh;
}
classTestObs:publicChaoObserver{
public:
voidUpdate(ChaoData d) {
//CHAOLOGI("TestObs Update data size is %d", d.size);
? ? }
};
ChaoVideoView *view =NULL;
extern"C"
JNIEXPORT
jintJNI_OnLoad(JavaVM *vm,void*res) {
FFDecode::InitHard(vm);
TestObs *tobs =newTestObs();
ChaoDemux *de =newFFDemux();
de->Open("/sdcard/Movies/1080.mp4");
ChaoDecode *vdecode =newFFDecode();
vdecode->Open(de->GetVPara(),true);
ChaoDecode *adecode =newFFDecode();
adecode->Open(de->GetAPara());
de->AddObs(vdecode);
de->AddObs(adecode);
view =newGLVideoView();
vdecode->AddObs(view);
ChaoResample *resample =newFFResample();
ChaoParameter outPara = de->GetAPara();
resample->Open(de->GetAPara(), outPara);
adecode->AddObs(resample);
ChaoAudioPlay *audioPlay =newSLAudioPlay();
audioPlay->StartPlay(outPara);
resample->AddObs(audioPlay);
de->Start();
vdecode->Start();
adecode->Start();
returnJNI_VERSION_1_4;
}
extern"C"
JNIEXPORT jstring JNICALL
Java_com_lichao_chaoplayer_MainActivity_stringFromJNI(JNIEnv *env, jobject/*this*/) {
std::string hello ="Hello from C++";
//1 創(chuàng)建引擎
SLEngineItf eng =CreateSL();
if(eng){
LOGD("CreateSL success魏身!");
}else{
LOGD("CreateSL failed举户!");
? ? }
//2 創(chuàng)建混音器
SLObjectItf mix =NULL;
SLresult re =0;
re = (*eng)->CreateOutputMix(eng, &mix,0,0,0);//1 引擎? 2 輸出的混音器 345配置項(xiàng)音效
if(re != SL_RESULT_SUCCESS) {
LOGD("SL_RESULT_SUCCESS failed!");
? ? }
re = (*mix)->Realize(mix, SL_BOOLEAN_FALSE);//實(shí)例化對象? 1 對象? 2 等待創(chuàng)建完畢
if(re != SL_RESULT_SUCCESS) {
LOGD("(*mix)->Realize failed!");
? ? }
SLDataLocator_OutputMix outMix = {SL_DATALOCATOR_OUTPUTMIX, mix};//用來存放聲音給音頻
SLDataSink audioSink= {&outMix,0};
//3 配置音頻信息
//緩沖隊(duì)列
SLDataLocator_AndroidSimpleBufferQueue que = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,10};
//音頻格式
? ? SLDataFormat_PCM pcm = {
? ? ? ? ? ? SL_DATAFORMAT_PCM,
2,//聲道數(shù)
? ? ? ? ? ? SL_SAMPLINGRATE_44_1,
? ? ? ? ? ? SL_PCMSAMPLEFORMAT_FIXED_16,
? ? ? ? ? ? SL_PCMSAMPLEFORMAT_FIXED_16,
? ? ? ? ? ? SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT,
SL_BYTEORDER_LITTLEENDIAN//字節(jié)序,小端
? ? };
? ? SLDataSource ds = {&que,&pcm};
//4 創(chuàng)建播放器
SLObjectItf player =NULL;
SLPlayItf iplayer =NULL;
SLAndroidSimpleBufferQueueItf pcmQue =NULL;//存放地址
constSLInterfaceID ids[] = {SL_IID_BUFFERQUEUE};
constSLboolean req[] = {SL_BOOLEAN_TRUE};
//創(chuàng)建播放器 1 引擎? 2 播放器對象? 3 數(shù)據(jù)源信息? 4 混音器? 5? 6? 7
re = (*eng)->CreateAudioPlayer(eng, &player, &ds, &audioSink,sizeof(ids) /sizeof(SLInterfaceID), ids, req);
if(re != SL_RESULT_SUCCESS) {
LOGD("CreateAudioPlayer failed!");
}else{
LOGD("CreateAudioPlayer success!");
? ? }
(*player)->Realize(player, SL_BOOLEAN_FALSE);//實(shí)例化
//獲取player接口
re = (*player)->GetInterface(player, SL_IID_PLAY,&iplayer);
if(re != SL_RESULT_SUCCESS) {
LOGD("GetInterface SL_IID_PLAY failed!");
? ? }
re = (*player)->GetInterface(player, SL_IID_BUFFERQUEUE, &pcmQue);//獲取播放用的接口
if(re != SL_RESULT_SUCCESS) {
LOGD("GetInterface SL_IID_BUFFERQUEUE failed!");
? ? }
//設(shè)置回調(diào)函數(shù)箫津,播放隊(duì)列空調(diào)用
(*pcmQue)->RegisterCallback(pcmQue, PcmCall,0);
//設(shè)置為播放狀態(tài)
(*iplayer)->SetPlayState(iplayer, SL_PLAYSTATE_PLAYING);
//啟動隊(duì)列回調(diào)
(*pcmQue)->Enqueue(pcmQue,"",1);
returnenv->NewStringUTF(hello.c_str());
}
extern"C"
JNIEXPORTvoidJNICALL
Java_com_lichao_chaoplayer_ChaoPlay_Open(JNIEnv *env, jobject instance, jstring url_, jobject surface) {
constchar*path = env->GetStringUTFChars(url_,0);
//初始化解封裝
av_register_all();
//初始化網(wǎng)絡(luò)
avformat_network_init();
avcodec_register_all();
//打開文件
AVFormatContext *ic =NULL;
intre =avformat_open_input(&ic, path,0,0);
if(re !=0) {
//打開失敗輸出錯誤原因
LOGE("avformat_open_input failed!:%s",av_err2str(re));
return;
? ? }
LOGI("avformat_open_input %s success!", path);
//獲取視頻流信息 加這句能保證flv格式視頻(沒格式信息的視頻)
re =avformat_find_stream_info(ic,0);
if(re !=0) {
LOGW("avformat_find_stream_info failed");
? ? }
//duration總時(shí)長微秒? nb_streams流的數(shù)量
LOGW("duration = %lld nb_streams = %d", ic->duration, ic->nb_streams);
//遍歷流信息
intfps =0;//幀率
intvideoStream =0;//視頻流
intaudioStream =1;//音頻流
for(inti =0; i < ic->nb_streams; i++) {
AVStream *as = ic->streams[i];
if(as->codecpar->codec_type== AVMEDIA_TYPE_VIDEO) {
LOGW("視頻數(shù)據(jù)");
? ? ? ? ? ? videoStream = i;
fps =r2d(as->avg_frame_rate);
LOGW("fps = %d, width=%d height=%d codecId=%d pixFormat=%d", fps,
as->codecpar->width,//寬度
as->codecpar->height,//高度
as->codecpar->codec_id,//編碼器
as->codecpar->format//編碼器格式
? ? ? ? ? ? );
}elseif(as->codecpar->codec_type== AVMEDIA_TYPE_AUDIO) {
LOGW("音頻數(shù)據(jù)");
? ? ? ? ? ? audioStream = i;
LOGW("sample_rate=%d channels=%d sample_format=%d",
as->codecpar->sample_rate,//音頻采樣率
as->codecpar->channels,//通道數(shù)
as->codecpar->format//格式
? ? ? ? ? ? );
? ? ? ? }
? ? }
//獲取音頻流數(shù)據(jù)
audioStream =av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, -1, -1,NULL,0);
LOGW("av_find_best_stream audioStream = %d", audioStream);
/*********************************打開視頻解碼器****************************************/
//解碼器--軟解碼
AVCodec *codec =avcodec_find_decoder(ic->streams[videoStream]->codecpar->codec_id);
//硬解碼
codec =avcodec_find_decoder_by_name("h264_mediacodec");
if(!codec) {
LOGW("AVCodec find decoder failed");
return;
? ? }
//視頻解碼器初始化
AVCodecContext *vc =avcodec_alloc_context3(codec);
//復(fù)制視頻
avcodec_parameters_to_context(vc, ic->streams[videoStream]->codecpar);
//線程數(shù)量
vc->thread_count=8;
//打開解碼器
re =avcodec_open2(vc,0,0);
if(re !=0) {
LOGW("avcodec_open2 video failed");
return;
? ? }
/*********************************打開音頻解碼器****************************************/
//軟解碼器
AVCodec *acodec =avcodec_find_decoder(ic->streams[audioStream]->codecpar->codec_id);
if(!acodec) {
LOGW("AVCodec find decoder failed");
return;
? ? }
//視頻解碼器初始化
AVCodecContext *ac =avcodec_alloc_context3(acodec);
//復(fù)制視頻
avcodec_parameters_to_context(ac, ic->streams[audioStream]->codecpar);
//線程數(shù)量
ac->thread_count=8;
//打開解碼器
re =avcodec_open2(ac,0,0);
if(re !=0) {
LOGW("avcodec_open2 audio failed");
return;
? ? }
//讀取幀數(shù)據(jù)
AVPacket *pkt =av_packet_alloc();
AVFrame *frame =av_frame_alloc();
longlongstart =GetNowMs();
intframeCount =0;
//初始化像素格式轉(zhuǎn)換的上下文
SwsContext *vctx =NULL;
intoutWidth =1280;
intoutHeight =720;
char*rgb =newchar[1920*1080*4];
char*pcm =newchar[48000*4*2];
//音頻重采樣上下文初始化
SwrContext *actx =swr_alloc();
actx =swr_alloc_set_opts(actx,
av_get_default_channel_layout(2),//音頻輸出通道數(shù)
AV_SAMPLE_FMT_S16,//輸出格式
ac->sample_rate,//輸出樣本率
av_get_default_channel_layout(ac->channels),//輸入格式
ac->sample_fmt,//輸入格式
ac->sample_rate,//輸入樣本采樣率
0,0);
re =swr_init(actx);
if(re !=0) {
LOGW("swr_init failed!");
}else{
LOGW("swr_init success!");
? ? }
//顯示窗口初始化
ANativeWindow *nwin =ANativeWindow_fromSurface(env, surface);
ANativeWindow_setBuffersGeometry(nwin,outWidth,outHeight, WINDOW_FORMAT_RGBA_8888);
? ? ANativeWindow_Buffer wbuf;
for(;;) {
//超過三秒
if(GetNowMs() - start >=3000) {
LOGW("now decode fps is %d", frameCount /3);
start =GetNowMs();
frameCount =0;
? ? ? ? }
intre =av_read_frame(ic, pkt);
if(re !=0) {
LOGW("讀取到結(jié)尾處!");
//20秒
intpos =20*r2d(ic->streams[videoStream]->time_base);
//跳20秒 往后找和找關(guān)鍵幀
av_seek_frame(ic, videoStream, pos, AVSEEK_FLAG_BACKWARD|AVSEEK_FLAG_FRAME );
continue;
? ? ? ? }
? ? ? ? AVCodecContext *cc = vc;
if(pkt->stream_index== audioStream)
? ? ? ? ? ? cc = ac;
//LOGW("stream = %d size =%d pts=%lld flag=%d", pkt->stream_index, pkt->size, pkt->pts, pkt->flags);
//發(fā)送到線程中解碼
re =avcodec_send_packet(cc, pkt);
//清理
intp = pkt->pts;
av_packet_unref(pkt);
if(re !=0) {
//失敗
LOGW("avcodec_send_packet failed!");
continue;
? ? ? ? }
for(;;) {
re =avcodec_receive_frame(cc, frame);
if(re !=0) {
break;
? ? ? ? ? ? }
//LOGW("avcodec_receive_frame %lld", frame->pts);
//如果是視頻幀
if(cc == vc) {
? ? ? ? ? ? ? ? frameCount++;
//像素格式初始化
vctx =sws_getCachedContext(vctx,
frame->width,
frame->height,
(AVPixelFormat)frame->format,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? outWidth,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? outHeight,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AV_PIX_FMT_RGBA,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? SWS_FAST_BILINEAR,
0,0,0);
if(!vctx) {
LOGW("sws_getCachedContext failed!");
}else{
//顯示大小轉(zhuǎn)換
uint8_t*data[AV_NUM_DATA_POINTERS] = {0};
data[0] =(uint8_t*)rgb;
intlines[AV_NUM_DATA_POINTERS] = {0};//一行寬度的大小
lines[0] = outWidth *4;
inth =sws_scale(vctx,
(constuint8_t**)frame->data,
frame->linesize,0,
frame->height,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? data,lines);
LOGW("sws_scale = %d", h);
if(h >0) {
ANativeWindow_lock(nwin,&wbuf,0);
uint8_t*dst = (uint8_t*)wbuf.bits;
memcpy(dst,rgb,outWidth*outHeight *4);
ANativeWindow_unlockAndPost(nwin);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
}else{
//音頻
uint8_t*out[2] = {0};
out[0] = (uint8_t*) pcm;
//音頻重采樣
intlen =swr_convert(actx,out,
frame->nb_samples,
(constuint8_t**)frame->data,
frame->nb_samples);
LOGW("swr_convert = %d", len);
? ? ? ? ? ? }
? ? ? ? }
? ? }
deletergb;
deletepcm;
//關(guān)閉上下文
avformat_close_input(&ic);
env->ReleaseStringUTFChars(url_, path);
}
extern"C"
JNIEXPORTvoidJNICALL
Java_com_lichao_chaoplayer_ChaoPlay_Yuv(JNIEnv *env, jobject instance, jstring url_, jobject surface) {
constchar*url = env->GetStringUTFChars(url_,0);
LOGD("open url is %s", url);
FILE*fp =fopen(url,"rb");
if(!fp) {
LOGD("open file %s failed!", url);
return;
? ? }
//獲取原始窗口
ANativeWindow *nwin =ANativeWindow_fromSurface(env,surface);
//1 EGL display創(chuàng)建和初始化
EGLDisplay display =eglGetDisplay(EGL_DEFAULT_DISPLAY);//創(chuàng)建
if(display == EGL_NO_DISPLAY) {
LOGD("eglGetDisplay failed!");
return;
? ? }
if(EGL_TRUE !=eglInitialize(display,0,0)) {//初始化
LOGD("eglInitialize failed!");
return;
? ? }
//2 surface
//輸出配置
? ? EGLConfig config;
? ? EGLint configNum;
//輸入配置
? ? EGLint configSpec[] = {
EGL_RED_SIZE,8,
EGL_GREEN_SIZE,8,
EGL_BLUE_SIZE,8,
? ? ? ? ? ? EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE
? ? };
//surface窗口配置
if(EGL_TRUE !=eglChooseConfig(display, configSpec, &config,1, &configNum)) {
LOGD("eglChooseConfig failed!");
return;
? ? }
//創(chuàng)建surface
EGLSurface winSurface =eglCreateWindowSurface(display, config, nwin,0);
if(winSurface == EGL_NO_SURFACE) {
LOGD("eglCreateWindowSurface failed!");
return;
? ? }
//3 context 創(chuàng)建關(guān)聯(lián)的上下文
constEGLint ctxAttr[] = {
EGL_CONTEXT_CLIENT_VERSION,2, EGL_NONE
? ? };
EGLContext context =eglCreateContext(display, config, EGL_NO_CONTEXT, ctxAttr);
if(context == EGL_NO_CONTEXT) {
LOGD("eglCreateContext failed!");
return;
? ? }
if(EGL_TRUE !=eglMakeCurrent(display, winSurface, winSurface, context)) {
LOGD("eglMakeCurrent failed!");
return;
? ? }
LOGD("EGL Init Success!");
//頂點(diǎn)和片元shader初始化
//頂點(diǎn)shader初始化
GLint vsh =InitShader(vertexShader, GL_VERTEX_SHADER);
//片元yuv420 shader初始化
GLint fsh =InitShader(fragYUV420P, GL_FRAGMENT_SHADER);
//創(chuàng)建渲染程序
GLint program =glCreateProgram();
if(program ==0) {
LOGD("glCreateProgram failed!");
return;
? ? }
//渲染程序中加入著色器代碼
glAttachShader(program, vsh);
glAttachShader(program, fsh);
//鏈接程序
glLinkProgram(program);
GLint status =0;
glGetProgramiv(program ,GL_LINK_STATUS, &status);
if(status != GL_TRUE) {
LOGD("glLinkProgram failed!");
return;
? ? }
glUseProgram(program);//激活渲染程序
LOGD("glLinkProgram success!");
/*****************************************************************/
//加入三維頂點(diǎn)數(shù)據(jù) 兩個三角形組成正方形
staticfloatvers[] = {
1.0f,-1.0f,0.0f,
-1.0f,-1.0f,0.0f,
1.0f,1.0f,0.0f,
-1.0f,1.0f,0.0f,
? ? };
GLuint apos = (GLuint)glGetAttribLocation(program,"aPosition");
glEnableVertexAttribArray(apos);
//傳遞頂點(diǎn)
glVertexAttribPointer(apos,3, GL_FLOAT,GL_FALSE,12, vers);
//加入材質(zhì)坐標(biāo)數(shù)據(jù)
staticfloattxts[] = {
1.0f,0.0f,//右下
0.0f,0.0f,
1.0f,1.0f,
0.0,1.0
? ? };
GLuint atex = (GLuint)glGetAttribLocation(program,"aTexCoord");
glEnableVertexAttribArray(atex);
glVertexAttribPointer(atex,2, GL_FLOAT,GL_FALSE,8, txts);
intwidth =424;
intheight =240;
//材質(zhì)紋理初始化
//設(shè)置紋理層
glUniform1i(glGetUniformLocation(program,"yTexture"),0);//對于紋理第1層
glUniform1i(glGetUniformLocation(program,"uTexture"),1);//對于紋理第2層
glUniform1i(glGetUniformLocation(program,"vTexture"),2);//對于紋理第3層
//創(chuàng)建opengl紋理
GLuint texts[3] = {0};
//創(chuàng)建三個紋理
glGenTextures(3, texts);
//設(shè)置紋理屬性
glBindTexture(GL_TEXTURE_2D, texts[0]);
//縮小的過濾器
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//設(shè)置紋理的格式和大小
glTexImage2D(GL_TEXTURE_2D,
0,//細(xì)節(jié)基本 0默認(rèn)
GL_LUMINANCE,//gpu內(nèi)部格式 亮度,灰度圖
width, height,//拉升到全屏
0,//邊框
GL_LUMINANCE,//數(shù)據(jù)的像素格式 亮度宰啦,灰度圖 要與上面一致
GL_UNSIGNED_BYTE,//像素的數(shù)據(jù)類型
NULL//紋理的數(shù)據(jù)
? ? );
//設(shè)置紋理屬性
glBindTexture(GL_TEXTURE_2D, texts[1]);
//縮小的過濾器
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//設(shè)置紋理的格式和大小
glTexImage2D(GL_TEXTURE_2D,
0,//細(xì)節(jié)基本 0默認(rèn)
GL_LUMINANCE,//gpu內(nèi)部格式 亮度苏遥,灰度圖
width/2, height/2,//拉升到全屏
0,//邊框
GL_LUMINANCE,//數(shù)據(jù)的像素格式 亮度,灰度圖 要與上面一致
GL_UNSIGNED_BYTE,//像素的數(shù)據(jù)類型
NULL//紋理的數(shù)據(jù)
? ? );
//設(shè)置紋理屬性
glBindTexture(GL_TEXTURE_2D, texts[2]);
//縮小的過濾器
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//設(shè)置紋理的格式和大小
glTexImage2D(GL_TEXTURE_2D,
0,//細(xì)節(jié)基本 0默認(rèn)
GL_LUMINANCE,//gpu內(nèi)部格式 亮度赡模,灰度圖
width/2, height/2,//拉升到全屏
0,//邊框
GL_LUMINANCE,//數(shù)據(jù)的像素格式 亮度田炭,灰度圖 要與上面一致
GL_UNSIGNED_BYTE,//像素的數(shù)據(jù)類型
NULL//紋理的數(shù)據(jù)
? ? );
/*****************************************************************/
//紋理的修改和顯示
unsignedchar*buf[3] = {0};
buf[0] =newunsignedchar[width * height];
buf[1] =newunsignedchar[width * height /4];
buf[2] =newunsignedchar[width * height /4];
for(inti =0; i <10000; i++) {
//420p? yyyyyyyy uu vv
if(feof(fp) ==0) {
fread(buf[0],1, width*height, fp);
fread(buf[1],1, width*height /4, fp);
fread(buf[2],1, width*height /4, fp);
? ? ? ? }
//激活第1層紋理,綁定到創(chuàng)建的opengl紋理
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texts[0]);
//替換紋理內(nèi)容
glTexSubImage2D(GL_TEXTURE_2D,0,0,0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, buf[0]);
//激活第2層紋理,綁定到創(chuàng)建的opengl紋理
glActiveTexture(GL_TEXTURE0 +1);
glBindTexture(GL_TEXTURE_2D, texts[1]);
//替換紋理內(nèi)容
glTexSubImage2D(GL_TEXTURE_2D,0,0,0, width/2, height/2, GL_LUMINANCE, GL_UNSIGNED_BYTE, buf[1]);
//激活第2層紋理,綁定到創(chuàng)建的opengl紋理
glActiveTexture(GL_TEXTURE0 +2);
glBindTexture(GL_TEXTURE_2D, texts[2]);
//替換紋理內(nèi)容
glTexSubImage2D(GL_TEXTURE_2D,0,0,0, width/2, height/2, GL_LUMINANCE, GL_UNSIGNED_BYTE, buf[2]);
//三維繪制
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
//窗口顯示
eglSwapBuffers(display, winSurface);
? ? }
env->ReleaseStringUTFChars(url_, url);
}
extern"C"
JNIEXPORT jstring JNICALL
Java_com_lichao_chaoplayer_MainActivity_TestJNI(JNIEnv *env, jobject instance) {
std::string hello ="Hello from C++";
returnenv->NewStringUTF(hello.c_str());
}
extern"C"
JNIEXPORTvoidJNICALL
Java_com_lichao_chaoplayer_ChaoPlay_InitView(JNIEnv *env, jobject instance, jobject surface) {
ANativeWindow *win =ANativeWindow_fromSurface(env,surface);
view->SetRender(win);
//ChaoEGL::Get()->Init(win);
//ChaoShader shader;
//shader.Init();
}