Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(987)

Unified Diff: media/base/android/media_decoder_job.h

Issue 254473010: Refactor MSE implementation on Android to simplify the logic and improve the performance (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/base/android/media_decoder_job.h
diff --git a/media/base/android/media_decoder_job.h b/media/base/android/media_decoder_job.h
index 9dbbd00fceaba8c1a222fabfd6e95c0fce8749b1..6542ba41f0b193fe1943ee09d68d34842aaaa19b 100644
--- a/media/base/android/media_decoder_job.h
+++ b/media/base/android/media_decoder_job.h
@@ -10,6 +10,7 @@
#include "base/time/time.h"
#include "media/base/android/demuxer_stream_player_params.h"
#include "media/base/android/media_codec_bridge.h"
+#include "ui/gl/android/scoped_java_surface.h"
namespace base {
class SingleThreadTaskRunner;
@@ -17,6 +18,8 @@ class SingleThreadTaskRunner;
namespace media {
+class MediaDrmBridge;
+
// Class for managing all the decoding tasks. Each decoding task will be posted
// onto the same thread. The thread will be stopped once Stop() is called.
// Data is stored in 2 chunks. When new data arrives, it is always stored in
@@ -56,8 +59,8 @@ class MediaDecoderJob {
//
// Returns true if the next decode was started and |callback| will be
// called when the decode operation is complete.
- // Returns false if a config change is needed. |callback| is ignored
- // and will not be called.
+ // Returns false if |media_codec_bridge_| cannot be created. |callback| is
+ // ignored and will not be called.
bool Decode(base::TimeTicks start_time_ticks,
base::TimeDelta start_presentation_timestamp,
const DecoderCallback& callback);
@@ -72,25 +75,42 @@ class MediaDecoderJob {
// reflects whether data was actually decoded or the decode terminated early.
void StopDecode();
- // Flush the decoder.
+ // Flushes the decoder and abandons all the data that is being decoded.
void Flush();
// Enter prerolling state. The job must not currently be decoding.
void BeginPrerolling(base::TimeDelta preroll_timestamp);
- bool prerolling() const { return prerolling_; }
+ // Releases all the decoder resources as the current tab is going background.
+ virtual void ReleaseDecoderResources();
+
+ // Sets the demuxer configs. Returns true if configs has changed, or false
+ // otherwise.
+ virtual bool SetDemuxerConfigs(const DemuxerConfigs& configs);
+
+ // Returns whether the decoder has finished decoding all the data.
+ bool OutputEOSReached() const;
+
+ // Returns true if the audio/video stream is available, implemented by child
+ // classes.
+ virtual bool HasStream() const = 0;
bool is_decoding() const { return !decode_cb_.is_null(); }
- bool is_requesting_demuxer_data() const {
- return is_requesting_demuxer_data_;
- }
+ void set_drm_bridge(MediaDrmBridge* drm_bridge) { drm_bridge_ = drm_bridge; }
+
+ bool is_content_encrypted() const { return is_content_encrypted_; }
protected:
+ // Creates a new MediaDecoderJob instance.
+ // |decoder_task_runner| - Thread on which the decoder task will run.
+ // |request_data_cb| - Callback to request more data for the decoder.
+ // |on_demuxer_config_changed_cb| - Callback to inform the caller that
+ // demuxer config has changed.
MediaDecoderJob(
const scoped_refptr<base::SingleThreadTaskRunner>& decoder_task_runner,
- MediaCodecBridge* media_codec_bridge,
- const base::Closure& request_data_cb);
+ const base::Closure& request_data_cb,
+ const base::Closure& on_demuxer_config_changed_cb);
// Release the output buffer at index |output_buffer_index| and render it if
// |render_output| is true. Upon completion, |callback| will be called.
@@ -105,13 +125,32 @@ class MediaDecoderJob {
// this decoder job.
virtual bool ComputeTimeToRender() const = 0;
+ // Gets MediaCrypto object from |drm_bridge_|.
+ base::android::ScopedJavaLocalRef<jobject> GetMediaCrypto();
+
+ // Releases the |media_codec_bridge_|.
+ void ReleaseMediaCodecBridge();
+
+ MediaDrmBridge* drm_bridge() { return drm_bridge_; }
+
+ void set_is_content_encrypted(bool is_content_encrypted) {
+ is_content_encrypted_ = is_content_encrypted;
+ }
+
+ bool need_to_reconfig_decoder_job_;
+
+ scoped_ptr<MediaCodecBridge> media_codec_bridge_;
+
private:
friend class MediaSourcePlayerTest;
// Causes this instance to be deleted on the thread it is bound to.
void Release();
- MediaCodecStatus QueueInputBuffer(const AccessUnit& unit);
+ // Queues an access unit into |media_codec_bridge_|'s input buffer. If
+ // |drain_decoder| is true, the access unit is replaced with an EOS unit so
+ // that we can drain the current buffer in |media_codec_bridge_|.
+ MediaCodecStatus QueueInputBuffer(const AccessUnit& unit, bool drain_decoder);
// Returns true if this object has data to decode.
bool HasData() const;
@@ -135,6 +174,7 @@ class MediaDecoderJob {
base::TimeTicks start_time_ticks,
base::TimeDelta start_presentation_timestamp,
bool needs_flush,
+ bool drain_decoder,
const DecoderCallback& callback);
// Called on the UI thread to indicate that one decode cycle has completed.
@@ -147,22 +187,43 @@ class MediaDecoderJob {
// Helper function to get the current access unit that is being decoded.
const AccessUnit& CurrentAccessUnit() const;
- // Check whether a chunk has no remaining access units to decode. If
+ // Checks whether a chunk has no remaining access units to decode. If
// |is_active_chunk| is true, this function returns whether decoder has
// consumed all data in |received_data_[current_demuxer_data_index_]|.
// Otherwise, it returns whether decoder has consumed all data in the inactive
// chunk.
bool NoAccessUnitsRemainingInChunk(bool is_active_chunk) const;
- // Clearn all the received data.
- void ClearData();
-
- // Request new data for the current chunk if it runs out of data.
+ // Requests new data for the current chunk if it runs out of data.
void RequestCurrentChunkIfEmpty();
- // Initialize |received_data_| and |access_unit_index_|.
+ // Initializes |received_data_| and |access_unit_index_|.
void InitializeReceivedData();
+ void OnDecoderDrained();
+
+ // Creates |media_codec_bridge_| for decoding purpose.
+ bool CreateMediaCodecBridge();
+
+ // Called when an access unit is consumed by the decoder. |is_config_change|
+ // indicates whether the current access unit is a config change. If it is
+ // true, the next access unit is guarateed to be an I-frame.
+ virtual void CurrentDataConsumed(bool is_config_change) {}
+
+ // Called when |media_codec_bridge_| is released
+ virtual void OnMediaCodecBridgeReleased() {}
+
+ // Implemented by the child class to create |media_codec_bridge_| for a
+ // particular stream.
+ virtual bool CreateMediaCodecBridgeInternal() = 0;
+
+ // Returns true if the |configs| doesn't match the current demuxer configs
+ // the decoder job has.
+ virtual bool IsDemuxerConfigChanged(const DemuxerConfigs& configs) const = 0;
+
+ // Update the demuxer configs.
+ virtual void UpdateDemuxerConfigs(const DemuxerConfigs& configs) = 0;
+
// Return the index to |received_data_| that is not currently being decoded.
size_t inactive_demuxer_data_index() const {
return 1 - current_demuxer_data_index_;
@@ -174,10 +235,6 @@ class MediaDecoderJob {
// The task runner that decoder job runs on.
scoped_refptr<base::SingleThreadTaskRunner> decoder_task_runner_;
- // The media codec bridge used for decoding. Owned by derived class.
- // NOTE: This MUST NOT be accessed in the destructor.
- MediaCodecBridge* media_codec_bridge_;
-
// Whether the decoder needs to be flushed.
bool needs_flush_;
@@ -210,6 +267,9 @@ class MediaDecoderJob {
// Callback used to request more data.
base::Closure request_data_cb_;
+ // Callback to notify the caller config has changed.
+ base::Closure on_demuxer_config_changed_cb_;
+
// Callback to run when new data has been received.
base::Closure on_data_received_cb_;
@@ -234,6 +294,11 @@ class MediaDecoderJob {
// If the index is uninitialized or invalid, it must be -1.
int input_buf_index_;
+ // Indicates whether content is encrypted.
+ bool is_content_encrypted_;
+
+ // Indicates the decoder job should stop after decoding the current access
+ // unit.
bool stop_decode_pending_;
// Indicates that this object should be destroyed once the current
@@ -247,10 +312,17 @@ class MediaDecoderJob {
// Indicates whether the incoming data should be ignored.
bool is_incoming_data_invalid_;
- // Weak pointer passed to media decoder jobs for callbacks. It is bounded to
- // the decoder thread.
- // NOTE: Weak pointers must be invalidated before all other member variables.
- base::WeakPtrFactory<MediaDecoderJob> weak_factory_;
+ // Indicates that |media_codec_bridge_| should be released once the current
+ // Decode() has completed. This gets set when ReleaseDecoderResources() gets
+ // called while there is a decode in progress.
+ bool release_resources_pending_;
+
+ // Pointer to a DRM object that will be used for encrypted streams.
+ MediaDrmBridge* drm_bridge_;
+
+ // Indicates whether |media_codec_bridge_| is in the middle of being drained
+ // due to a config change.
+ bool drain_decoder_;
DISALLOW_IMPLICIT_CONSTRUCTORS(MediaDecoderJob);
};

Powered by Google App Engine
This is Rietveld 408576698