summaryrefslogtreecommitdiffstats
path: root/media/base/android/media_source_player.h
diff options
context:
space:
mode:
Diffstat (limited to 'media/base/android/media_source_player.h')
-rw-r--r--media/base/android/media_source_player.h222
1 files changed, 222 insertions, 0 deletions
diff --git a/media/base/android/media_source_player.h b/media/base/android/media_source_player.h
new file mode 100644
index 0000000..c671950
--- /dev/null
+++ b/media/base/android/media_source_player.h
@@ -0,0 +1,222 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_ANDROID_MEDIA_SOURCE_PLAYER_H_
+#define MEDIA_BASE_ANDROID_MEDIA_SOURCE_PLAYER_H_
+
+#include <jni.h>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/android/scoped_java_ref.h"
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread.h"
+#include "base/time.h"
+#include "media/base/android/demuxer_stream_player_params.h"
+#include "media/base/android/media_codec_bridge.h"
+#include "media/base/android/media_player_android.h"
+#include "media/base/media_export.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace media {
+
+class VideoDecoderJob;
+class AudioDecoderJob;
+
+// 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.
+class MediaDecoderJob {
+ public:
+ virtual ~MediaDecoderJob();
+
+ // Callback when a decoder job finishes its work. Args: presentation time,
+ // timestamp when the data is rendered, whether decoder is reaching EOS.
+ typedef base::Callback<void(const base::TimeDelta&, const base::Time&, bool)>
+ DecoderCallback;
+
+ // Called by MediaSourcePlayer to decode some data.
+ void Decode(
+ const MediaPlayerHostMsg_ReadFromDemuxerAck_Params::AccessUnit& unit,
+ const base::Time& start_wallclock_time,
+ const base::TimeDelta& start_presentation_timestamp,
+ const MediaDecoderJob::DecoderCallback& callback);
+
+ // Flush the decoder.
+ void Flush();
+
+ struct Deleter {
+ inline void operator()(MediaDecoderJob* ptr) const { ptr->Release(); }
+ };
+
+ // Causes this instance to be deleted on the thread it is bound to.
+ void Release();
+
+ protected:
+ MediaDecoderJob(
+ bool is_audio, const scoped_refptr<base::MessageLoopProxy>& message_loop);
+
+ // Release the output buffer and render it.
+ void ReleaseOutputBuffer(
+ int outputBufferIndex, size_t size,
+ const base::TimeDelta& presentation_timestamp,
+ bool end_of_stream, const MediaDecoderJob::DecoderCallback& callback);
+
+ // Helper function to decoder data on |thread_|. |unit| contains all the data
+ // to be decoded. |start_wallclock_time| and |start_presentation_timestamp|
+ // represent the system time and the presentation timestamp when the first
+ // frame is rendered. We use these information to estimate when the current
+ // frame should be rendered. If |needs_flush| is true, codec needs to be
+ // flushed at the beginning of this call.
+ void DecodeInternal(
+ const MediaPlayerHostMsg_ReadFromDemuxerAck_Params::AccessUnit& unit,
+ const base::Time& start_wallclock_time,
+ const base::TimeDelta& start_presentation_timestamp,
+ bool needs_flush,
+ const MediaDecoderJob::DecoderCallback& callback);
+
+ // The media codec bridge used for decoding.
+ scoped_ptr<MediaCodecBridge> media_codec_bridge_;
+
+ // The message loop where callbacks should be dispatched.
+ scoped_refptr<base::MessageLoopProxy> message_loop_;
+
+ // Thread the decode task runs on.
+ scoped_ptr<base::Thread> thread_;
+
+ // Whether the decoder needs to be flushed.
+ bool needs_flush_;
+
+ // Whether this is an audio decoder.
+ bool is_audio_;
+
+ // Weak pointer passed to media decoder jobs for callbacks.
+ base::WeakPtrFactory<MediaDecoderJob> weak_this_;
+};
+
+typedef scoped_ptr<MediaDecoderJob, MediaDecoderJob::Deleter>
+ ScopedMediaDecoderJob;
+
+// This class handles media source extensions on Android. It uses Android
+// MediaCodec to decode audio and video streams in two separate threads.
+// IPC is being used to send data from the render process to this object.
+// TODO(qinmin): use shared memory to send data between processes.
+class MEDIA_EXPORT MediaSourcePlayer : public MediaPlayerAndroid {
+ public:
+ // Construct a MediaSourcePlayer object with all the needed media player
+ // callbacks.
+ MediaSourcePlayer(int player_id,
+ MediaPlayerManager* manager);
+ virtual ~MediaSourcePlayer();
+
+ // MediaPlayerAndroid implementation.
+ virtual void SetVideoSurface(jobject surface) OVERRIDE;
+ virtual void Start() OVERRIDE;
+ virtual void Pause() OVERRIDE;
+ virtual void SeekTo(base::TimeDelta timestamp) OVERRIDE;
+ virtual void Release() OVERRIDE;
+ virtual void SetVolume(float leftVolume, float rightVolume) OVERRIDE;
+ virtual int GetVideoWidth() OVERRIDE;
+ virtual int GetVideoHeight() OVERRIDE;
+ virtual base::TimeDelta GetCurrentTime() OVERRIDE;
+ virtual base::TimeDelta GetDuration() OVERRIDE;
+ virtual bool IsPlaying() OVERRIDE;
+ virtual bool CanPause() OVERRIDE;
+ virtual bool CanSeekForward() OVERRIDE;
+ virtual bool CanSeekBackward() OVERRIDE;
+ virtual bool IsPlayerReady() OVERRIDE;
+
+ // Called when the demuxer is ready.
+ virtual void DemuxerReady(
+ const MediaPlayerHostMsg_DemuxerReady_Params& params) OVERRIDE;
+
+ // Called when the requested data is received from the demuxer.
+ virtual void ReadFromDemuxerAck(
+ const MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) OVERRIDE;
+
+ private:
+ // Update the timestamps for A/V sync scheduling. |kickoff_time| keeps
+ // track of when the job is started. We need this to check if a seek is
+ // performed during decoding.
+ void UpdateTimestamps(
+ const base::Time& kickoff_time,
+ const base::TimeDelta& presentation_timestamp,
+ const base::Time& wallclock_time);
+
+ // Helper function for starting media playback.
+ void StartInternal();
+
+ // Playback is completed for one channel.
+ void PlaybackCompleted(bool is_audio);
+
+ // Called when the decoder finishes its task.
+ void MediaDecoderCallback(
+ bool is_audio, const base::Time& kickoff_time,
+ const base::TimeDelta& presentation_timestamp,
+ const base::Time& wallclock_time, bool end_of_stream);
+
+ // Called to decoder more data.
+ void DecodeMoreAudio();
+ void DecodeMoreVideo();
+
+ // Functions check whether audio/video is present.
+ bool HasVideo();
+ bool HasAudio();
+
+ // Pending play event while player is preparing.
+ bool pending_play_;
+
+ // Stats about the media.
+ base::TimeDelta duration_;
+ int width_;
+ int height_;
+ AudioCodec audio_codec_;
+ VideoCodec video_codec_;
+ int num_channels_;
+ int sampling_rate_;
+ bool seekable_;
+ base::TimeDelta last_presentation_timestamp_;
+ std::vector<uint8> audio_extra_data_;
+ bool audio_finished_;
+ bool video_finished_;
+ bool playing_;
+
+ // Timestamps for providing simple A/V sync. When start decoding an audio
+ // chunk, we record its presentation timestamp and the current system time.
+ // Then we use this information to estimate when the next audio/video frame
+ // should be rendered.
+ // TODO(qinmin): Need to fix the problem if audio/video lagged too far behind
+ // due to network or decoding problem.
+ base::Time start_wallclock_time_;
+ base::TimeDelta start_presentation_timestamp_;
+ base::Time last_seek_time_;
+
+ // Decoder jobs
+ ScopedMediaDecoderJob audio_decoder_job_;
+ ScopedMediaDecoderJob video_decoder_job_;
+
+ // These variables keep track of the current decoding data.
+ // TODO(qinmin): remove these variables when we no longer relies on IPC for
+ // data passing.
+ size_t audio_access_unit_index_;
+ size_t video_access_unit_index_;
+ bool waiting_for_audio_data_;
+ bool waiting_for_video_data_;
+ MediaPlayerHostMsg_ReadFromDemuxerAck_Params received_audio_;
+ MediaPlayerHostMsg_ReadFromDemuxerAck_Params received_video_;
+
+ // Weak pointer passed to media decoder jobs for callbacks.
+ base::WeakPtrFactory<MediaSourcePlayer> weak_this_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaSourcePlayer);
+};
+
+} // namespace media
+
+#endif // MEDIA_BASE_ANDROID_MEDIA_SOURCE_PLAYER_H_