media_source_player.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
1// Copyright (c) 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#include "media/base/android/media_source_player.h"
6
7#include "base/android/jni_android.h"
8#include "base/android/jni_string.h"
9#include "base/basictypes.h"
10#include "base/bind.h"
11#include "base/logging.h"
12#include "base/message_loop.h"
13#include "base/threading/thread.h"
14#include "media/base/android/media_codec_bridge.h"
15#include "media/base/android/media_player_manager.h"
16
17namespace {
18// Timeout value for media codec operations.
19const int kMediaCodecTimeoutInMicroseconds = 5000;
20}
21
22namespace media {
23
24MediaDecoderJob::MediaDecoderJob(
25    bool is_audio, const scoped_refptr<base::MessageLoopProxy>& message_loop)
26    : message_loop_(message_loop),
27      needs_flush_(false),
28      is_audio_(is_audio),
29      weak_this_(this) {
30}
31
32MediaDecoderJob::~MediaDecoderJob() {}
33
34// Class for managing audio decoding jobs.
35class AudioDecoderJob : public MediaDecoderJob {
36 public:
37  AudioDecoderJob(
38      const scoped_refptr<base::MessageLoopProxy>& message_loop,
39      const AudioCodec audio_codec, int sample_rate, int channel_count,
40      const uint8* extra_data, size_t extra_data_size);
41  virtual ~AudioDecoderJob() {}
42};
43
44// Class for managing video decoding jobs.
45class VideoDecoderJob : public MediaDecoderJob {
46 public:
47  VideoDecoderJob(
48      const scoped_refptr<base::MessageLoopProxy>& message_loop,
49      const VideoCodec video_codec, const gfx::Size& size, jobject surface);
50  virtual ~VideoDecoderJob() {}
51
52  void Configure(
53      const VideoCodec codec, const gfx::Size& size, jobject surface);
54};
55
56void MediaDecoderJob::Decode(
57    const MediaPlayerHostMsg_ReadFromDemuxerAck_Params::AccessUnit& unit,
58    const base::Time& start_wallclock_time,
59    const base::TimeDelta& start_presentation_timestamp,
60    const MediaDecoderJob::DecoderCallback& callback) {
61  if (!thread_->IsRunning())
62    thread_->Start();
63  thread_->message_loop()->PostTask(FROM_HERE, base::Bind(
64      &MediaDecoderJob::DecodeInternal, base::Unretained(this), unit,
65      start_wallclock_time, start_presentation_timestamp, needs_flush_,
66      callback));
67  needs_flush_ = false;
68}
69
70void MediaDecoderJob::DecodeInternal(
71    const MediaPlayerHostMsg_ReadFromDemuxerAck_Params::AccessUnit& unit,
72    const base::Time& start_wallclock_time,
73    const base::TimeDelta& start_presentation_timestamp,
74    bool needs_flush,
75    const MediaDecoderJob::DecoderCallback& callback) {
76  if (needs_flush)
77    media_codec_bridge_->Reset();
78  base::TimeDelta timeout = base::TimeDelta::FromMicroseconds(
79      kMediaCodecTimeoutInMicroseconds);
80  int input_buf_index = media_codec_bridge_->DequeueInputBuffer(timeout);
81  // TODO(qinmin): skip frames if video is falling far behind.
82  if (input_buf_index >= 0) {
83    if (unit.end_of_stream) {
84      media_codec_bridge_->QueueEOS(input_buf_index);
85    } else {
86      media_codec_bridge_->QueueInputBuffer(
87          input_buf_index, &unit.data[0], unit.data.size(), unit.timestamp);
88    }
89  }
90  size_t offset = 0;
91  size_t size = 0;
92  base::TimeDelta presentation_timestamp;
93  bool end_of_stream = false;
94
95  int outputBufferIndex = media_codec_bridge_->DequeueOutputBuffer(
96      timeout, &offset, &size, &presentation_timestamp, &end_of_stream);
97  switch (outputBufferIndex) {
98    case MediaCodecBridge::INFO_OUTPUT_BUFFERS_CHANGED:
99      media_codec_bridge_->GetOutputBuffers();
100      break;
101    case MediaCodecBridge::INFO_OUTPUT_FORMAT_CHANGED:
102      // TODO(qinmin): figure out what we should do if format changes.
103      break;
104    case MediaCodecBridge::INFO_TRY_AGAIN_LATER:
105      break;
106    default:
107      DCHECK_LE(0, outputBufferIndex);
108      if (size == 0 && end_of_stream)
109        break;
110      base::TimeDelta time_to_render;
111      if (!start_wallclock_time.is_null()) {
112        time_to_render = presentation_timestamp - (base::Time::Now() -
113            start_wallclock_time + start_presentation_timestamp);
114      }
115      if (time_to_render >= base::TimeDelta()) {
116        MessageLoop::current()->PostDelayedTask(
117            FROM_HERE,
118            base::Bind(&MediaDecoderJob::ReleaseOutputBuffer,
119                       weak_this_.GetWeakPtr(), outputBufferIndex, size,
120                       presentation_timestamp, end_of_stream, callback),
121            time_to_render);
122      } else {
123        // TODO(qinmin): The codec is lagging behind, need to recalculate the
124        // |start_presentation_timestamp_| and |start_wallclock_time_|.
125        DVLOG(1) << (is_audio_ ? "audio " : "video ")
126            << "codec is lagging behind :" << time_to_render.InMicroseconds();
127        ReleaseOutputBuffer(outputBufferIndex, size, presentation_timestamp,
128                            end_of_stream, callback);
129      }
130      return;
131  }
132  message_loop_->PostTask(FROM_HERE, base::Bind(
133      callback, start_presentation_timestamp, start_wallclock_time,
134      end_of_stream));
135}
136
137void MediaDecoderJob::ReleaseOutputBuffer(
138    int outputBufferIndex, size_t size,
139    const base::TimeDelta& presentation_timestamp,
140    bool end_of_stream, const MediaDecoderJob::DecoderCallback& callback) {
141  // TODO(qinmin): Refactor this function. Maybe AudioDecoderJob should provide
142  // its own ReleaseOutputBuffer().
143  if (is_audio_) {
144    static_cast<AudioCodecBridge*>(media_codec_bridge_.get())->PlayOutputBuffer(
145        outputBufferIndex, size);
146  }
147  media_codec_bridge_->ReleaseOutputBuffer(outputBufferIndex, !is_audio_);
148  message_loop_->PostTask(FROM_HERE, base::Bind(
149      callback, presentation_timestamp, base::Time::Now(), end_of_stream));
150}
151
152void MediaDecoderJob::Flush() {
153  // Do nothing, flush when the next Decode() happens.
154  needs_flush_ = true;
155}
156
157void MediaDecoderJob::Release() {
158  if (thread_->IsRunning() &&
159      thread_->message_loop() != base::MessageLoop::current()) {
160    thread_->message_loop()->DeleteSoon(FROM_HERE, this);
161  } else {
162    delete this;
163  }
164}
165
166VideoDecoderJob::VideoDecoderJob(
167    const scoped_refptr<base::MessageLoopProxy>& message_loop,
168    const VideoCodec video_codec, const gfx::Size& size, jobject surface)
169    : MediaDecoderJob(false, message_loop) {
170  scoped_ptr<VideoCodecBridge> codec(VideoCodecBridge::Create(video_codec));
171  codec->Start(video_codec, size, surface);
172  media_codec_bridge_.reset(codec.release());
173  thread_.reset(new base::Thread("MediaSource_VideoDecoderThread"));
174}
175
176AudioDecoderJob::AudioDecoderJob(
177    const scoped_refptr<base::MessageLoopProxy>& message_loop,
178    const AudioCodec audio_codec,
179    int sample_rate,
180    int channel_count,
181    const uint8* extra_data,
182    size_t extra_data_size)
183    : MediaDecoderJob(true, message_loop) {
184  scoped_ptr<AudioCodecBridge> codec(AudioCodecBridge::Create(audio_codec));
185  codec->Start(audio_codec, sample_rate, channel_count, extra_data,
186               extra_data_size, true);
187  media_codec_bridge_.reset(codec.release());
188  thread_.reset(new base::Thread("MediaSource_AudioDecoderThread"));
189}
190
191MediaSourcePlayer::MediaSourcePlayer(
192    int player_id,
193    MediaPlayerManager* manager)
194    : MediaPlayerAndroid(player_id, manager),
195      pending_event_(NO_EVENT_PENDING),
196      active_decoding_tasks_(0),
197      width_(0),
198      height_(0),
199      audio_codec_(kUnknownAudioCodec),
200      video_codec_(kUnknownVideoCodec),
201      num_channels_(0),
202      sampling_rate_(0),
203      seekable_(true),
204      audio_finished_(true),
205      video_finished_(true),
206      playing_(false),
207      audio_access_unit_index_(0),
208      video_access_unit_index_(0),
209      waiting_for_audio_data_(false),
210      waiting_for_video_data_(false),
211      use_empty_surface_(true),
212      weak_this_(this) {
213}
214
215MediaSourcePlayer::~MediaSourcePlayer() {
216  Release();
217}
218
219void MediaSourcePlayer::SetVideoSurface(jobject surface) {
220  use_empty_surface_ =  surface ? false : true;
221
222  // If we haven't processed a surface change event, do so now.
223  if (active_decoding_tasks_ > 0) {
224    pending_event_ |= SURFACE_CHANGE_EVENT_PENDING;
225    // Request a seek so that the next decoder will decode an I-frame first.
226    // Or otherwise, MediaCodec might crash. See b/8950387.
227    pending_event_ |= SEEK_EVENT_PENDING;
228    ProcessPendingEvents();
229    return;
230  }
231
232  if (HasVideo()) {
233    video_decoder_job_.reset(new VideoDecoderJob(
234        base::MessageLoopProxy::current(), video_codec_,
235        gfx::Size(width_, height_), surface));
236  }
237
238  // Inform the fullscreen view the player is ready.
239  // TODO(qinmin): refactor MediaPlayerBridge so that we have a better way
240  // to inform ContentVideoView.
241  OnMediaMetadataChanged(duration_, width_, height_, true);
242
243  if (pending_event_ & SURFACE_CHANGE_EVENT_PENDING) {
244    // We should already requested a seek in this case.
245    pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING;
246  } else {
247    // Perform a seek so the new decoder can get the I-frame first.
248    pending_event_ |= SEEK_EVENT_PENDING;
249    ProcessPendingEvents();
250    return;
251  }
252
253  if (playing_)
254    StartInternal();
255}
256
257void MediaSourcePlayer::Start() {
258  playing_ = true;
259  if (HasAudio() && !audio_decoder_job_) {
260    audio_decoder_job_.reset(new AudioDecoderJob(
261        base::MessageLoopProxy::current(), audio_codec_, sampling_rate_,
262        num_channels_, &audio_extra_data_[0], audio_extra_data_.size()));
263  }
264
265  if (HasVideo() && !video_decoder_job_) {
266    // StartInternal() will be delayed until SetVideoSurface() gets called.
267    return;
268  }
269
270  StartInternal();
271}
272
273void MediaSourcePlayer::Pause() {
274  playing_ = false;
275  start_wallclock_time_ = base::Time();
276}
277
278bool MediaSourcePlayer::IsPlaying() {
279  return playing_;
280}
281
282int MediaSourcePlayer::GetVideoWidth() {
283  return width_;
284}
285
286int MediaSourcePlayer::GetVideoHeight() {
287  return height_;
288}
289
290void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) {
291  last_presentation_timestamp_ = timestamp;
292  pending_event_ |= SEEK_EVENT_PENDING;
293  ProcessPendingEvents();
294}
295
296base::TimeDelta MediaSourcePlayer::GetCurrentTime() {
297  return last_presentation_timestamp_;
298}
299
300base::TimeDelta MediaSourcePlayer::GetDuration() {
301  return duration_;
302}
303
304void MediaSourcePlayer::Release() {
305  ClearDecodingData();
306  audio_decoder_job_.reset();
307  video_decoder_job_.reset();
308  active_decoding_tasks_ = 0;
309  playing_ = false;
310  pending_event_ = NO_EVENT_PENDING;
311  ReleaseMediaResourcesFromManager();
312}
313
314void MediaSourcePlayer::SetVolume(float leftVolume, float rightVolume) {
315}
316
317bool MediaSourcePlayer::CanPause() {
318  return seekable_;
319}
320
321bool MediaSourcePlayer::CanSeekForward() {
322  return seekable_;
323}
324
325bool MediaSourcePlayer::CanSeekBackward() {
326  return seekable_;
327}
328
329bool MediaSourcePlayer::IsPlayerReady() {
330  return audio_decoder_job_ || video_decoder_job_;
331}
332
333void MediaSourcePlayer::StartInternal() {
334  // Do nothing if the decoders are already running.
335  if (active_decoding_tasks_ > 0 || pending_event_ != NO_EVENT_PENDING)
336    return;
337
338  if (HasAudio()) {
339    audio_finished_ = false;
340    DecodeMoreAudio();
341  }
342  if (HasVideo()) {
343    video_finished_ = false;
344    DecodeMoreVideo();
345  }
346}
347
348void MediaSourcePlayer::DemuxerReady(
349    const MediaPlayerHostMsg_DemuxerReady_Params& params) {
350  if (params.duration_ms == std::numeric_limits<int>::max())
351    seekable_ = false;
352  duration_ = base::TimeDelta::FromMilliseconds(params.duration_ms);
353  width_ = params.video_size.width();
354  height_ = params.video_size.height();
355  num_channels_ = params.audio_channels;
356  sampling_rate_ = params.audio_sampling_rate;
357  audio_codec_ = params.audio_codec;
358  video_codec_ = params.video_codec;
359  audio_extra_data_ = params.audio_extra_data;
360  OnMediaMetadataChanged(duration_, width_, height_, true);
361}
362
363void MediaSourcePlayer::ReadFromDemuxerAck(
364    const MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) {
365  if (params.type == DemuxerStream::AUDIO)
366    waiting_for_audio_data_ = false;
367  else
368    waiting_for_video_data_ = false;
369
370  // If there is a pending seek request, ignore the data from the chunk demuxer.
371  // The data will be requested later when OnSeekRequestAck() is called.
372  if (pending_event_ & SEEK_EVENT_PENDING)
373    return;
374
375  if (params.type == DemuxerStream::AUDIO) {
376    DCHECK_EQ(0u, audio_access_unit_index_);
377    received_audio_ = params;
378    if (!pending_event_)
379      DecodeMoreAudio();
380  } else {
381    DCHECK_EQ(0u, video_access_unit_index_);
382    received_video_ = params;
383    if (!pending_event_)
384      DecodeMoreVideo();
385  }
386}
387
388void MediaSourcePlayer::OnSeekRequestAck() {
389  pending_event_ &= ~SEEK_EVENT_PENDING;
390  OnSeekComplete();
391  if (playing_)
392    StartInternal();
393}
394
395void MediaSourcePlayer::UpdateTimestamps(
396    const base::TimeDelta& presentation_timestamp,
397    const base::Time& wallclock_time) {
398  last_presentation_timestamp_ = presentation_timestamp;
399  OnTimeUpdated();
400  if (start_wallclock_time_.is_null() && playing_) {
401    start_wallclock_time_ = wallclock_time;
402    start_presentation_timestamp_ = last_presentation_timestamp_;
403  }
404}
405
406void MediaSourcePlayer::ProcessPendingEvents() {
407  // Wait for all the decoding jobs to finish before sending a seek request.
408  if (active_decoding_tasks_ > 0)
409    return;
410
411  DCHECK(pending_event_ != NO_EVENT_PENDING);
412  if (use_empty_surface_ && (pending_event_ & SURFACE_CHANGE_EVENT_PENDING)) {
413    video_decoder_job_.reset();
414    pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING;
415  }
416
417  ClearDecodingData();
418  manager()->OnMediaSeekRequest(player_id(),
419                                last_presentation_timestamp_,
420                                pending_event_ & SURFACE_CHANGE_EVENT_PENDING);
421}
422
423void MediaSourcePlayer::MediaDecoderCallback(
424    bool is_audio, const base::TimeDelta& presentation_timestamp,
425    const base::Time& wallclock_time, bool end_of_stream) {
426  if (active_decoding_tasks_ > 0)
427    active_decoding_tasks_--;
428
429  if (pending_event_ != NO_EVENT_PENDING) {
430    ProcessPendingEvents();
431    return;
432  }
433
434  if (is_audio || !HasAudio())
435    UpdateTimestamps(presentation_timestamp, wallclock_time);
436
437  if (end_of_stream) {
438    PlaybackCompleted(is_audio);
439    return;
440  }
441
442  if (!playing_)
443    return;
444
445  if (is_audio)
446    DecodeMoreAudio();
447  else
448    DecodeMoreVideo();
449}
450
451void MediaSourcePlayer::DecodeMoreAudio() {
452  if (audio_access_unit_index_ >= received_audio_.access_units.size()) {
453    if (!waiting_for_audio_data_) {
454      manager()->OnReadFromDemuxer(player_id(), DemuxerStream::AUDIO, true);
455      received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
456      audio_access_unit_index_ = 0;
457      waiting_for_audio_data_ = true;
458    }
459    return;
460  }
461
462  audio_decoder_job_->Decode(
463      received_audio_.access_units[audio_access_unit_index_],
464      start_wallclock_time_, start_presentation_timestamp_,
465      base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
466                 weak_this_.GetWeakPtr(), true));
467  active_decoding_tasks_++;
468  audio_access_unit_index_++;
469}
470
471void MediaSourcePlayer::DecodeMoreVideo() {
472  if (video_access_unit_index_ >= received_video_.access_units.size()) {
473    if (!waiting_for_video_data_) {
474      manager()->OnReadFromDemuxer(player_id(), DemuxerStream::VIDEO, true);
475      received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
476      video_access_unit_index_ = 0;
477      waiting_for_video_data_ = true;
478    }
479    return;
480  }
481
482  video_decoder_job_->Decode(
483      received_video_.access_units[video_access_unit_index_],
484      start_wallclock_time_, start_presentation_timestamp_,
485      base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
486                 weak_this_.GetWeakPtr(), false));
487  active_decoding_tasks_++;
488  video_access_unit_index_++;
489}
490
491
492void MediaSourcePlayer::PlaybackCompleted(bool is_audio) {
493  if (is_audio)
494    audio_finished_ = true;
495  else
496    video_finished_ = true;
497
498  if ((!HasAudio() || audio_finished_) && (!HasVideo() || video_finished_)) {
499    playing_ = false;
500    start_wallclock_time_ = base::Time();
501    OnPlaybackComplete();
502  }
503}
504
505void MediaSourcePlayer::ClearDecodingData() {
506  if (audio_decoder_job_)
507    audio_decoder_job_->Flush();
508  if (video_decoder_job_)
509    video_decoder_job_->Flush();
510  start_wallclock_time_ = base::Time();
511  received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
512  received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
513  audio_access_unit_index_ = 0;
514  video_access_unit_index_ = 0;
515}
516
517bool MediaSourcePlayer::HasVideo() {
518  return kUnknownVideoCodec != video_codec_;
519}
520
521bool MediaSourcePlayer::HasAudio() {
522  return kUnknownAudioCodec != audio_codec_;
523}
524
525}  // namespace media
526