http://bbs.csdn.net/topics/390899416
#include <string.h>
#include <jni.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <android/log.h>
//#include "codes_orion_swplayer_MediaObj.h"
#define FILENAME_MAXLEN 1024
#define null NULL
char
fileName[FILENAME_MAXLEN];
AVFormatContext *pFormatCtx=NULL;
AVCodecContext *pCodecCtx=NULL;
AVCodec *pCodec=NULL;
AVPacket avpkt;
AVFrame *avfrm;
int
audioStream;
size_t
data_size;
JNIEXPORT
void
JNICALL Java_codes_orion_swplayer_MediaObj_openFile
(JNIEnv * env, jobject obj, jstring jfileName) {
//Convert filename
strncpy
(fileName,(*env)->GetStringUTFChars(env,jfileName,0),FILENAME_MAXLEN);
//open file to AVFormatContext
if
(avformat_open_input(&pFormatCtx, fileName, NULL, NULL)!=0) {
__android_log_print(ANDROID_LOG_DEBUG, null,
"fail to open file"
);
}
if
(avformat_find_stream_info(pFormatCtx,NULL)<0) {
__android_log_print(ANDROID_LOG_DEBUG, null,
"fail to open track"
);
}
//Find Stream
int
i;
audioStream=-1;
for
(i=0;i<pFormatCtx->nb_streams; i++) {
if
(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
audioStream=i;
break
;
}
//TODO:Check Video track
}
if
(audioStream == -1) {
__android_log_print(ANDROID_LOG_DEBUG, null,
"fail to open track"
);
}
//find decoder
pCodecCtx=pFormatCtx->streams[audioStream]->codec;
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if
(pCodec==NULL) {
__android_log_print(ANDROID_LOG_DEBUG, null,
"fail to find decoder"
);
}
if
(pCodec->capabilities & CODEC_CAP_TRUNCATED)
pCodecCtx->flags|=CODEC_FLAG_TRUNCATED;
if
(avcodec_open2(pCodecCtx, pCodec,NULL)<0) {
__android_log_print(ANDROID_LOG_DEBUG, null,
"fail to open decoder"
);
}
__android_log_print(ANDROID_LOG_DEBUG, null,
"File opened:\n decoder: %s"
,pCodec->name);
}
char
*arr=NULL;
jbyteArray jarr;
JNIEXPORT jbyteArray JNICALL Java_codes_orion_swplayer_MediaObj_stream
(JNIEnv* env, jobject obj, jint minbufsize) {
data_size=0;
if
(!arr) {
arr=
malloc
(
sizeof
(
char
)*minbufsize*2);
}
while
(data_size<minbufsize) {
//__android_log_print(ANDROID_LOG_DEBUG, null, "reading");
for
(;;) {
if
(av_read_frame(pFormatCtx,&avpkt)<0) {
__android_log_print(ANDROID_LOG_DEBUG, null,
"cannot read packet"
);
data_size=0;
free
(arr);
arr=NULL;
return
;
}
if
(avpkt.stream_index!=audioStream) {
av_free_packet(&avpkt);
continue
;
}
break
;
}
int
got_frame=0,len;
len = avcodec_decode_audio4(pCodecCtx,avfrm,&got_frame,&avpkt);
if
(len < 0) {
__android_log_print(ANDROID_LOG_DEBUG, null,
"packet len<0"
);
break
;
}
if
(got_frame) {
int
dsize = av_samples_get_buffer_size(NULL,pCodecCtx->channels,
avfrm->nb_samples,
pCodecCtx->sample_fmt, 1);
memcpy
(arr+data_size,avfrm->data[0],dsize);
data_size+=dsize;
av_free_packet(&avpkt);
}
else
break
;
}
__android_log_print(ANDROID_LOG_DEBUG, null,
"minbuf: %d, data_size: %d"
,minbufsize,data_size);
jarr= (*env)->NewByteArray(env,data_size);
(*env)->SetByteArrayRegion(env,jarr, 0,data_size,(jbyte*)arr);
return
jarr;
}
JNIEXPORT jint JNICALL Java_codes_orion_swplayer_MediaObj_data_1size
(JNIEnv *env, jobject obj) {
return
(jint)data_size;
}
JNIEXPORT jint JNICALL Java_codes_orion_swplayer_MediaObj_getSampleRate
(JNIEnv *env, jobject obj) {
if
(pCodecCtx)
return
(jint)(pCodecCtx->sample_rate);
}
JNIEXPORT jint JNICALL Java_codes_orion_swplayer_MediaObj_getChannel
(JNIEnv *env, jobject obj) {
if
(pCodecCtx)
return
(jint)(pCodecCtx->channels);
}
JNIEXPORT
void
JNICALL Java_codes_orion_swplayer_MediaObj_JNIinit
(JNIEnv *env, jobject obj) {
//init
av_register_all();
avcodec_register_all();
avfrm=av_frame_alloc();
av_init_packet(&avpkt);
}
JNIEXPORT
void
JNICALL Java_codes_orion_swplayer_MediaObj_JNIexit
(JNIEnv *env, jobject obj) {
av_frame_free(&avfrm);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
avformat_free_context(pFormatCtx);
free
(arr);
arr=NULL;
}
|
MediaObj.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
package
codes.orion.swplayer;
import
java.io.IOException;
import
android.media.AudioTrack;
import
android.media.AudioFormat;
import
android.os.Handler;
import
android.util.Log;
public
class
MediaObj {
private
AudioTrack audioTrack;
private
Handler handler =
new
Handler();
private
Runnable updateThread =
new
Runnable(){
public
void
run() {
byte
[] bytes=stream(minbufsize);
int
dsize=data_size();
if
(audioTrack.write(bytes,
0
, dsize)<dsize) {
Log.w(
null
,
"Data not written completely"
);
}
handler.postDelayed(updateThread,
50
);
}
};
private
int
samplerate,channeltype,minbufsize;
public
void
setDataSource(String sourceFile)
throws
IOException {
openFile(sourceFile);
samplerate=getSampleRate();
if
(getChannel()==
1
)
channeltype=AudioFormat.CHANNEL_OUT_MONO;
else
channeltype=AudioFormat.CHANNEL_OUT_STEREO;
minbufsize=AudioTrack.getMinBufferSize (samplerate, channeltype, AudioFormat.ENCODING_PCM_16BIT);
audioTrack =
new
AudioTrack(android.media.AudioManager.STREAM_MUSIC,samplerate,channeltype,
AudioFormat.ENCODING_PCM_16BIT,
minbufsize*
2
,
AudioTrack.MODE_STREAM);
}
public
void
prepare() {
}
public
void
play() {
handler.post(updateThread);
audioTrack.play();
}
public
MediaObj() {
JNIinit();
}
@Override
protected
void
finalize()
throws
Throwable {
JNIexit();
handler.removeCallbacks(updateThread);
super
.finalize();
}
public
native
byte
[] stream(
int
minbufsize);
public
native
int
data_size();
public
native
void
openFile(String sourceFile)
throws
IOException;
public
native
int
getSampleRate();
public
native
int
getChannel();
public
native
void
JNIinit();
public
native
void
JNIexit();
static
{
System.loadLibrary(
"mediaobj-jni"
);
}
}
|