Skip to content

Commit 9c4102d

Browse files
authored
[android] Support BUFFER_FLAG_DECODE_ONLY (#6813)
Set flag MediaCodec.BUFFER_FLAG_DECODE_ONLY for decoding only video buffers when tunneling playback is enabled. The change is part of the [PR/5642](#5642) from MTK. Bug: 417273879 Bug: 306236129
1 parent c949c7d commit 9c4102d

File tree

8 files changed

+71
-25
lines changed

8 files changed

+71
-25
lines changed

cobalt/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,10 @@ class MediaCodecBridge {
6262
private static final String KEY_CROP_TOP = "crop-top";
6363

6464
private final Object mNativeBridgeLock = new Object();
65+
6566
@GuardedBy("mNativeBridgeLock")
6667
private long mNativeMediaCodecBridge;
68+
6769
private final SynchronizedHolder<MediaCodec, IllegalStateException> mMediaCodec =
6870
new SynchronizedHolder<>(() -> new IllegalStateException("MediaCodec was destroyed"));
6971

@@ -290,9 +292,7 @@ private String errorMessage() {
290292
}
291293

292294
public MediaCodecBridge(
293-
long nativeMediaCodecBridge,
294-
MediaCodec mediaCodec,
295-
int tunnelModeAudioSessionId) {
295+
long nativeMediaCodecBridge, MediaCodec mediaCodec, int tunnelModeAudioSessionId) {
296296
if (mediaCodec == null) {
297297
throw new IllegalArgumentException();
298298
}
@@ -400,6 +400,15 @@ public static boolean isFrameRenderedCallbackEnabled() {
400400
return Build.VERSION.SDK_INT >= 34;
401401
}
402402

403+
private boolean isDecodeOnlyFlagEnabled() {
404+
// Right now, we only enable BUFFER_FLAG_DECODE_ONLY for tunneling playback.
405+
if (!mIsTunnelingPlayback) {
406+
return false;
407+
}
408+
// BUFFER_FLAG_DECODE_ONLY is added in Android 14.
409+
return Build.VERSION.SDK_INT >= 34;
410+
}
411+
403412
@CalledByNative
404413
public static void createVideoMediaCodecBridge(
405414
long nativeMediaCodecBridge,
@@ -466,10 +475,7 @@ public static void createVideoMediaCodecBridge(
466475
}
467476

468477
MediaCodecBridge bridge =
469-
new MediaCodecBridge(
470-
nativeMediaCodecBridge,
471-
mediaCodec,
472-
tunnelModeAudioSessionId);
478+
new MediaCodecBridge(nativeMediaCodecBridge, mediaCodec, tunnelModeAudioSessionId);
473479
MediaFormat mediaFormat =
474480
createVideoDecoderFormat(mime, widthHint, heightHint, videoCapabilities);
475481

@@ -739,9 +745,14 @@ private ByteBuffer getOutputBuffer(int index) {
739745

740746
@CalledByNative
741747
private int queueInputBuffer(
742-
int index, int offset, int size, long presentationTimeUs, int flags) {
748+
int index, int offset, int size, long presentationTimeUs, int flags, boolean is_decode_only) {
743749
resetLastPresentationTimeIfNeeded(presentationTimeUs);
744750
try {
751+
if (isDecodeOnlyFlagEnabled()
752+
&& is_decode_only
753+
&& (flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) == 0) {
754+
flags |= MediaCodec.BUFFER_FLAG_DECODE_ONLY;
755+
}
745756
mMediaCodec.get().queueInputBuffer(index, offset, size, presentationTimeUs, flags);
746757
} catch (Exception e) {
747758
Log.e(TAG, "Failed to queue input buffer", e);
@@ -762,7 +773,8 @@ private int queueSecureInputBuffer(
762773
int cipherMode,
763774
int blocksToEncrypt,
764775
int blocksToSkip,
765-
long presentationTimeUs) {
776+
long presentationTimeUs,
777+
boolean is_decode_only) {
766778
resetLastPresentationTimeIfNeeded(presentationTimeUs);
767779
try {
768780
CryptoInfo cryptoInfo = new CryptoInfo();
@@ -776,7 +788,14 @@ private int queueSecureInputBuffer(
776788
return MediaCodecStatus.ERROR;
777789
}
778790

779-
mMediaCodec.get().queueSecureInputBuffer(index, offset, cryptoInfo, presentationTimeUs, 0);
791+
int flags = 0;
792+
if (isDecodeOnlyFlagEnabled() && is_decode_only) {
793+
flags |= MediaCodec.BUFFER_FLAG_DECODE_ONLY;
794+
}
795+
796+
mMediaCodec
797+
.get()
798+
.queueSecureInputBuffer(index, offset, cryptoInfo, presentationTimeUs, flags);
780799
} catch (MediaCodec.CryptoException e) {
781800
int errorCode = e.getErrorCode();
782801
if (errorCode == MediaCodec.CryptoException.ERROR_NO_KEY) {
@@ -1043,7 +1062,10 @@ private int getAudioFormat(int channelCount) {
10431062
@NativeMethods
10441063
interface Natives {
10451064
void onMediaCodecError(
1046-
long nativeMediaCodecBridge, boolean isRecoverable, boolean isTransient, String diagnosticInfo);
1065+
long nativeMediaCodecBridge,
1066+
boolean isRecoverable,
1067+
boolean isTransient,
1068+
String diagnosticInfo);
10471069

10481070
void onMediaCodecInputBufferAvailable(long nativeMediaCodecBridge, int bufferIndex);
10491071

starboard/android/shared/audio_decoder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ class AudioDecoder
7373
void RefreshOutputFormat(MediaCodecBridge* media_codec_bridge) override;
7474
bool Tick(MediaCodecBridge* media_codec_bridge) override { return false; }
7575
void OnFlushing() override {}
76+
bool IsBufferDecodeOnly(
77+
const scoped_refptr<InputBuffer>& input_buffer) override {
78+
return false;
79+
}
7680

7781
void ReportError(SbPlayerError error, const std::string& error_message);
7882

starboard/android/shared/media_codec_bridge.cc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -324,18 +324,20 @@ jint MediaCodecBridge::QueueInputBuffer(jint index,
324324
jint offset,
325325
jint size,
326326
jlong presentation_time_microseconds,
327-
jint flags) {
327+
jint flags,
328+
jboolean is_decode_only) {
328329
JNIEnv* env = AttachCurrentThread();
329330
return Java_MediaCodecBridge_queueInputBuffer(
330331
env, j_media_codec_bridge_, index, offset, size,
331-
presentation_time_microseconds, flags);
332+
presentation_time_microseconds, flags, is_decode_only);
332333
}
333334

334335
jint MediaCodecBridge::QueueSecureInputBuffer(
335336
jint index,
336337
jint offset,
337338
const SbDrmSampleInfo& drm_sample_info,
338-
jlong presentation_time_microseconds) {
339+
jlong presentation_time_microseconds,
340+
jboolean is_decode_only) {
339341
JNIEnv* env = AttachCurrentThread();
340342

341343
ScopedJavaLocalRef<jbyteArray> j_iv =
@@ -371,7 +373,7 @@ jint MediaCodecBridge::QueueSecureInputBuffer(
371373
return Java_MediaCodecBridge_queueSecureInputBuffer(
372374
env, j_media_codec_bridge_, index, offset, j_iv, j_key_id, j_clear_bytes,
373375
j_encrypted_bytes, subsample_count, cipher_mode, blocks_to_encrypt,
374-
blocks_to_skip, presentation_time_microseconds);
376+
blocks_to_skip, presentation_time_microseconds, is_decode_only);
375377
}
376378

377379
ScopedJavaLocalRef<jobject> MediaCodecBridge::GetOutputBuffer(jint index) {

starboard/android/shared/media_codec_bridge.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,11 +185,13 @@ class MediaCodecBridge {
185185
jint offset,
186186
jint size,
187187
jlong presentation_time_microseconds,
188-
jint flags);
188+
jint flags,
189+
jboolean is_decode_only);
189190
jint QueueSecureInputBuffer(jint index,
190191
jint offset,
191192
const SbDrmSampleInfo& drm_sample_info,
192-
jlong presentation_time_microseconds);
193+
jlong presentation_time_microseconds,
194+
jboolean is_decode_only);
193195

194196
// It is the responsibility of the client to manage the lifetime of the
195197
// jobject that |GetOutputBuffer| returns.

starboard/android/shared/media_decoder.cc

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -517,23 +517,24 @@ bool MediaDecoder::ProcessOneInputBuffer(
517517
// should wait until it's initialized to avoid errors.
518518
status = MEDIA_CODEC_NO_KEY;
519519
} else if (pending_input.type == PendingInput::kWriteCodecConfig) {
520-
status = media_codec_bridge_->QueueInputBuffer(dequeue_input_result.index,
521-
kNoOffset, size, kNoPts,
522-
BUFFER_FLAG_CODEC_CONFIG);
520+
status = media_codec_bridge_->QueueInputBuffer(
521+
dequeue_input_result.index, kNoOffset, size, kNoPts,
522+
BUFFER_FLAG_CODEC_CONFIG, false);
523523
} else if (pending_input.type == PendingInput::kWriteInputBuffer) {
524524
jlong pts_us = input_buffer->timestamp();
525525
if (drm_system_ && input_buffer->drm_info()) {
526526
status = media_codec_bridge_->QueueSecureInputBuffer(
527527
dequeue_input_result.index, kNoOffset, *input_buffer->drm_info(),
528-
pts_us);
528+
pts_us, host_->IsBufferDecodeOnly(input_buffer));
529529
} else {
530530
status = media_codec_bridge_->QueueInputBuffer(
531-
dequeue_input_result.index, kNoOffset, size, pts_us, kNoBufferFlags);
531+
dequeue_input_result.index, kNoOffset, size, pts_us, kNoBufferFlags,
532+
host_->IsBufferDecodeOnly(input_buffer));
532533
}
533534
} else {
534-
status = media_codec_bridge_->QueueInputBuffer(dequeue_input_result.index,
535-
kNoOffset, size, kNoPts,
536-
BUFFER_FLAG_END_OF_STREAM);
535+
status = media_codec_bridge_->QueueInputBuffer(
536+
dequeue_input_result.index, kNoOffset, size, kNoPts,
537+
BUFFER_FLAG_END_OF_STREAM, false);
537538
host_->OnEndOfStreamWritten(media_codec_bridge_.get());
538539
}
539540

starboard/android/shared/media_decoder.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ class MediaDecoder final
7171
// before the MediaCodecBridge is flushed.
7272
virtual void OnFlushing() = 0;
7373

74+
virtual bool IsBufferDecodeOnly(
75+
const scoped_refptr<InputBuffer>& input_buffer) = 0;
76+
7477
protected:
7578
~Host() {}
7679
};

starboard/android/shared/video_decoder.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,16 @@ void VideoDecoder::OnFlushing() {
973973
decoder_status_cb_(kReleaseAllFrames, NULL);
974974
}
975975

976+
bool VideoDecoder::IsBufferDecodeOnly(
977+
const scoped_refptr<InputBuffer>& input_buffer) {
978+
if (!is_video_frame_tracker_enabled_) {
979+
return false;
980+
}
981+
982+
SB_CHECK(video_frame_tracker_);
983+
return input_buffer->timestamp() < video_frame_tracker_->seek_to_time();
984+
}
985+
976986
namespace {
977987

978988
void updateTexImage(jobject surface_texture) {

starboard/android/shared/video_decoder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ class VideoDecoder
117117
void RefreshOutputFormat(MediaCodecBridge* media_codec_bridge) override;
118118
bool Tick(MediaCodecBridge* media_codec_bridge) override;
119119
void OnFlushing() override;
120+
bool IsBufferDecodeOnly(
121+
const scoped_refptr<InputBuffer>& input_buffer) override;
120122

121123
void TryToSignalPrerollForTunnelMode();
122124
bool IsFrameRenderedCallbackEnabled();

0 commit comments

Comments
 (0)