Android FFmpeg

#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();

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市漓柑,隨后出現(xiàn)的幾起案子诫肠,更是在濱河造成了極大的恐慌,老刑警劉巖欺缘,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件栋豫,死亡現(xiàn)場離奇詭異,居然都是意外死亡谚殊,警方通過查閱死者的電腦和手機(jī)丧鸯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嫩絮,“玉大人丛肢,你說我怎么就攤上這事〗烁桑” “怎么了蜂怎?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長置尔。 經(jīng)常有香客問我杠步,道長,這世上最難降的妖魔是什么榜轿? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任幽歼,我火速辦了婚禮,結(jié)果婚禮上谬盐,老公的妹妹穿的比我還像新娘甸私。我一直安慰自己,他們只是感情好飞傀,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布皇型。 她就那樣靜靜地躺著诬烹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪弃鸦。 梳的紋絲不亂的頭發(fā)上绞吁,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機(jī)與錄音寡键,去河邊找鬼。 笑死雪隧,一個胖子當(dāng)著我的面吹牛西轩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播脑沿,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼藕畔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了庄拇?” 一聲冷哼從身側(cè)響起注服,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎措近,沒想到半個月后溶弟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瞭郑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年辜御,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屈张。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡擒权,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出阁谆,到底是詐尸還是另有隱情碳抄,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布场绿,位于F島的核電站剖效,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏焰盗。R本人自食惡果不足惜贱鄙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望姨谷。 院中可真熱鬧逗宁,春花似錦、人聲如沸梦湘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至哼拔,卻和暖如春引有,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背倦逐。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工譬正, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人檬姥。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓曾我,卻偏偏與公主長得像,于是被迫代替她去往敵國和親健民。 傳聞我的和親對象是個殘疾皇子抒巢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容