You've already forked android_translation_layer
mirror of
https://gitlab.com/android_translation_layer/android_translation_layer.git
synced 2025-10-27 11:48:10 -07:00
MediaCodec: handle end-of-file properly
This commit is contained in:
@@ -7,6 +7,8 @@
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
#undef android_media_MediaCodec_BUFFER_FLAG_END_OF_STREAM
|
||||||
|
#define android_media_MediaCodec_BUFFER_FLAG_END_OF_STREAM 4L
|
||||||
/*
|
/*
|
||||||
* Class: android_media_MediaCodec
|
* Class: android_media_MediaCodec
|
||||||
* Method: native_constructor
|
* Method: native_constructor
|
||||||
|
|||||||
@@ -425,22 +425,26 @@ JNIEXPORT void JNICALL Java_android_media_MediaCodec_native_1start(JNIEnv *env,
|
|||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_android_media_MediaCodec_native_1queueInputBuffer(JNIEnv *env, jobject this, jlong codec, jobject buffer, jlong presentationTimeUs)
|
JNIEXPORT jint JNICALL Java_android_media_MediaCodec_native_1queueInputBuffer(JNIEnv *env, jobject this, jlong codec, jobject buffer, jlong presentationTimeUs)
|
||||||
{
|
{
|
||||||
jarray array_ref;
|
jarray array_ref = NULL;
|
||||||
jbyte *array;
|
jbyte *array = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
struct ATL_codec_context *ctx = _PTR(codec);
|
struct ATL_codec_context *ctx = _PTR(codec);
|
||||||
AVCodecContext *codec_ctx = ctx->codec;
|
AVCodecContext *codec_ctx = ctx->codec;
|
||||||
AVPacket *pkt = av_packet_alloc();
|
AVPacket *pkt = NULL;
|
||||||
|
if (buffer) { // buffer can be null if we're sending EOF
|
||||||
|
pkt = av_packet_alloc();
|
||||||
pkt->size = get_nio_buffer_size(env, buffer);
|
pkt->size = get_nio_buffer_size(env, buffer);
|
||||||
pkt->data = get_nio_buffer(env, buffer, &array_ref, &array);
|
pkt->data = get_nio_buffer(env, buffer, &array_ref, &array);
|
||||||
pkt->pts = presentationTimeUs;
|
pkt->pts = presentationTimeUs;
|
||||||
|
}
|
||||||
ret = avcodec_send_packet(codec_ctx, pkt);
|
ret = avcodec_send_packet(codec_ctx, pkt);
|
||||||
if (ret < 0 && ret != AVERROR(EAGAIN)) {
|
if (ret < 0 && ret != AVERROR(EAGAIN)) {
|
||||||
fprintf(stderr, "Error while sending packet: %d = %s\n", ret, av_err2str(ret));
|
fprintf(stderr, "Error while sending packet: %d = %s\n", ret, av_err2str(ret));
|
||||||
}
|
}
|
||||||
|
if (buffer) {
|
||||||
release_nio_buffer(env, array_ref, array);
|
release_nio_buffer(env, array_ref, array);
|
||||||
av_packet_free(&pkt);
|
av_packet_free(&pkt);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,6 +459,14 @@ JNIEXPORT jint JNICALL Java_android_media_MediaCodec_native_1dequeueOutputBuffer
|
|||||||
|
|
||||||
ret = avcodec_receive_frame(codec_ctx, frame);
|
ret = avcodec_receive_frame(codec_ctx, frame);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
if (ret == AVERROR_EOF) {
|
||||||
|
_SET_INT_FIELD(buffer_info, "flags", android_media_MediaCodec_BUFFER_FLAG_END_OF_STREAM);
|
||||||
|
_SET_INT_FIELD(buffer_info, "offset", 0);
|
||||||
|
_SET_INT_FIELD(buffer_info, "size", 0);
|
||||||
|
_SET_LONG_FIELD(buffer_info, "presentationTimeUs", 0);
|
||||||
|
av_frame_free(&frame);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (ret != AVERROR(EAGAIN)) {
|
if (ret != AVERROR(EAGAIN)) {
|
||||||
printf("avcodec_receive_frame returned %d\n", ret);
|
printf("avcodec_receive_frame returned %d\n", ret);
|
||||||
printf("frame->data = %p frame->nb_samples = %d\n", frame->data[0], frame->nb_samples);
|
printf("frame->data = %p frame->nb_samples = %d\n", frame->data[0], frame->nb_samples);
|
||||||
@@ -462,6 +474,7 @@ JNIEXPORT jint JNICALL Java_android_media_MediaCodec_native_1dequeueOutputBuffer
|
|||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
return INFO_TRY_AGAIN_LATER;
|
return INFO_TRY_AGAIN_LATER;
|
||||||
}
|
}
|
||||||
|
_SET_INT_FIELD(buffer_info, "flags", 0);
|
||||||
_SET_LONG_FIELD(buffer_info, "presentationTimeUs", frame->pts);
|
_SET_LONG_FIELD(buffer_info, "presentationTimeUs", frame->pts);
|
||||||
|
|
||||||
if (codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
|
if (codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import android.view.Surface;
|
|||||||
|
|
||||||
public class MediaCodec {
|
public class MediaCodec {
|
||||||
|
|
||||||
|
public static final int BUFFER_FLAG_END_OF_STREAM = 0x4;
|
||||||
|
|
||||||
private String codecName;
|
private String codecName;
|
||||||
private ByteBuffer[] inputBuffers;
|
private ByteBuffer[] inputBuffers;
|
||||||
private ByteBuffer[] outputBuffers;
|
private ByteBuffer[] outputBuffers;
|
||||||
@@ -104,9 +106,15 @@ public class MediaCodec {
|
|||||||
private void tryProcessInputBuffer() {
|
private void tryProcessInputBuffer() {
|
||||||
Integer index = queuedInputBuffers.peek();
|
Integer index = queuedInputBuffers.peek();
|
||||||
if (index != null) {
|
if (index != null) {
|
||||||
int ret = native_queueInputBuffer(native_codec, inputBuffers[index], inputBufferTimestamps[index]);
|
int ret;
|
||||||
|
if (index == -1) { // end of stream
|
||||||
|
ret = native_queueInputBuffer(native_codec, null, 0);
|
||||||
|
} else {
|
||||||
|
ret = native_queueInputBuffer(native_codec, inputBuffers[index], inputBufferTimestamps[index]);
|
||||||
|
}
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
queuedInputBuffers.remove(index);
|
queuedInputBuffers.remove(index);
|
||||||
|
if (index != -1)
|
||||||
freeInputBuffers.add(index);
|
freeInputBuffers.add(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,6 +131,11 @@ public class MediaCodec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void queueInputBuffer(int index, int offset, int size, long presentationTimeUs, int flags) {
|
public void queueInputBuffer(int index, int offset, int size, long presentationTimeUs, int flags) {
|
||||||
|
if ((flags & BUFFER_FLAG_END_OF_STREAM) != 0) {
|
||||||
|
queuedInputBuffers.add(-1);
|
||||||
|
tryProcessInputBuffer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
inputBufferTimestamps[index] = presentationTimeUs;
|
inputBufferTimestamps[index] = presentationTimeUs;
|
||||||
queuedInputBuffers.add(index);
|
queuedInputBuffers.add(index);
|
||||||
tryProcessInputBuffer();
|
tryProcessInputBuffer();
|
||||||
|
|||||||
Reference in New Issue
Block a user