标签:jnienv 创建 网络 native count i/o 引用 height tsp
图:杭州西湖
思路:
1、mp3转成pcm(音频数据),ffmpeg做的事
2、OpenSL ES引擎创建AudioPlayer,实际调用了AudioTrack
遇到的错误:
Error #include nested too deeply
原因:c文件互相引用
解决方案:
1、将两个头文件共用的那一部分抽出来单独建一个头文件。
2、加预处理#ifndef.. #define…#endif
x86平台没有编译出来so,怀疑存在版本不兼容,编译别的相关so,x86下没有异常。有空这里再更新下原因
studio写ndk相当方便:
工程结构:
Java代码:
package com.hejunlin.ffmpegaudio;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private EditText mInput;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInput = (EditText) findViewById(R.id.et_input);
mInput.setText("http://qzone.60dj.com/huiyuan/201704/19/201704190533197825_35285.mp3");
findViewById(R.id.bt_play).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NativePlayer.play(mInput.getText().toString().trim());
}
});
findViewById(R.id.bt_pause).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NativePlayer.stop();
}
});
}
}
NativePlayer:
package com.hejunlin.ffmpegaudio;
/**
* Created by hejunlin on 17/5/6.
*/
public class NativePlayer {
static {
System.loadLibrary("NativePlayer");
}
public static native void play(String url);
public static native void stop();
}
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.hejunlin.ffmpegaudio.MainActivity">
<TextView
android:id="@+id/tv_input"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:layout_marginTop="30dp"
android:text="播放链接:"
android:textSize="20sp"/>
<EditText
android:id="@+id/et_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/tv_input"
android:padding="10dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/et_input"
android:orientation="horizontal">
<Button
android:id="@+id/bt_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="60dp"
android:background="@drawable/button_shape"
android:textColor="@color/white"
android:text="播放" />
<Button
android:id="@+id/bt_pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@drawable/button_shape"
android:textColor="@color/white"
android:layout_marginLeft="80dp"
android:text="暂停" />
</LinearLayout>
</RelativeLayout>
jni相关代码: OpenSLESCore.c
//
// Created by hejunlin on 17/5/6.
//
#include "OpenSL_ES_Core.h"
#include "FFmpegCore.h"
#include <assert.h>
#include <jni.h>
#include <string.h>
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
// for native asset manager
#include <sys/types.h>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include "log.h"
// engine interfaces
static SLObjectItf engineObject = NULL;
static SLEngineItf engineEngine;
// output mix interfaces
static SLObjectItf outputMixObject = NULL;
static SLEnvironmentalReverbItf outputMixEnvironmentalReverb = NULL;
// buffer queue player interfaces
static SLObjectItf bqPlayerObject = NULL;
static SLPlayItf bqPlayerPlay;
static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
static SLEffectSendItf bqPlayerEffectSend;
static SLMuteSoloItf bqPlayerMuteSolo;
static SLVolumeItf bqPlayerVolume;
// aux effect on the output mix, used by the buffer queue player
static const SLEnvironmentalReverbSettings reverbSettings =
SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;
static void *buffer;
static size_t bufferSize;
// this callback handler is called every time a buffer finishes playing
void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
{
LOGD(">> buffere queue callback");
assert(bq == bqPlayerBufferQueue);
bufferSize = 0;
//assert(NULL == context);
getPCM(&buffer, &bufferSize);
// for streaming playback, replace this test by logic to find and fill the next buffer
if (NULL != buffer && 0 != bufferSize) {
SLresult result;
// enqueue another buffer
result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer,
bufferSize);
// the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
// which for this code example would indicate a programming error
assert(SL_RESULT_SUCCESS == result);
(void)result;
}
}
void initOpenSLES()
{
LOGD(">> initOpenSLES...");
SLresult result;
// 1、create engine
result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
LOGD(">> initOpenSLES... step 1, result = %d", result);
// 2、realize the engine
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
LOGD(">> initOpenSLES...step 2, result = %d", result);
// 3、get the engine interface, which is needed in order to create other objects
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
LOGD(">> initOpenSLES...step 3, result = %d", result);
// 4、create output mix, with environmental reverb specified as a non-required interface
const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
const SLboolean req[1] = {SL_BOOLEAN_FALSE};
result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0);
LOGD(">> initOpenSLES...step 4, result = %d", result);
// 5、realize the output mix
result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
LOGD(">> initOpenSLES...step 5, result = %d", result);
// 6、get the environmental reverb interface
// this could fail if the environmental reverb effect is not available,
// either because the feature is not present, excessive CPU load, or
// the required MODIFY_AUDIO_SETTINGS permission was not requested and granted
result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB,
&outputMixEnvironmentalReverb);
if (SL_RESULT_SUCCESS == result) {
result = (*outputMixEnvironmentalReverb)->SetEnvironmentalReverbProperties(
outputMixEnvironmentalReverb, &reverbSettings);
LOGD(">> initOpenSLES...step 6, result = %d", result);
}
}
// init buffer queue
void initBufferQueue(int rate, int channel, int bitsPerSample)
{
LOGD(">> initBufferQueue");
SLresult result;
// configure audio source
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
SLDataFormat_PCM format_pcm;
format_pcm.formatType = SL_DATAFORMAT_PCM;
format_pcm.numChannels = channel;
format_pcm.samplesPerSec = rate * 1000;
format_pcm.bitsPerSample = bitsPerSample;
format_pcm.containerSize = 16;
if (channel == 2)
format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
else
format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER;
format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
SLDataSource audioSrc = {&loc_bufq, &format_pcm};
// configure audio sink
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
SLDataSink audioSnk = {&loc_outmix, NULL};
// create audio player
const SLInterfaceID ids[3] = {SL_IID_BUFFERQUEUE, SL_IID_EFFECTSEND,
/*SL_IID_MUTESOLO,*/ SL_IID_VOLUME};
const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE,
/*SL_BOOLEAN_TRUE,*/ SL_BOOLEAN_TRUE};
result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk,
3, ids, req);
assert(SL_RESULT_SUCCESS == result);
(void)result;
// realize the player
result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
assert(SL_RESULT_SUCCESS == result);
(void)result;
// get the play interface
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
assert(SL_RESULT_SUCCESS == result);
(void)result;
// get the buffer queue interface
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE,
&bqPlayerBufferQueue);
assert(SL_RESULT_SUCCESS == result);
(void)result;
// register callback on the buffer queue
result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL);
assert(SL_RESULT_SUCCESS == result);
(void)result;
// get the effect send interface
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_EFFECTSEND,
&bqPlayerEffectSend);
assert(SL_RESULT_SUCCESS == result);
(void)result;
// get the volume interface
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
assert(SL_RESULT_SUCCESS == result);
(void)result;
// set the player‘s state to playing
result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
assert(SL_RESULT_SUCCESS == result);
(void)result;
}
// stop the native audio system
void stop()
{
// destroy buffer queue audio player object, and invalidate all associated interfaces
if (bqPlayerObject != NULL) {
(*bqPlayerObject)->Destroy(bqPlayerObject);
bqPlayerObject = NULL;
bqPlayerPlay = NULL;
bqPlayerBufferQueue = NULL;
bqPlayerEffectSend = NULL;
bqPlayerMuteSolo = NULL;
bqPlayerVolume = NULL;
}
// destroy output mix object, and invalidate all associated interfaces
if (outputMixObject != NULL) {
(*outputMixObject)->Destroy(outputMixObject);
outputMixObject = NULL;
outputMixEnvironmentalReverb = NULL;
}
// destroy engine object, and invalidate all associated interfaces
if (engineObject != NULL) {
(*engineObject)->Destroy(engineObject);
engineObject = NULL;
engineEngine = NULL;
}
// 释放FFmpeg解码器
releaseFFmpeg();
}
void play(char *url)
{
int rate, channel;
LOGD("...get url=%s", url);
// 1、初始化FFmpeg解码器
initFFmpeg(&rate, &channel, url);
// 2、初始化OpenSLES
initOpenSLES();
// 3、初始化BufferQueue
initBufferQueue(rate, channel, SL_PCMSAMPLEFORMAT_FIXED_16);
// 4、启动音频播放
bqPlayerCallback(bqPlayerBufferQueue, NULL);
}
FFmpegCore.c
#include "log.h"
#include "FFmpegCore.h"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
#include "libavutil/samplefmt.h"
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
uint8_t *outputBuffer;
size_t outputBufferSize;
AVPacket packet;
int audioStream;
AVFrame *aFrame;
SwrContext *swr;
AVFormatContext *aFormatCtx;
AVCodecContext *aCodecCtx;
int initFFmpeg(int *rate, int *channel, char *url) {
av_register_all();
aFormatCtx = avformat_alloc_context();
LOGD("ffmpeg get url=:%s", url);
// 网络音频流
char *file_name = url;
// Open audio file
if (avformat_open_input(&aFormatCtx, file_name, NULL, NULL) != 0) {
LOGE("Couldn‘t open file:%s\n", file_name);
return -1; // Couldn‘t open file
}
// Retrieve stream information
if (avformat_find_stream_info(aFormatCtx, NULL) < 0) {
LOGE("Couldn‘t find stream information.");
return -1;
}
// Find the first audio stream
int i;
audioStream = -1;
for (i = 0; i < aFormatCtx->nb_streams; i++) {
if (aFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
audioStream < 0) {
audioStream = i;
}
}
if (audioStream == -1) {
LOGE("Couldn‘t find audio stream!");
return -1;
}
// Get a pointer to the codec context for the video stream
aCodecCtx = aFormatCtx->streams[audioStream]->codec;
// Find the decoder for the audio stream
AVCodec *aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
if (!aCodec) {
fprintf(stderr, "Unsupported codec!\n");
return -1;
}
if (avcodec_open2(aCodecCtx, aCodec, NULL) < 0) {
LOGE("Could not open codec.");
return -1; // Could not open codec
}
aFrame = av_frame_alloc();
// 设置格式转换
swr = swr_alloc();
av_opt_set_int(swr, "in_channel_layout", aCodecCtx->channel_layout, 0);
av_opt_set_int(swr, "out_channel_layout", aCodecCtx->channel_layout, 0);
av_opt_set_int(swr, "in_sample_rate", aCodecCtx->sample_rate, 0);
av_opt_set_int(swr, "out_sample_rate", aCodecCtx->sample_rate, 0);
av_opt_set_sample_fmt(swr, "in_sample_fmt", aCodecCtx->sample_fmt, 0);
av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
swr_init(swr);
// 分配PCM数据缓存
outputBufferSize = 8196;
outputBuffer = (uint8_t *) malloc(sizeof(uint8_t) * outputBufferSize);
// 返回sample rate和channels
*rate = aCodecCtx->sample_rate;
*channel = aCodecCtx->channels;
return 0;
}
// 获取PCM数据, 自动回调获取
int getPCM(void **pcm, size_t *pcmSize) {
LOGD(">> getPcm");
while (av_read_frame(aFormatCtx, &packet) >= 0) {
int frameFinished = 0;
// Is this a packet from the audio stream?
if (packet.stream_index == audioStream) {
avcodec_decode_audio4(aCodecCtx, aFrame, &frameFinished, &packet);
if (frameFinished) {
// data_size为音频数据所占的字节数
int data_size = av_samples_get_buffer_size(
aFrame->linesize, aCodecCtx->channels,
aFrame->nb_samples, aCodecCtx->sample_fmt, 1);
LOGD(">> getPcm data_size=%d", data_size);
// 这里内存再分配可能存在问题
if (data_size > outputBufferSize) {
outputBufferSize = data_size;
outputBuffer = (uint8_t *) realloc(outputBuffer,
sizeof(uint8_t) * outputBufferSize);
}
// 音频格式转换
swr_convert(swr, &outputBuffer, aFrame->nb_samples,
(uint8_t const **) (aFrame->extended_data),
aFrame->nb_samples);
// 返回pcm数据
*pcm = outputBuffer;
*pcmSize = data_size;
return 0;
}
}
}
return -1;
}
// 释放相关资源
int releaseFFmpeg()
{
av_packet_unref(&packet);
av_free(outputBuffer);
av_free(aFrame);
avcodec_close(aCodecCtx);
avformat_close_input(&aFormatCtx);
return 0;
NativePlayer.c
//
// Created by hejunlin on 17/5/6.
//
#include "log.h"
#include "com_hejunlin_ffmpegaudio_NativePlayer.h"
#include "OpenSL_ES_Core.h"
JNIEXPORT void JNICALL
Java_com_hejunlin_ffmpegaudio_NativePlayer_play(JNIEnv *env, jclass type, jstring url_) {
const char *url = (*env)->GetStringUTFChars(env, url_, 0);
LOGD("start playaudio... url=%s", url);
play(url);
(*env)->ReleaseStringUTFChars(env, url_, url);
}
JNIEXPORT void JNICALL
Java_com_hejunlin_ffmpegaudio_NativePlayer_stop(JNIEnv *env, jclass type) {
LOGD("stop");
stop();
}
通过cmake,或ndk-build都可以编译,会生成一个NativePlayer.so
效果图:
log输出如下:
05-07 10:14:04.573 D/Surface: Surface::setBuffersDimensions(this=0xf45b6300,w=1080,h=1920)
05-07 10:14:04.577 W/linker: libNativePlayer.so: unused DT entry: type 0x6ffffffe arg 0x1414
05-07 10:14:04.577 W/linker: libNativePlayer.so: unused DT entry: type 0x6fffffff arg 0x4
05-07 10:14:04.578 W/linker: libavcodec-57.so: unused DT entry: type 0x6ffffffe arg 0x5da4
05-07 10:14:04.578 W/linker: libavcodec-57.so: unused DT entry: type 0x6fffffff arg 0x2
05-07 10:14:04.578 W/linker: libavformat-57.so: unused DT entry: type 0x6ffffffe arg 0x6408
05-07 10:14:04.578 W/linker: libavformat-57.so: unused DT entry: type 0x6fffffff arg 0x2
05-07 10:14:04.578 W/linker: libswresample-2.so: unused DT entry: type 0x6ffffffe arg 0xcd4
05-07 10:14:04.578 W/linker: libswresample-2.so: unused DT entry: type 0x6fffffff arg 0x1
05-07 10:14:04.578 W/linker: libswscale-4.so: unused DT entry: type 0x6ffffffe arg 0xd70
05-07 10:14:04.578 W/linker: libswscale-4.so: unused DT entry: type 0x6fffffff arg 0x1
05-07 10:14:04.589 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/NativePlayer.c: Java_com_hejunlin_ffmpegaudio_NativePlayer_play:start playaudio... url=http://qzone.60dj.com/huiyuan/201704/19/201704190533197825_35285.mp3
05-07 10:14:04.589 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: play:...get url=http://qzone.60dj.com/huiyuan/201704/19/201704190533197825_35285.mp3
05-07 10:14:04.590 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: initFFmpeg:ffmpeg get url=:http://qzone.60dj.com/huiyuan/201704/19/201704190533197825_35285.mp3
05-07 10:14:04.696 D/libc-netbsd: getaddrinfo: qzone.60dj.com get result from proxy >>
05-07 10:14:04.949 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: initOpenSLES:>> initOpenSLES...
05-07 10:14:04.950 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: initOpenSLES:>> initOpenSLES... step 1, result = 0
05-07 10:14:04.950 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: initOpenSLES:>> initOpenSLES...step 2, result = 0
05-07 10:14:04.950 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: initOpenSLES:>> initOpenSLES...step 3, result = 0
05-07 10:14:04.950 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: initOpenSLES:>> initOpenSLES...step 4, result = 0
05-07 10:14:04.950 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: initOpenSLES:>> initOpenSLES...step 5, result = 0
05-07 10:14:04.950 W/libOpenSLES: Leaving Object::GetInterface (SL_RESULT_FEATURE_UNSUPPORTED)
05-07 10:14:04.950 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: initBufferQueue:>> initBufferQueue
05-07 10:14:04.951 V/AudioTrack: set(): streamType 3, sampleRate 44100, format 0x1, channelMask 0x3, frameCount 0, flags #0, notificationFrames 0, sessionId 774, transferType 0
05-07 10:14:04.951 V/AudioTrack: set() streamType 3 frameCount 0 flags 0000
05-07 10:14:04.951 D/AudioTrack: audiotrack 0xf459cd80 set Type 3, rate 44100, fmt 1, chn 3, fcnt 0, flags 0000
05-07 10:14:04.951 D/AudioTrack: mChannelMask 0x3
05-07 10:14:04.953 V/AudioTrack: createTrack_l() output 2 afLatency 21
05-07 10:14:04.953 V/AudioTrack: afFrameCount=1024, minBufCount=1, afSampleRate=48000, afLatency=21
05-07 10:14:04.953 V/AudioTrack: minFrameCount: 2822, afFrameCount=1024, minBufCount=3, sampleRate=44100, afSampleRate=48000, afLatency=21
05-07 10:14:04.954 D/AudioTrackCenter: addTrack, trackId:0xdaf0c000, frameCount:2822, sampleRate:44100, trackPtr:0xf459cd80
05-07 10:14:04.954 D/AudioTrackCenter: mAfSampleRate 48000, sampleRate 44100, AfFrameCount 1024 , mAfSampleRate 48000, frameCount 2822
05-07 10:14:04.979 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: bqPlayerCallback:>> buffere queue callback
05-07 10:14:04.979 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:>> getPcm
05-07 10:14:04.979 D/AudioTrackShared: front(0x0), mIsOut 1, avail 2822, mFrameCount 2822, filled 0
05-07 10:14:04.979 V/AudioTrack: obtainBuffer(940) returned 2822 = 940 + 1882 err 0
05-07 10:14:04.979 D/AudioTrackShared: front(0x0), mIsOut 1, interrupt() FUTEX_WAKE
05-07 10:14:04.979 D/AudioTrack: audiotrack 0xf459cd80 stop done
05-07 10:14:04.980 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:>> getPcm data_size=188
05-07 10:14:04.980 D/AudioTrackShared: front(0x0), mIsOut 1, avail 2822, mFrameCount 2822, filled 0
05-07 10:14:04.980 V/AudioTrack: obtainBuffer(940) returned 2822 = 940 + 1882 err 0
05-07 10:14:04.980 D/AudioTrackShared: front(0x0), mIsOut 1, avail 2775, mFrameCount 2822, filled 47
05-07 10:14:04.980 V/AudioTrack: obtainBuffer(893) returned 2775 = 893 + 1882 err 0
05-07 10:14:04.980 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: bqPlayerCallback:>> buffere queue callback
05-07 10:14:04.980 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:>> getPcm
05-07 10:14:04.980 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:>> getPcm data_size=4608
05-07 10:14:04.980 D/AudioTrackShared: front(0x0), mIsOut 1, avail 1882, mFrameCount 2822, filled 940
05-07 10:14:04.980 V/AudioTrack: obtainBuffer(940) returned 1882 = 940 + 942 err 0
05-07 10:14:04.980 D/AudioTrackShared: front(0x0), mIsOut 1, avail 1623, mFrameCount 2822, filled 1199
05-07 10:14:04.980 V/AudioTrack: obtainBuffer(681) returned 1623 = 681 + 942 err 0
05-07 10:14:04.980 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: bqPlayerCallback:>> buffere queue callback
05-07 10:14:04.980 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:>> getPcm
05-07 10:14:04.981 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:>> getPcm data_size=4608
05-07 10:14:04.981 D/AudioTrackShared: front(0x0), mIsOut 1, avail 942, mFrameCount 2822, filled 1880
05-07 10:14:04.981 V/AudioTrack: obtainBuffer(940) returned 942 = 940 + 2 err 0
05-07 10:14:04.981 D/AudioTrackShared: front(0x0), mIsOut 1, avail 471, mFrameCount 2822, filled 2351
05-07 10:14:04.981 V/AudioTrack: obtainBuffer(469) returned 471 = 469 + 2 err 0
05-07 10:14:04.981 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/OpenSL_ES_Core.c: bqPlayerCallback:>> buffere queue callback
05-07 10:14:04.981 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:>> getPcm
05-07 10:14:04.981 D//Users/hejunlin/AndroidStudioProjects/FFmpegAudio/app/src/main/jni/FFmpegCore.c: getPCM:>> getPcm data_size=4608
http://blog.renren.com/blog/937184755/994083793
http://blog.renren.com/blog/937184755/994083886
http://blog.renren.com/blog/937184755/994084167
http://gamebbs.51.com/thread-324928-1-1.html
http://blog.163.com/m13094739605_1/blog/static/27240604620174100133493/
http://blog.163.com/m13094739605_1/blog/static/2724060462017410028912/
http://blog.163.com/m13094739605_1/blog/static/27240604620174100237428/
http://blog.163.com/m13094739605_1/blog/static/27240604620174100315903/
http://www.230la.com/com/wz801234567/news/itemid-3253535.html
FFmpeg总结(十一)用ffmpeg进行转格式,Android下播放网络音频流
标签:jnienv 创建 网络 native count i/o 引用 height tsp
原文地址:http://www.cnblogs.com/wz901881/p/6833452.html