NuPlayer2: fork the native code for MediaPlayer2
Forked from fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48
NuPlayer2Decoder uses NdkMediaCodec, NdkMediaCrypto.
NuPlayer2Drm uses NdkMediaDrm.
No more IMediaHTTPService and IMediaHTTPConnection in NuPlayer2.
Test: compiles
Bug: 69805888
Change-Id: Ica3c168d40dcf114fb44e8688a9ede671e8d77ef
diff --git a/media/libmedia/nuplayer2/NuPlayer2Renderer.h b/media/libmedia/nuplayer2/NuPlayer2Renderer.h
new file mode 100644
index 0000000..3007654
--- /dev/null
+++ b/media/libmedia/nuplayer2/NuPlayer2Renderer.h
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NUPLAYER2_RENDERER_H_
+
+#define NUPLAYER2_RENDERER_H_
+
+#include <media/AudioResamplerPublic.h>
+#include <media/AVSyncSettings.h>
+
+#include "NuPlayer2.h"
+
+namespace android {
+
+class JWakeLock;
+struct MediaClock;
+class MediaCodecBuffer;
+struct VideoFrameScheduler;
+
+struct NuPlayer2::Renderer : public AHandler {
+ enum Flags {
+ FLAG_REAL_TIME = 1,
+ FLAG_OFFLOAD_AUDIO = 2,
+ };
+ Renderer(const sp<MediaPlayer2Base::AudioSink> &sink,
+ const sp<MediaClock> &mediaClock,
+ const sp<AMessage> ¬ify,
+ uint32_t flags = 0);
+
+ static size_t AudioSinkCallback(
+ MediaPlayer2Base::AudioSink *audioSink,
+ void *data, size_t size, void *me,
+ MediaPlayer2Base::AudioSink::cb_event_t event);
+
+ void queueBuffer(
+ bool audio,
+ const sp<MediaCodecBuffer> &buffer,
+ const sp<AMessage> ¬ifyConsumed);
+
+ void queueEOS(bool audio, status_t finalResult);
+
+ status_t setPlaybackSettings(const AudioPlaybackRate &rate /* sanitized */);
+ status_t getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */);
+ status_t setSyncSettings(const AVSyncSettings &sync, float videoFpsHint);
+ status_t getSyncSettings(AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */);
+
+ void flush(bool audio, bool notifyComplete);
+
+ void signalTimeDiscontinuity();
+
+ void signalDisableOffloadAudio();
+ void signalEnableOffloadAudio();
+
+ void pause();
+ void resume();
+
+ void setVideoFrameRate(float fps);
+
+ status_t getCurrentPosition(int64_t *mediaUs);
+ int64_t getVideoLateByUs();
+
+ status_t openAudioSink(
+ const sp<AMessage> &format,
+ bool offloadOnly,
+ bool hasVideo,
+ uint32_t flags,
+ bool *isOffloaded,
+ bool isStreaming);
+ void closeAudioSink();
+
+ // re-open audio sink after all pending audio buffers played.
+ void changeAudioFormat(
+ const sp<AMessage> &format,
+ bool offloadOnly,
+ bool hasVideo,
+ uint32_t flags,
+ bool isStreaming,
+ const sp<AMessage> ¬ify);
+
+ enum {
+ kWhatEOS = 'eos ',
+ kWhatFlushComplete = 'fluC',
+ kWhatPosition = 'posi',
+ kWhatVideoRenderingStart = 'vdrd',
+ kWhatMediaRenderingStart = 'mdrd',
+ kWhatAudioTearDown = 'adTD',
+ kWhatAudioOffloadPauseTimeout = 'aOPT',
+ };
+
+ enum AudioTearDownReason {
+ kDueToError = 0, // Could restart with either offload or non-offload.
+ kDueToTimeout,
+ kForceNonOffload, // Restart only with non-offload.
+ };
+
+protected:
+ virtual ~Renderer();
+
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+private:
+ enum {
+ kWhatDrainAudioQueue = 'draA',
+ kWhatDrainVideoQueue = 'draV',
+ kWhatPostDrainVideoQueue = 'pDVQ',
+ kWhatQueueBuffer = 'queB',
+ kWhatQueueEOS = 'qEOS',
+ kWhatConfigPlayback = 'cfPB',
+ kWhatConfigSync = 'cfSy',
+ kWhatGetPlaybackSettings = 'gPbS',
+ kWhatGetSyncSettings = 'gSyS',
+ kWhatFlush = 'flus',
+ kWhatPause = 'paus',
+ kWhatResume = 'resm',
+ kWhatOpenAudioSink = 'opnA',
+ kWhatCloseAudioSink = 'clsA',
+ kWhatChangeAudioFormat = 'chgA',
+ kWhatStopAudioSink = 'stpA',
+ kWhatDisableOffloadAudio = 'noOA',
+ kWhatEnableOffloadAudio = 'enOA',
+ kWhatSetVideoFrameRate = 'sVFR',
+ };
+
+ // if mBuffer != nullptr, it's a buffer containing real data.
+ // else if mNotifyConsumed == nullptr, it's EOS.
+ // else it's a tag for re-opening audio sink in different format.
+ struct QueueEntry {
+ sp<MediaCodecBuffer> mBuffer;
+ sp<AMessage> mMeta;
+ sp<AMessage> mNotifyConsumed;
+ size_t mOffset;
+ status_t mFinalResult;
+ int32_t mBufferOrdinal;
+ };
+
+ static const int64_t kMinPositionUpdateDelayUs;
+
+ sp<MediaPlayer2Base::AudioSink> mAudioSink;
+ bool mUseVirtualAudioSink;
+ sp<AMessage> mNotify;
+ Mutex mLock;
+ uint32_t mFlags;
+ List<QueueEntry> mAudioQueue;
+ List<QueueEntry> mVideoQueue;
+ uint32_t mNumFramesWritten;
+ sp<VideoFrameScheduler> mVideoScheduler;
+
+ bool mDrainAudioQueuePending;
+ bool mDrainVideoQueuePending;
+ int32_t mAudioQueueGeneration;
+ int32_t mVideoQueueGeneration;
+ int32_t mAudioDrainGeneration;
+ int32_t mVideoDrainGeneration;
+ int32_t mAudioEOSGeneration;
+
+ const sp<MediaClock> mMediaClock;
+ float mPlaybackRate; // audio track rate
+
+ AudioPlaybackRate mPlaybackSettings;
+ AVSyncSettings mSyncSettings;
+ float mVideoFpsHint;
+
+ int64_t mAudioFirstAnchorTimeMediaUs;
+ int64_t mAnchorTimeMediaUs;
+ int64_t mAnchorNumFramesWritten;
+ int64_t mVideoLateByUs;
+ int64_t mNextVideoTimeMediaUs;
+ bool mHasAudio;
+ bool mHasVideo;
+
+ bool mNotifyCompleteAudio;
+ bool mNotifyCompleteVideo;
+
+ bool mSyncQueues;
+
+ // modified on only renderer's thread.
+ bool mPaused;
+ int64_t mPauseDrainAudioAllowedUs; // time when we can drain/deliver audio in pause mode.
+
+ bool mVideoSampleReceived;
+ bool mVideoRenderingStarted;
+ int32_t mVideoRenderingStartGeneration;
+ int32_t mAudioRenderingStartGeneration;
+ bool mRenderingDataDelivered;
+
+ int64_t mNextAudioClockUpdateTimeUs;
+ // the media timestamp of last audio sample right before EOS.
+ int64_t mLastAudioMediaTimeUs;
+
+ int32_t mAudioOffloadPauseTimeoutGeneration;
+ bool mAudioTornDown;
+ audio_offload_info_t mCurrentOffloadInfo;
+
+ struct PcmInfo {
+ audio_channel_mask_t mChannelMask;
+ audio_output_flags_t mFlags;
+ audio_format_t mFormat;
+ int32_t mNumChannels;
+ int32_t mSampleRate;
+ };
+ PcmInfo mCurrentPcmInfo;
+ static const PcmInfo AUDIO_PCMINFO_INITIALIZER;
+
+ int32_t mTotalBuffersQueued;
+ int32_t mLastAudioBufferDrained;
+ bool mUseAudioCallback;
+
+ sp<JWakeLock> mWakeLock;
+
+ status_t getCurrentPositionOnLooper(int64_t *mediaUs);
+ status_t getCurrentPositionOnLooper(
+ int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
+ bool getCurrentPositionIfPaused_l(int64_t *mediaUs);
+ status_t getCurrentPositionFromAnchor(
+ int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
+
+ void notifyEOSCallback();
+ size_t fillAudioBuffer(void *buffer, size_t size);
+
+ bool onDrainAudioQueue();
+ void drainAudioQueueUntilLastEOS();
+ int64_t getPendingAudioPlayoutDurationUs(int64_t nowUs);
+ void postDrainAudioQueue_l(int64_t delayUs = 0);
+
+ void clearAnchorTime();
+ void clearAudioFirstAnchorTime_l();
+ void setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs);
+ void setVideoLateByUs(int64_t lateUs);
+
+ void onNewAudioMediaTime(int64_t mediaTimeUs);
+ int64_t getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs);
+
+ void onDrainVideoQueue();
+ void postDrainVideoQueue();
+
+ void prepareForMediaRenderingStart_l();
+ void notifyIfMediaRenderingStarted_l();
+
+ void onQueueBuffer(const sp<AMessage> &msg);
+ void onQueueEOS(const sp<AMessage> &msg);
+ void onFlush(const sp<AMessage> &msg);
+ void onAudioSinkChanged();
+ void onDisableOffloadAudio();
+ void onEnableOffloadAudio();
+ status_t onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */);
+ status_t onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */);
+ status_t onConfigSync(const AVSyncSettings &sync, float videoFpsHint);
+ status_t onGetSyncSettings(AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */);
+
+ void onPause();
+ void onResume();
+ void onSetVideoFrameRate(float fps);
+ int32_t getQueueGeneration(bool audio);
+ int32_t getDrainGeneration(bool audio);
+ bool getSyncQueues();
+ void onAudioTearDown(AudioTearDownReason reason);
+ status_t onOpenAudioSink(
+ const sp<AMessage> &format,
+ bool offloadOnly,
+ bool hasVideo,
+ uint32_t flags,
+ bool isStreaming);
+ void onCloseAudioSink();
+ void onChangeAudioFormat(const sp<AMessage> &meta, const sp<AMessage> ¬ify);
+
+ void notifyEOS(bool audio, status_t finalResult, int64_t delayUs = 0);
+ void notifyEOS_l(bool audio, status_t finalResult, int64_t delayUs = 0);
+ void notifyFlushComplete(bool audio);
+ void notifyPosition();
+ void notifyVideoLateBy(int64_t lateByUs);
+ void notifyVideoRenderingStart();
+ void notifyAudioTearDown(AudioTearDownReason reason);
+
+ void flushQueue(List<QueueEntry> *queue);
+ bool dropBufferIfStale(bool audio, const sp<AMessage> &msg);
+ void syncQueuesDone_l();
+
+ bool offloadingAudio() const { return (mFlags & FLAG_OFFLOAD_AUDIO) != 0; }
+
+ void startAudioOffloadPauseTimeout();
+ void cancelAudioOffloadPauseTimeout();
+
+ int64_t getDurationUsIfPlayedAtSampleRate(uint32_t numFrames);
+
+ DISALLOW_EVIL_CONSTRUCTORS(Renderer);
+};
+
+} // namespace android
+
+#endif // NUPLAYER2_RENDERER_H_