1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef MEDIA_BASE_ANDROID_MEDIA_DECODER_JOB_H_
6#define MEDIA_BASE_ANDROID_MEDIA_DECODER_JOB_H_
7
8#include "base/callback.h"
9#include "base/memory/weak_ptr.h"
10#include "base/time/time.h"
11#include "media/base/android/demuxer_stream_player_params.h"
12#include "media/base/android/media_codec_bridge.h"
13
14namespace base {
15class MessageLoopProxy;
16}
17
18namespace media {
19
20// Class for managing all the decoding tasks. Each decoding task will be posted
21// onto the same thread. The thread will be stopped once Stop() is called.
22class MediaDecoderJob {
23 public:
24  struct Deleter {
25    inline void operator()(MediaDecoderJob* ptr) const { ptr->Release(); }
26  };
27
28  // Callback when a decoder job finishes its work. Args: whether decode
29  // finished successfully, presentation time, audio output bytes.
30  // If the presentation time is equal to kNoTimestamp(), the decoder job
31  // skipped rendering of the decoded output and the callback target should
32  // update its clock to avoid introducing extra delays to the next frame.
33  typedef base::Callback<void(MediaCodecStatus, const base::TimeDelta&,
34                              size_t)> DecoderCallback;
35  // Callback when a decoder job finishes releasing the output buffer.
36  // Args: audio output bytes, must be 0 for video.
37  typedef base::Callback<void(size_t)> ReleaseOutputCompletionCallback;
38
39  virtual ~MediaDecoderJob();
40
41  // Called by MediaSourcePlayer when more data for this object has arrived.
42  void OnDataReceived(const DemuxerData& data);
43
44  // Prefetch so we know the decoder job has data when we call Decode().
45  // |prefetch_cb| - Run when prefetching has completed.
46  void Prefetch(const base::Closure& prefetch_cb);
47
48  // Called by MediaSourcePlayer to decode some data.
49  // |callback| - Run when decode operation has completed.
50  //
51  // Returns true if the next decode was started and |callback| will be
52  // called when the decode operation is complete.
53  // Returns false if a config change is needed. |callback| is ignored
54  // and will not be called.
55  bool Decode(const base::TimeTicks& start_time_ticks,
56              const base::TimeDelta& start_presentation_timestamp,
57              const DecoderCallback& callback);
58
59  // Called to stop the last Decode() early.
60  // If the decoder is in the process of decoding the next frame, then
61  // this method will just allow the decode to complete as normal. If
62  // this object is waiting for a data request to complete, then this method
63  // will wait for the data to arrive and then call the |callback|
64  // passed to Decode() with a status of MEDIA_CODEC_STOPPED. This ensures that
65  // the |callback| passed to Decode() is always called and the status
66  // reflects whether data was actually decoded or the decode terminated early.
67  void StopDecode();
68
69  // Flush the decoder.
70  void Flush();
71
72  // Enter prerolling state. The job must not currently be decoding.
73  void BeginPrerolling(const base::TimeDelta& preroll_timestamp);
74
75  bool prerolling() const { return prerolling_; }
76
77  bool is_decoding() const { return !decode_cb_.is_null(); }
78
79 protected:
80  MediaDecoderJob(const scoped_refptr<base::MessageLoopProxy>& decoder_loop,
81                  MediaCodecBridge* media_codec_bridge,
82                  const base::Closure& request_data_cb);
83
84  // Release the output buffer at index |output_buffer_index| and render it if
85  // |render_output| is true. Upon completion, |callback| will be called.
86  virtual void ReleaseOutputBuffer(
87      int output_buffer_index,
88      size_t size,
89      bool render_output,
90      const ReleaseOutputCompletionCallback& callback) = 0;
91
92  // Returns true if the "time to render" needs to be computed for frames in
93  // this decoder job.
94  virtual bool ComputeTimeToRender() const = 0;
95
96 private:
97  // Causes this instance to be deleted on the thread it is bound to.
98  void Release();
99
100  MediaCodecStatus QueueInputBuffer(const AccessUnit& unit);
101
102  // Returns true if this object has data to decode.
103  bool HasData() const;
104
105  // Initiates a request for more data.
106  // |done_cb| is called when more data is available in |received_data_|.
107  void RequestData(const base::Closure& done_cb);
108
109  // Posts a task to start decoding the next access unit in |received_data_|.
110  void DecodeNextAccessUnit(
111      const base::TimeTicks& start_time_ticks,
112      const base::TimeDelta& start_presentation_timestamp);
113
114  // Helper function to decoder data on |thread_|. |unit| contains all the data
115  // to be decoded. |start_time_ticks| and |start_presentation_timestamp|
116  // represent the system time and the presentation timestamp when the first
117  // frame is rendered. We use these information to estimate when the current
118  // frame should be rendered. If |needs_flush| is true, codec needs to be
119  // flushed at the beginning of this call.
120  void DecodeInternal(const AccessUnit& unit,
121                      const base::TimeTicks& start_time_ticks,
122                      const base::TimeDelta& start_presentation_timestamp,
123                      bool needs_flush,
124                      const DecoderCallback& callback);
125
126  // Called on the UI thread to indicate that one decode cycle has completed.
127  // Completes any pending job destruction or any pending decode stop. If
128  // destruction was not pending, passes its arguments to |decode_cb_|.
129  void OnDecodeCompleted(MediaCodecStatus status,
130                         const base::TimeDelta& presentation_timestamp,
131                         size_t audio_output_bytes);
132
133  // The UI message loop where callbacks should be dispatched.
134  scoped_refptr<base::MessageLoopProxy> ui_loop_;
135
136  // The message loop that decoder job runs on.
137  scoped_refptr<base::MessageLoopProxy> decoder_loop_;
138
139  // The media codec bridge used for decoding. Owned by derived class.
140  // NOTE: This MUST NOT be accessed in the destructor.
141  MediaCodecBridge* media_codec_bridge_;
142
143  // Whether the decoder needs to be flushed.
144  bool needs_flush_;
145
146  // Whether input EOS is encountered.
147  // TODO(wolenetz/qinmin): Protect with a lock. See http://crbug.com/320043.
148  bool input_eos_encountered_;
149
150  // Whether output EOS is encountered.
151  bool output_eos_encountered_;
152
153  // Tracks whether DecodeInternal() should skip decoding if the first access
154  // unit is EOS or empty, and report |MEDIA_CODEC_OUTPUT_END_OF_STREAM|. This
155  // is to work around some decoders that could crash otherwise. See
156  // http://b/11696552.
157  bool skip_eos_enqueue_;
158
159  // The timestamp the decoder needs to preroll to. If an access unit's
160  // timestamp is smaller than |preroll_timestamp_|, don't render it.
161  // TODO(qinmin): Comparing access unit's timestamp with |preroll_timestamp_|
162  // is not very accurate.
163  base::TimeDelta preroll_timestamp_;
164
165  // Indicates prerolling state. If true, this job has not yet decoded output
166  // that it will render, since the most recent of job construction or
167  // BeginPrerolling(). If false, |preroll_timestamp_| has been reached.
168  // TODO(qinmin): Comparing access unit's timestamp with |preroll_timestamp_|
169  // is not very accurate.
170  bool prerolling_;
171
172  // Weak pointer passed to media decoder jobs for callbacks. It is bounded to
173  // the decoder thread.
174  base::WeakPtrFactory<MediaDecoderJob> weak_this_;
175
176  // Callback used to request more data.
177  base::Closure request_data_cb_;
178
179  // Callback to run when new data has been received.
180  base::Closure on_data_received_cb_;
181
182  // Callback to run when the current Decode() operation completes.
183  DecoderCallback decode_cb_;
184
185  // The current access unit being processed.
186  size_t access_unit_index_;
187
188  // Data received over IPC from last RequestData() operation.
189  DemuxerData received_data_;
190
191  // The index of input buffer that can be used by QueueInputBuffer().
192  // If the index is uninitialized or invalid, it must be -1.
193  int input_buf_index_;
194
195  bool stop_decode_pending_;
196
197  // Indicates that this object should be destroyed once the current
198  // Decode() has completed. This gets set when Release() gets called
199  // while there is a decode in progress.
200  bool destroy_pending_;
201
202  DISALLOW_IMPLICIT_CONSTRUCTORS(MediaDecoderJob);
203};
204
205}  // namespace media
206
207#endif  // MEDIA_BASE_ANDROID_MEDIA_DECODER_JOB_H_
208