1 // Copyright 2015 Samsung Electronics Inc. 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.
5 #include "base/process/process.h"
6 #include "base/thread_task_runner_handle.h"
7 #include "content/browser/media/efl/browser_demuxer_efl.h"
8 #include "media/base/efl/media_player_manager_efl.h"
9 #include "media/base/tizen/media_source_player_capi.h"
10 #include "third_party/libyuv/include/libyuv.h"
13 const int kDurationUpdateInterval = 100;
15 // Waiting time for buffering while seeking.
16 const double kSeekBufferingWaitInSec = 2;
18 // CAPI internal appsrc buffer size.
19 const uint64 max_size = 2097152; // 2MB
21 // Appsrc minimum buffering level
22 const unsigned int min_threshold = 30;
27 void OnCapiPlayerPreparedCB(void* user_data) {
28 MediaSourcePlayerCapi* player =
29 static_cast<MediaSourcePlayerCapi*>(user_data);
30 player->OnPrepareComplete();
33 void OnSeekCompleteCB(void* user_data) {
34 MediaSourcePlayerCapi* player =
35 static_cast<MediaSourcePlayerCapi*>(user_data);
36 player->OnSeekComplete();
39 void OnHandleBufferingMessageCB(int percent, void* user_data) {
40 MediaSourcePlayerCapi* player =
41 static_cast<MediaSourcePlayerCapi*>(user_data);
42 player->OnHandleBufferingMessage(percent);
45 void OnCapiAudioBufStatusCB(player_media_stream_buffer_status_e status,
47 MediaSourcePlayerCapi* player =
48 static_cast<MediaSourcePlayerCapi*>(user_data);
49 if (status == PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN) {
50 player->OnUpdateDataStatus(media::DemuxerStream::AUDIO, true);
51 } else if (status == PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW) {
52 player->OnUpdateDataStatus(media::DemuxerStream::AUDIO, false);
56 void OnCapiVideoBufStatusCB(player_media_stream_buffer_status_e status,
58 MediaSourcePlayerCapi* player =
59 static_cast<MediaSourcePlayerCapi*>(user_data);
60 if (status == PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN) {
61 player->OnUpdateDataStatus(media::DemuxerStream::VIDEO, true);
62 } else if (status == PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW) {
63 player->OnUpdateDataStatus(media::DemuxerStream::VIDEO, false);
67 static void OnMediaPacketDecoded(media_packet_h packet, void* data) {
69 LOG(ERROR) << "media_packet handle is null";
73 MediaSourcePlayerCapi* player = static_cast<MediaSourcePlayerCapi*>(data);
74 player->OnMediaPacketUpdated(packet);
77 void OnPlaybackCompleteCB(void* user_data) {
78 LOG(INFO) << "On playback complete Call back";
79 MediaSourcePlayerCapi* player =
80 static_cast<MediaSourcePlayerCapi*>(user_data);
85 player->OnPlaybackComplete();
88 void OnPlayerErrorCB(int error_code, void* user_data) {
89 MediaSourcePlayerCapi* player =
90 static_cast<MediaSourcePlayerCapi*>(user_data);
95 player->OnHandlePlayerError(error_code, FROM_HERE);
98 void MediaSourcePlayerCapi::PrepareComplete() {
99 player_prepared_ = true;
100 manager()->OnReadyStateChange(
101 GetPlayerId(), blink::WebMediaPlayer::ReadyStateHaveEnoughData);
102 manager()->OnNetworkStateChange(
103 GetPlayerId(), blink::WebMediaPlayer::NetworkStateLoaded);
106 MediaPlayerEfl* MediaPlayerEfl::CreatePlayer(
107 int player_id, content::BrowserDemuxerEfl* demuxer,
108 int demuxer_id, MediaPlayerManager* manager) {
109 LOG(INFO) << "MediaSourceElement is using |CAPI| to play media";
110 return new MediaSourcePlayerCapi(player_id,
111 demuxer->CreateDemuxer(demuxer_id),
115 MediaSourcePlayerCapi::MediaSourcePlayerCapi(int player_id,
116 scoped_ptr<DemuxerEfl> demuxer,
117 MediaPlayerManager* manager)
118 : MediaPlayerEfl(player_id, manager),
119 demuxer_(std::move(demuxer)),
120 task_runner_(base::ThreadTaskRunnerHandle::Get()),
126 player_prepared_(false),
128 is_end_reached_(false),
131 error_occured_(false),
132 should_feed_audio_(false),
133 should_feed_video_(false),
135 seek_state_(MEDIA_SEEK_NONE),
139 weak_factory_(this) {
140 demuxer_->Initialize(this);
141 audio_buffer_queue_.clear();
142 video_buffer_queue_.clear();
145 int ret = player_create(&player_);
146 if (ret != PLAYER_ERROR_NONE) {
147 OnHandlePlayerError(ret, FROM_HERE);
151 ret = player_set_buffering_cb(player_, OnHandleBufferingMessageCB, this);
152 if (ret != PLAYER_ERROR_NONE) {
153 OnHandlePlayerError(ret, FROM_HERE);
157 ret = player_set_sound_type(player_, SOUND_TYPE_MEDIA);
158 if (ret != PLAYER_ERROR_NONE) {
159 OnHandlePlayerError(ret, FROM_HERE);
162 ret = player_set_error_cb(player_, OnPlayerErrorCB, this);
163 if (ret != PLAYER_ERROR_NONE) {
164 OnHandlePlayerError(ret, FROM_HERE);
167 ret = player_set_completed_cb(player_, OnPlaybackCompleteCB, this);
168 if (ret != PLAYER_ERROR_NONE) {
169 OnHandlePlayerError(ret, FROM_HERE);
173 ret = player_set_media_packet_video_frame_decoded_cb(
174 player_, OnMediaPacketDecoded, this);
175 if (ret != PLAYER_ERROR_NONE) {
176 OnHandlePlayerError(ret, FROM_HERE);
180 player_set_display_visible(player_, true);
182 ret = player_set_uri(player_, "es_buff://push_mode");
183 if (ret != PLAYER_ERROR_NONE) {
184 OnHandlePlayerError(ret, FROM_HERE);
189 MediaSourcePlayerCapi::~MediaSourcePlayerCapi() {
191 player_destroy(player_);
194 void MediaSourcePlayerCapi::SeekComplete() {
195 DCHECK(task_runner_->BelongsToCurrentThread());
196 UpdateSeekState(MEDIA_SEEK_NONE);
198 // Initiate play for internal seeks.
199 if (GetPlayerState() != PLAYER_STATE_PLAYING)
202 manager()->OnTimeUpdate(GetPlayerId(), GetCurrentTime());
203 manager()->OnTimeChanged(GetPlayerId());
207 void MediaSourcePlayerCapi::UpdateSeekState(MediaSeekState state) {
209 // Notify manager about player seek complete.
210 case MEDIA_SEEK_NONE:
211 manager()->OnSeekStateChange(GetPlayerId(), false);
214 // Notify manager about player seek start.
215 case MEDIA_SEEK_PLAYER:
216 manager()->OnSeekStateChange(GetPlayerId(), true);
219 // No need to notify manager about seek state change.
220 case MEDIA_SEEK_DEMUXER:
221 case MEDIA_SEEK_DEMUXER_DONE:
232 void MediaSourcePlayerCapi::SetRate(double rate) {
233 if (play_rate_ == rate)
242 // FIXME: |player_set_playback_rate| is always failing.
243 int err = player_set_playback_rate(player_, static_cast<float>(rate));
244 if (err != PLAYER_ERROR_NONE) {
245 OnHandlePlayerError(err, FROM_HERE);
248 // If previous rate was zero and requested rate is non-zero, change the
249 // playback rate and call play.
250 if (play_rate_ == 0.0) {
259 void MediaSourcePlayerCapi::Seek(const double time) {
260 UpdateSeekState(MEDIA_SEEK_DEMUXER);
261 if (GetPlayerState() == PLAYER_STATE_PLAYING)
266 base::TimeDelta seek_time = base::TimeDelta::FromSecondsD(time);
267 demuxer_->RequestDemuxerSeek(seek_time);
270 player_state_e MediaSourcePlayerCapi::GetPlayerState() {
271 player_state_e state = PLAYER_STATE_NONE;
272 player_get_state(player_, &state);
273 LOG(INFO) << __FUNCTION__ << " state " << state;
277 void MediaSourcePlayerCapi::SeekInternal() {
281 int ret = PLAYER_ERROR_NONE;
282 ret = player_set_play_position(
283 player_, ConvertSecondsToMilliSeconds(seek_offset_),
284 true, OnSeekCompleteCB, this);
288 MediaSeekState state = MEDIA_SEEK_PLAYER;
289 if (ret != PLAYER_ERROR_NONE) {
290 LOG(ERROR) << "Seek to " << " failed";
291 OnHandlePlayerError(ret, FROM_HERE);
292 state = MEDIA_SEEK_NONE;
294 UpdateSeekState(state);
297 void MediaSourcePlayerCapi::OnDemuxerDurationChanged(
298 base::TimeDelta duration) {
299 duration_ = duration.InSecondsF();
302 void MediaSourcePlayerCapi::OnDemuxerSeekDone(
303 const base::TimeDelta& actual_browser_seek_time) {
307 seek_offset_ = actual_browser_seek_time.InSecondsF();
308 UpdateSeekState(MEDIA_SEEK_DEMUXER_DONE);
310 audio_buffer_queue_.clear();
311 video_buffer_queue_.clear();
313 OnReadDemuxedData(media::DemuxerStream::AUDIO);
314 OnReadDemuxedData(media::DemuxerStream::VIDEO);
317 void MediaSourcePlayerCapi::OnMediaPacketUpdated(media_packet_h packet) {
318 ScopedMediaPacket packet_proxy(packet);
319 task_runner_->PostTask(
320 FROM_HERE, base::Bind(
321 &MediaSourcePlayerCapi::DeliverMediaPacket,
322 weak_factory_.GetWeakPtr(), base::Passed(&packet_proxy)));
325 void MediaSourcePlayerCapi::SetVolume(double volume) {
326 if (GetPlayerState() <= PLAYER_STATE_IDLE)
329 if (player_set_volume(player_, volume, volume) != PLAYER_ERROR_NONE)
330 LOG(ERROR) << "|player_set_volume| failed";
333 double MediaSourcePlayerCapi::GetCurrentTime() {
338 player_get_play_position(player_, &position);
339 return ConvertMilliSecondsToSeconds(position);
342 void MediaSourcePlayerCapi::OnCurrentTimeUpdateTimerFired() {
343 manager()->OnTimeUpdate(GetPlayerId(), GetCurrentTime());
346 void MediaSourcePlayerCapi::StartCurrentTimeUpdateTimer() {
347 if (current_time_update_timer_.IsRunning())
350 current_time_update_timer_.Start(
352 base::TimeDelta::FromMilliseconds(kDurationUpdateInterval),
354 &MediaSourcePlayerCapi::OnCurrentTimeUpdateTimerFired);
357 void MediaSourcePlayerCapi::StopCurrentTimeUpdateTimer() {
358 if (current_time_update_timer_.IsRunning())
359 current_time_update_timer_.Stop();
362 void MediaSourcePlayerCapi::Play() {
363 if (error_occured_ || playing_ || !player_prepared_)
366 if (play_rate_ == 0.0) {
371 #if defined(OS_TIZEN_MOBILE)
372 WakeUpDisplayAndAcquireDisplayLock();
374 int ret = player_start(player_);
375 if (ret != PLAYER_ERROR_NONE) {
376 OnHandlePlayerError(ret, FROM_HERE);
380 StartCurrentTimeUpdateTimer();
383 void MediaSourcePlayerCapi::Pause(bool is_media_related_action) {
384 if (error_occured_ || !playing_)
387 if (GetPlayerState() != PLAYER_STATE_PLAYING) {
388 LOG(WARNING) << "Can't PAUSE player";
392 int ret = player_pause(player_);
393 if (ret != PLAYER_ERROR_NONE) {
394 OnHandlePlayerError(ret, FROM_HERE);
397 StopCurrentTimeUpdateTimer();
398 if (!is_media_related_action) {
399 #if defined(OS_TIZEN_MOBILE)
400 ReleaseDisplayLock();
406 void MediaSourcePlayerCapi::PlaybackComplete() {
407 double time = GetCurrentTime() != duration_ ? duration_ : GetCurrentTime();
408 is_end_reached_ = true;
409 StopCurrentTimeUpdateTimer();
410 manager()->OnTimeUpdate(GetPlayerId(), time);
411 manager()->OnTimeChanged(GetPlayerId());
412 #if defined(OS_TIZEN_MOBILE)
413 ReleaseDisplayLock();
417 // TODO(sam) : It's worked as bypass now. Need Suspend/Resume/Initialize
418 // implementation for MSE multiple instance.
419 void MediaSourcePlayerCapi::Initialize() {
420 manager()->OnInitComplete(GetPlayerId(), true);
423 void MediaSourcePlayerCapi::Release() {
425 StopCurrentTimeUpdateTimer();
426 audio_buffer_queue_.clear();
427 video_buffer_queue_.clear();
429 player_unset_completed_cb(player_);
430 player_unset_media_packet_video_frame_decoded_cb(player_);
431 player_unprepare(player_);
433 manager()->OnSuspendComplete(GetPlayerId());
435 media_packet_destroy(media_packet_);
436 media_packet_ = NULL;
439 void MediaSourcePlayerCapi::OnDemuxerConfigsAvailable(
440 const DemuxerConfigs& configs) {
444 LOG(INFO) << "New width " << configs.video_size.width()
445 << " height " << configs.video_size.height();
446 if (GetPlayerState() > PLAYER_STATE_IDLE) {
447 media_format_set_video_width(video_format_, configs.video_size.width());
448 media_format_set_video_height(video_format_, configs.video_size.height());
451 int ret = PLAYER_ERROR_NONE;
453 if ((configs.video_codec == kUnknownVideoCodec ||
454 configs.video_codec != kCodecH264) &&
455 (configs.audio_codec == kUnknownAudioCodec ||
456 (configs.audio_codec != kCodecAAC &&
457 configs.audio_codec != kCodecMP3))) {
458 LOG(ERROR) << "Audio and Video codecs not supported for MediaSource";
459 OnHandlePlayerError(PLAYER_ERROR_NOT_SUPPORTED_FILE, FROM_HERE);
462 int samplerate = configs.audio_sampling_rate;
463 int channel = configs.audio_channels;
464 width_ = configs.video_size.width();
465 height_ = configs.video_size.height();
467 ret = media_format_create(&audio_format_);
468 if (ret != MEDIA_FORMAT_ERROR_NONE) {
469 LOG(ERROR) << "media_format_create : 0x" << ret;
473 media_format_mimetype_e audiomimeType = MEDIA_FORMAT_MP3;
474 if (configs.audio_codec == kCodecAAC)
475 audiomimeType = MEDIA_FORMAT_AAC;
477 LOG(INFO) << "samplerate: " << samplerate
478 << ", channel: " << channel
479 << ", audiomimeType: " << audiomimeType;
481 media_format_set_audio_mime(audio_format_, audiomimeType);
482 media_format_set_audio_channel(audio_format_, channel);
483 media_format_set_audio_samplerate(audio_format_, samplerate);
485 ret = player_set_media_stream_info(player_, PLAYER_STREAM_TYPE_AUDIO,
487 if (ret != PLAYER_ERROR_NONE) {
488 LOG(ERROR) << "player_set_audio_stream_info Error: " << ret;
491 ret = player_set_media_stream_buffer_status_cb(player_,
492 PLAYER_STREAM_TYPE_AUDIO,
493 OnCapiAudioBufStatusCB,
495 if (ret != PLAYER_ERROR_NONE) {
496 LOG(ERROR) << "player set audio buffer status cb failed :" << ret;
500 ret = media_format_create(&video_format_);
501 if (ret != MEDIA_FORMAT_ERROR_NONE) {
502 LOG(ERROR) << "media_format_create : 0x" << ret;
506 media_format_mimetype_e videomimeType = MEDIA_FORMAT_H264_SP;
508 media_format_set_video_mime(video_format_, videomimeType);
509 media_format_set_video_width(video_format_, width_);
510 media_format_set_video_height(video_format_, height_);
512 LOG(INFO) << "width: " << width_
513 << ", height: " << height_
514 << ", videomimeType: " << videomimeType;
516 ret = player_set_media_stream_info(player_,
517 PLAYER_STREAM_TYPE_VIDEO,
519 if (ret != PLAYER_ERROR_NONE) {
520 LOG(ERROR) << "player_set_video_stream_info Error: " << ret;
524 // FIXME(Kodam): This property should be updated based on dynamic
526 player_set_media_stream_buffer_max_size(
527 player_, PLAYER_STREAM_TYPE_VIDEO, max_size);
528 player_set_media_stream_buffer_min_threshold(
529 player_, PLAYER_STREAM_TYPE_VIDEO, min_threshold);
530 ret = player_set_media_stream_buffer_status_cb(player_,
531 PLAYER_STREAM_TYPE_VIDEO,
532 OnCapiVideoBufStatusCB,
534 if (ret != PLAYER_ERROR_NONE) {
535 LOG(ERROR) << "player set video buffer status cb failed : 0x" << ret;
539 // Audio stream is present if sample rate is valid.
541 media_type_ |= MEDIA_AUDIO_MASK;
543 // Video stream is present if both video width and height are valid.
544 if (width_ > 0 && height_ > 0)
545 media_type_ |= MEDIA_VIDEO_MASK;
547 manager()->OnMediaDataChange(GetPlayerId(), width_, height_, media_type_);
548 manager()->OnReadyStateChange(
549 GetPlayerId(), blink::WebMediaPlayer::ReadyStateHaveMetadata);
551 if (GetPlayerState() == PLAYER_STATE_IDLE) {
552 ret = player_prepare_async(player_, OnCapiPlayerPreparedCB, this);
553 if (ret != PLAYER_ERROR_NONE) {
554 LOG(ERROR) <<"player prepare failed : 0x " << ret;
559 // TODO(Venu): Need to check where is the exact place for this code.
560 // For make it work added this below code
561 // TODO(max): We have a contradiction here.
562 // To Complete preparing the capi-player, we have to get the first frame
563 // But to get the first frame we have to set readyState to EnoughData,
564 // even we are not ready for play(Setting the Enoughdata make HTML
565 // think that player is ready for play)
566 // We have to make some hack to get/set the first frame without notifying
568 manager()->OnReadyStateChange(
569 GetPlayerId(), blink::WebMediaPlayer::ReadyStateHaveEnoughData);
572 // Helper method that prints error occured with CAPI.
573 void MediaSourcePlayerCapi::OnMediaError(MediaError error_type) {
574 StopCurrentTimeUpdateTimer();
575 MediaPlayerEfl::OnMediaError(error_type);
578 void MediaSourcePlayerCapi::ReadDemuxedData(
579 media::DemuxerStream::Type type) {
580 demuxer_->RequestDemuxerData(type);
583 void MediaSourcePlayerCapi::HandleBufferingMessage(int percent) {
584 // FIXME: add code if required
588 void MediaSourcePlayerCapi::HandleUnderFlowStatus(
589 media::DemuxerStream::Type type, bool underflow_status) {
590 if (underflow_status) {
591 if (type == media::DemuxerStream::VIDEO) {
592 should_feed_video_ = underflow_status;
593 LOG(INFO) << "Video Underflow " << should_feed_video_
594 << " call CAPI Pause";
595 } else if (type == media::DemuxerStream::AUDIO) {
596 should_feed_audio_ = underflow_status;
597 LOG(INFO) << "Audio Underflow " << should_feed_audio_
598 << " call CAPI Pause";
600 if (player_prepared_) {
601 task_runner_->PostTask(
602 FROM_HERE, base::Bind(&MediaSourcePlayerCapi::Pause,
603 weak_factory_.GetWeakPtr(), true));
605 task_runner_->PostTask(
606 FROM_HERE, base::Bind(&MediaSourcePlayerCapi::ReadDemuxedData,
607 weak_factory_.GetWeakPtr(), type));
608 } else if (!underflow_status) {
609 if (type == media::DemuxerStream::VIDEO) {
610 should_feed_video_ = underflow_status;
611 LOG(INFO) << "Video Overflow " << should_feed_video_
612 << " call CAPI Play";
613 } else if (type == media::DemuxerStream::AUDIO) {
614 should_feed_audio_ = underflow_status;
615 LOG(INFO) << "Audio Overflow " << should_feed_audio_
616 << " call CAPI Play";
619 // FIXME(Kodam): Distinguish from user triggered PAUSE.
620 if ((!should_feed_audio_ || eos_audio_) &&
621 (!should_feed_video_ || eos_video_)) {
622 task_runner_->PostTask(
623 FROM_HERE, base::Bind(&MediaSourcePlayerCapi::Play,
624 weak_factory_.GetWeakPtr()));
630 void MediaSourcePlayerCapi::OnDemuxerDataAvailable(
631 base::SharedMemoryHandle foreign_memory_handle,
632 const media::DemuxedBufferMetaData& meta_data) {
633 if (error_occured_) {
634 LOG(ERROR) << "error occured";
638 if (meta_data.status != media::DemuxerStream::kOk ||
639 meta_data.end_of_stream)
640 BufferMetaDataAvailable(meta_data);
642 if (seek_state_ == MEDIA_SEEK_DEMUXER_DONE) {
643 // Seek either reached to eos or buffered enough data to seek.
644 if (meta_data.end_of_stream ||
645 (seek_offset_ + kSeekBufferingWaitInSec) <=
646 meta_data.timestamp.InSecondsF()) {
651 if (meta_data.size <= 0) {
652 LOG(ERROR) << "ERROR : Size of shared memory is Zero";
655 ReadFromQueueIfAny(meta_data.type);
657 if (meta_data.type == media::DemuxerStream::AUDIO && !should_feed_audio_) {
658 // Why store the DecoderBuffer? we have requested for buffer
659 // from demuxer but gstreamer asked to stop. So need to save
660 // this buffer and use it on next |need_data| call.
661 SaveDecoderBuffer(foreign_memory_handle, meta_data);
664 if (meta_data.type == media::DemuxerStream::VIDEO && !should_feed_video_) {
665 SaveDecoderBuffer(foreign_memory_handle, meta_data);
669 // Wrapping each frame and deleting shared memory using callback
670 // will not work as possibility of Gstreamer retaining frames (such as
671 // 'i' frames) is high. In that case shared memory will crash. So, we
672 // copy frames and release shared memory right away.
674 base::SharedMemory shared_memory(foreign_memory_handle, false);
675 if (!shared_memory.Map(meta_data.size)) {
676 LOG(ERROR) << "Failed to map shared memory of size " << meta_data.size;
680 if (meta_data.type == media::DemuxerStream::AUDIO) {
681 if (media_packet_create_from_external_memory(
682 audio_format_, static_cast<void*>(shared_memory.memory()),
683 meta_data.size, NULL, NULL, &media_packet_)
684 != MEDIA_PACKET_ERROR_NONE) {
685 LOG(ERROR) << "Audio media_packet_create_from_external_memory failed";
688 } else if (meta_data.type == media::DemuxerStream::VIDEO) {
689 if (media_packet_create_from_external_memory(
690 video_format_, static_cast<void*>(shared_memory.memory()),
691 meta_data.size, NULL, NULL, &media_packet_)
692 != MEDIA_PACKET_ERROR_NONE) {
693 LOG(ERROR) << "Video media_packet_create_from_external_memory failed";
698 if (media_packet_set_pts(media_packet_, meta_data.timestamp.InMilliseconds())
699 != MEDIA_PACKET_ERROR_NONE) {
700 LOG(ERROR) << "media_packet_set_pts failed";
703 if (player_push_media_stream(player_, media_packet_)
704 != MEDIA_PACKET_ERROR_NONE)
705 LOG(ERROR) << "player_push_media_stream failed";
707 if (meta_data.type == media::DemuxerStream::AUDIO)
708 media_format_unref(audio_format_);
709 else if (meta_data.type == media::DemuxerStream::VIDEO)
710 media_format_unref(video_format_);
713 media_packet_destroy(media_packet_);
714 media_packet_ = NULL;
716 if (meta_data.type == media::DemuxerStream::AUDIO)
717 OnReadDemuxedData(media::DemuxerStream::AUDIO);
718 else if (meta_data.type == media::DemuxerStream::VIDEO)
719 OnReadDemuxedData(media::DemuxerStream::VIDEO);
723 void MediaSourcePlayerCapi::BufferMetaDataAvailable(
724 const media::DemuxedBufferMetaData& meta_data) {
725 LOG(INFO) << __FUNCTION__ << " meta_data.type " << meta_data.type;
726 if (error_occured_) {
727 LOG(ERROR) << "Pipeline_ null or error occured";
731 switch (meta_data.status) {
732 case media::DemuxerStream::kAborted:
733 LOG(WARNING) << "[BROWSER] : DemuxerStream::kAborted, Stream type = "
735 case media::DemuxerStream::kConfigChanged:
736 if (meta_data.type == media::DemuxerStream::AUDIO)
737 OnReadDemuxedData(media::DemuxerStream::AUDIO);
738 else if (meta_data.type == media::DemuxerStream::VIDEO)
739 OnReadDemuxedData(media::DemuxerStream::VIDEO);
742 case media::DemuxerStream::kOk:
743 if (meta_data.end_of_stream) {
744 ReadFromQueueIfAny(meta_data.type);
745 LOG(INFO) <<"[BROWSER] : DemuxerStream::kOk but |end_of_stream|";
746 SendEosToCapi(meta_data);
757 void MediaSourcePlayerCapi::SendEosToCapi(
758 const media::DemuxedBufferMetaData& meta_data) {
759 if (meta_data.type == media::DemuxerStream::AUDIO) {
761 if (media_packet_create(audio_format_, NULL, NULL, &media_packet_)
762 != MEDIA_PACKET_ERROR_NONE) {
763 LOG(ERROR) << "Audio media_packet_create failed";
768 LOG(ERROR) << "Audio EOS Already Pushed";
771 } else if (meta_data.type == media::DemuxerStream::VIDEO) {
773 if (media_packet_create(video_format_, NULL, NULL, &media_packet_)
774 != MEDIA_PACKET_ERROR_NONE) {
775 LOG(ERROR) << "Video media_packet_create failed";
780 LOG(ERROR) << "Video EOS Already Pushed";
785 if (media_packet_set_flags(media_packet_, MEDIA_PACKET_END_OF_STREAM)
786 != MEDIA_PACKET_ERROR_NONE)
787 LOG(ERROR) << "media_packet_set_flags failed";
789 if (player_push_media_stream(player_, media_packet_)
790 != MEDIA_PACKET_ERROR_NONE)
791 LOG(ERROR) << "player_push_media_stream failed";
793 if (meta_data.type == media::DemuxerStream::AUDIO)
794 media_format_unref(audio_format_);
795 else if (meta_data.type == media::DemuxerStream::VIDEO)
796 media_format_unref(video_format_);
799 media_packet_destroy(media_packet_);
800 media_packet_ = NULL;
803 void MediaSourcePlayerCapi::ReadFromQueueIfAny(
804 DemuxerStream::Type type) {
805 if (error_occured_) {
806 LOG(ERROR) << "error occured in capi";
810 if (type == media::DemuxerStream::AUDIO) {
811 if (audio_buffer_queue_.empty() || !should_feed_audio_)
815 if (type == media::DemuxerStream::VIDEO) {
816 if (video_buffer_queue_.empty() || !should_feed_video_)
820 scoped_refptr<DecoderBuffer> decoder_buffer;
822 if (type == media::DemuxerStream::AUDIO) {
823 decoder_buffer = audio_buffer_queue_.front();
824 audio_buffer_queue_.pop_front();
825 } else if (type == media::DemuxerStream::VIDEO) {
826 decoder_buffer = video_buffer_queue_.front();
827 video_buffer_queue_.pop_front();
829 uint64 size = static_cast<uint64>(decoder_buffer.get()->data_size());
832 static_cast<uint64>(decoder_buffer.get()->timestamp().InMilliseconds());
833 if (type == media::DemuxerStream::AUDIO) {
834 if (media_packet_create_from_external_memory(
836 static_cast<void*>(decoder_buffer.get()->writable_data()),
837 size, NULL, NULL, &media_packet_)
838 != MEDIA_PACKET_ERROR_NONE) {
839 LOG(ERROR) << "Audio media_packet_create_from_external_memory failed";
842 } else if (type == media::DemuxerStream::VIDEO) {
843 if (media_packet_create_from_external_memory(
845 static_cast<void*>(decoder_buffer.get()->writable_data()),
846 size, NULL, NULL, &media_packet_)
847 != MEDIA_PACKET_ERROR_NONE) {
848 LOG(ERROR) << "Video media_packet_create_from_external_memory failed";
853 if (media_packet_set_pts(media_packet_, timestamp)
854 != MEDIA_PACKET_ERROR_NONE) {
855 LOG(ERROR) << "media_packet_set_pts failed";
859 if (player_push_media_stream(player_, media_packet_)
860 != MEDIA_PACKET_ERROR_NONE)
861 LOG(ERROR) << "player_push_media_stream failed";
863 if (type == media::DemuxerStream::AUDIO)
864 media_format_unref(audio_format_);
865 else if (type == media::DemuxerStream::VIDEO)
866 media_format_unref(video_format_);
868 // Empty the Buffer before reading the new buffer from render process.
870 media_packet_destroy(media_packet_);
871 media_packet_ = NULL;
873 ReadFromQueueIfAny(type);
877 void MediaSourcePlayerCapi::SaveDecoderBuffer(
878 base::SharedMemoryHandle foreign_memory_handle,
879 const media::DemuxedBufferMetaData& meta_data) {
880 if (error_occured_) {
881 LOG(ERROR) << "Error occured in capi";
885 base::SharedMemory shared_memory(foreign_memory_handle, false);
886 if (!shared_memory.Map(meta_data.size)) {
887 LOG(ERROR) << "Failed to map shared memory of size " << meta_data.size;
890 scoped_refptr<DecoderBuffer> buffer;
891 buffer = DecoderBuffer::CopyFrom(static_cast<const uint8*> (
892 shared_memory.memory()), meta_data.size);
895 LOG(ERROR) << "DecoderBuffer::CopyFrom failed";
899 buffer->set_timestamp(meta_data.timestamp);
900 buffer->set_duration(meta_data.time_duration);
902 if (meta_data.type == media::DemuxerStream::AUDIO)
903 audio_buffer_queue_.push_back(buffer);
904 else if (meta_data.type == media::DemuxerStream::VIDEO)
905 video_buffer_queue_.push_back(buffer);
908 void MediaSourcePlayerCapi::OnPrepareComplete() {
909 task_runner_->PostTask(
910 FROM_HERE, base::Bind(&MediaSourcePlayerCapi::PrepareComplete,
911 weak_factory_.GetWeakPtr()));
914 void MediaSourcePlayerCapi::OnPlaybackComplete() {
915 task_runner_->PostTask(
916 FROM_HERE, base::Bind(&MediaSourcePlayerCapi::PlaybackComplete,
917 weak_factory_.GetWeakPtr()));
920 void MediaSourcePlayerCapi::OnSeekComplete() {
921 task_runner_->PostTask(
922 FROM_HERE, base::Bind(&MediaSourcePlayerCapi::SeekComplete,
923 weak_factory_.GetWeakPtr()));
926 void MediaSourcePlayerCapi::OnHandleBufferingMessage(int percent) {
927 task_runner_->PostTask(
928 FROM_HERE, base::Bind(&MediaSourcePlayerCapi::HandleBufferingMessage,
929 weak_factory_.GetWeakPtr(),
933 void MediaSourcePlayerCapi::OnReadDemuxedData(
934 media::DemuxerStream::Type type) {
935 task_runner_->PostTask(
936 FROM_HERE, base::Bind(&MediaSourcePlayerCapi::ReadDemuxedData,
937 weak_factory_.GetWeakPtr(), type));
940 void MediaSourcePlayerCapi::OnUpdateDataStatus(
941 media::DemuxerStream::Type type, bool underflow_status) {
942 task_runner_->PostTask(
943 FROM_HERE, base::Bind(&MediaSourcePlayerCapi::HandleUnderFlowStatus,
944 weak_factory_.GetWeakPtr(),
949 void MediaSourcePlayerCapi::OnHandlePlayerError(
950 int player_error_code, const tracked_objects::Location& location) {
952 LOG(ERROR) << GetErrorString(player_error_code) << " from "
953 << location.ToString();
955 OnMediaError(GetMediaError(player_error_code));