我以标准格式使用MediaCodec,例如:
public void run() {
MediaExtractor extractor = new MediaExtractor();
try {
extractor.setDataSource("/sdcard/video-only.mpg");
} catch (Exception e1) {
}
MediaFormat format = extractor.getTrackFormat(0);
extractor.selectTrack(0);
MediaCodec decoder = MediaCodec.createDecoderByType("video/avc");
decoder.configure(format, mSurface, null, 0);
decoder.start();
ByteBuffer[] inputBuffers = decoder.getInputBuffers();
ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
BufferInfo info = new BufferInfo();
boolean isEOS = false;
long startMs = System.currentTimeMillis();
while (!Thread.interrupted()) {
if (!isEOS) {
int inIndex = decoder.dequeueInputBuffer(10000);
if (inIndex >= 0) {
ByteBuffer buffer = inputBuffers[inIndex];
int sampleSize = extractor.readSampleData(buffer, 0);
if (sampleSize < 0) {
decoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isEOS = true;
} else {
decoder.queueInputBuffer(inIndex, 0, sampleSize, extractor.getSampleTime(), 0);
extractor.advance();
}
}
}
int outIndex = decoder.dequeueOutputBuffer(info, 10000);
switch (outIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
outputBuffers = decoder.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
break;
default:
ByteBuffer buffer = outputBuffers[outIndex];
while (info.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) {
try {
Thread.sleep(10);
} catch (Exception e) {
break;
}
}
decoder.releaseOutputBuffer(outIndex, true);
break;
}
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0)
break;
}
decoder.stop();
decoder.release();
extractor.release();
}
我现在从在JNI中运行的SEPARATE线程获取输入缓冲区。在这个线程中,我收到一个回调,我得到(已经解析的)h264数据。我打算将java代码修改为以下内容(不再提取器):
public void run() {
MediaFormat format = MediaFormat format = MediaFormat.createVideoFormat("video/avc", 640, 480);
MediaCodec decoder = MediaCodec.createDecoderByType("video/avc");
decoder.configure(format, mSurface, null, 0);
decoder.start();
ByteBuffer[] inputBuffers = decoder.getInputBuffers();
ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
BufferInfo info = new BufferInfo();
boolean isEOS = false;
long startMs = System.currentTimeMillis();
while (!Thread.interrupted()) {
if (!isEOS) {
int inIndex = decoder.dequeueInputBuffer(10000);
if (inIndex >= 0) {
ByteBuffer buffer = inputBuffers[inIndex];
int sampleSize = ??????? // How to memcpy from JNI
if (sampleSize < 0) {
decoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isEOS = true;
}
}
}
int outIndex = decoder.dequeueOutputBuffer(info, 10000);
switch (outIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
outputBuffers = decoder.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
break;
default:
ByteBuffer buffer = outputBuffers[outIndex];
while (info.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) {
try {
Thread.sleep(10);
} catch (Exception e) {
break;
}
}
decoder.releaseOutputBuffer(outIndex, true);
break;
}
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0)
break;
}
decoder.stop();
decoder.release();
}
在JNI代码中,我收到以下回调:
static void callback_with_buffer (uint8 *buffer, uint size) {
}
我应该怎么做才能将JNI缓冲区memcpy到Java inputBuffers [inIndex],特别是在两个线程都没有真正同步的约束下?
答案 0 :(得分:1)
在JNI:
JNIEnv *env = get_jni_env();
jbyteArray jBuf = (*env)->NewByteArray(env, map.size);
(*env)->SetByteArrayRegion(env, jBuf, 0, map.size, (jbyte*) map.data);
(*env)->CallVoidMethod(env, data->app, set_buffer_method_id, jBuf);
if ((*env)->ExceptionCheck(env)) {
GST_ERROR("Failed to call Java method");
(*env)->ExceptionClear(env);
}
(*env)->DeleteLocalRef(env, jBuf);
在Java中:
public LinkedList<byte[]> mData = new LinkedList<byte[]>();
private void setBuffer(byte[] buf) {
mData.add(buf);
}
在MediaCodec解码器线程中:
ByteBuffer buffer = inputBuffers[inIndex];
int sampleSize = 0;
buffer.clear();
while (!((IVESampleActivity) mContext).mData.isEmpty()) {
byte[] buf = ((IVESampleActivity) mContext).mData.removeFirst();
buffer.put(buf);
sampleSize += buf.length;
}
我想知道我是否可以避免一些重复...