b4ae7ebc4c36d05c393445c07d8f9b9710cb336f
[platform/framework/web/chromium-efl.git] / tizen_src / impl / media / base / tizen / media_source_player_gstreamer.cc
1 // Copyright 2014 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.
4
5 #include "media/base/tizen/media_source_player_gstreamer.h"
6
7 #include <gst/app/gstappsink.h>
8 #include <gst/app/gstappsrc.h>
9 #include <gst/interfaces/xoverlay.h>
10 #include <gst/video/video.h>
11
12 #include "base/process/process.h"
13 #include "media/base/tizen/media_player_manager_tizen.h"
14
15 #if defined(OS_TIZEN_MOBILE) && (defined(TIZEN_V_2_3) || defined(TIZEN_V_2_4))
16 #include <device/power.h>
17 #endif
18
19 namespace {
20
21 const uint32 GST_VIDEO_SN12 = GST_MAKE_FOURCC('S','N','1','2');
22
23 const uint SN12_TILE_WIDTH = 64;
24 const uint SN12_TILE_HEIGHT = 32;
25 const uint SN12_TILE_SIZE = SN12_TILE_WIDTH * SN12_TILE_HEIGHT;
26
27 // Pipeline element name
28 const char* kPipelineName = "gst_pipeline";
29
30 // Update duration every 100ms.
31 const int kDurationUpdateInterval = 100;
32
33 // For smooth playback, seeking will be done to I-Frame + kSixteenMilliSeconds
34 // Reason to choose kSixteenMilliSeconds is duration of each video frame at
35 // 60 fps video will be ~16 milliseconds.
36 const int64 kSixteenMilliSeconds = 16000000;
37
38 const char *h264elements[] = {
39     "h264parse"
40 #if defined(OS_TIZEN)
41     , "omx_h264dec"
42 #else
43     , "ffdec_h264"
44 #endif
45 };
46
47 const char *aacelements[] = {
48     "aacparse"
49 #if defined(OS_TIZEN_MOBILE)
50     , "ffdec_aac", "autoaudiosink"
51 #elif defined(OS_TIZEN_TV)
52     , "omx_aacdec", "alsasink"
53 #else
54     , "faad", "autoaudiosink"
55 #endif
56 };
57
58 // FIXME: This is derived from command-line pipeline on desktop and mobile.
59 // Need to find the pipeline on TV.
60 // Also the connection might be different when converting it to code.
61 const char *mp3elements[] = {
62     "mpegaudioparse"
63     , "ffdec_mp3"
64     ,"autoaudiosink"
65 };
66
67 const AudioCodecGstElementsMapping AudioMapping[] = {
68     {media::kCodecAAC, aacelements},
69     {media::kCodecMP3, mp3elements},
70     {media::kUnknownAudioCodec, NULL}
71 };
72
73 const VideoCodecGstElementsMapping VideoMapping[] = {
74     {media::kCodecH264, h264elements},
75     {media::kUnknownVideoCodec, NULL}
76 };
77
78 GstClockTime ConvertToGstClockTime(double time) {
79   if (time < 0) {
80     LOG(ERROR) << "Invalid time:" << time << " Reset to 0";
81     time = 0;
82   }
83
84   // Extract the integer part of the time (seconds) and the fractional part
85   // (microseconds). Attempt to round the microseconds so no floating point
86   // precision is lost and we can perform an accurate seek.
87   double seconds;
88   double microSeconds = std::modf(time, &seconds) * 1000000;
89   GTimeVal timeValue;
90   timeValue.tv_sec = static_cast<glong>(seconds);
91   timeValue.tv_usec = static_cast<glong>(lround(microSeconds / 10) * 10);
92   return GST_TIMEVAL_TO_TIME(timeValue);
93 }
94
95 double ConvertNanoSecondsToSeconds(int64 time) {
96   double seconds = static_cast<double>(time) /
97       (base::Time::kNanosecondsPerSecond);
98   return seconds;
99 }
100
101 }  // namespace
102
103 namespace media {
104
105 static GstBusSyncReply gst_pipeline_message_cb(
106     GstBus* bus,
107     GstMessage* message,
108     gpointer user_data) {
109   MediaSourcePlayerGstreamer* player =
110       static_cast<MediaSourcePlayerGstreamer*>(user_data);
111   if (!player || player->IsPlayerDestructing())
112     return GST_BUS_PASS;
113
114   player->HandleMessage(message);
115   gst_message_unref(message);
116   return GST_BUS_DROP;
117 }
118
119 #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT)
120 static Eina_Bool notify_damage_updated_cb(
121     void* user_data,
122     int type,
123     void* event) {
124   MediaSourcePlayerGstreamer* player =
125       static_cast<MediaSourcePlayerGstreamer*>(user_data);
126   if (!player || player->IsPlayerDestructing())
127     return ECORE_CALLBACK_PASS_ON;
128   player->PlatformSurfaceUpdated();
129   return ECORE_CALLBACK_PASS_ON;
130 }
131 #endif
132
133 #if defined(OS_TIZEN_TV)
134 #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT)
135 static int get_pixmap_id_cb(void* user_data) {
136   MediaSourcePlayerGstreamer* player =
137       static_cast<MediaSourcePlayerGstreamer*>(user_data);
138   return player->GetSurfaceID();
139 }
140 #endif
141
142 static ASM_cb_result_t media_player_audio_session_event_source_pause(
143     ASM_event_sources_t event_source,
144     void* user_data) {
145   MediaPlayerTizen* player =
146       static_cast<MediaPlayerTizen*>(user_data);
147   if (!player) {
148     return ASM_CB_RES_IGNORE;
149   }
150
151   switch (event_source) {
152     case ASM_EVENT_SOURCE_CALL_START:
153     case ASM_EVENT_SOURCE_ALARM_START:
154     case ASM_EVENT_SOURCE_MEDIA:
155     case ASM_EVENT_SOURCE_EMERGENCY_START:
156     case ASM_EVENT_SOURCE_OTHER_PLAYER_APP:
157     case ASM_EVENT_SOURCE_RESOURCE_CONFLICT:
158     case ASM_EVENT_SOURCE_EARJACK_UNPLUG:
159       player->Pause(true);
160       return ASM_CB_RES_PAUSE;
161     default:
162       return ASM_CB_RES_NONE;
163   }
164 }
165
166 static ASM_cb_result_t media_player_audio_session_event_source_play(
167     ASM_event_sources_t event_source,
168     void* user_data) {
169   MediaPlayerTizen* player =
170       static_cast<MediaPlayerTizen*>(user_data);
171   if (!player) {
172     return ASM_CB_RES_IGNORE;
173   }
174
175   switch (event_source) {
176     case ASM_EVENT_SOURCE_ALARM_END:
177       player->Play();
178       return ASM_CB_RES_PLAYING;
179     default:
180       return ASM_CB_RES_NONE;
181   }
182 }
183
184 static ASM_cb_result_t media_player_private_audio_session_notify_cb(
185     int,
186     ASM_event_sources_t event_source,
187     ASM_sound_commands_t command,
188     unsigned int,
189     void* user_data) {
190   if (command == ASM_COMMAND_STOP || command == ASM_COMMAND_PAUSE)
191     return media_player_audio_session_event_source_pause(
192         event_source, user_data);
193   if (command == ASM_COMMAND_PLAY || command == ASM_COMMAND_RESUME)
194     return media_player_audio_session_event_source_play(
195         event_source, user_data);
196   return ASM_CB_RES_NONE;
197 }
198 #endif
199
200 static void  on_gst_start_video_feed_cb(
201     GstAppSrc* pipeline,
202     guint size,
203     void *user_data) {
204   MediaSourcePlayerGstreamer* player =
205       static_cast<MediaSourcePlayerGstreamer*>(user_data);
206   if (!player || player->IsPlayerDestructing())
207     return;
208   player->OnReadDemuxedData(media::DemuxerStream::VIDEO);
209   return ;
210 }
211
212 static void  on_gst_stop_video_feed_cb(GstAppSrc * pipeline,void *user_data) {
213   MediaSourcePlayerGstreamer* player =
214       static_cast<MediaSourcePlayerGstreamer*>(user_data);
215   if (!player || player->IsPlayerDestructing())
216     return;
217   player->OnStopDemuxedData(media::DemuxerStream::VIDEO);
218 }
219
220 static gboolean on_gst_seek_video_feed_cb(
221     GstAppSrc* pipeline,
222     guint64 offset,
223     void *user_data) {
224
225   MediaSourcePlayerGstreamer* player =
226       static_cast<MediaSourcePlayerGstreamer*>(user_data);
227   if (!player || player->IsPlayerDestructing())
228     return FALSE;
229   player->UpdateVideoSeekOffset(offset);
230   return TRUE;
231 }
232
233 static GstFlowReturn on_gst_appsink_preroll(
234     GstAppSink* sink,
235     gpointer user_data) {
236   MediaSourcePlayerGstreamer* player =
237       static_cast<MediaSourcePlayerGstreamer*>(user_data);
238   if (!player || player->IsPlayerDestructing())
239     return GST_FLOW_ERROR;
240   player->GetFrameDetails();
241   return GST_FLOW_OK;
242 }
243
244 static GstFlowReturn on_gst_appsink_buffer(
245     GstAppSink* sink,
246     gpointer user_data) {
247   MediaSourcePlayerGstreamer* player =
248       static_cast<MediaSourcePlayerGstreamer*>(user_data);
249   if (!player || player->IsPlayerDestructing())
250     return GST_FLOW_ERROR;
251   player->OnNewFrameAvailable(player->PullBuffer());
252   return GST_FLOW_OK;
253 }
254
255 gboolean on_gst_seek_audio_feed_cb(
256     GstAppSrc *pipeline,
257     guint64 offset,
258     void* user_data) {
259   MediaSourcePlayerGstreamer* player =
260       static_cast<MediaSourcePlayerGstreamer*>(user_data);
261   if (!player || player->IsPlayerDestructing())
262     return FALSE;
263   player->UpdateAudioSeekOffset(offset);
264   return TRUE;
265 }
266
267 static void on_gst_start_audio_feed_cb (
268     GstAppSrc * pipeline,
269     guint size,
270     void* user_data) {
271   MediaSourcePlayerGstreamer* player =
272       static_cast<MediaSourcePlayerGstreamer*>(user_data);
273   if (!player || player->IsPlayerDestructing())
274     return;
275   player->OnReadDemuxedData(media::DemuxerStream::AUDIO);
276 }
277
278 static void on_gst_stop_audio_feed_cb(GstAppSrc* pipeline, void* user_data) {
279   MediaSourcePlayerGstreamer* player =
280       static_cast<MediaSourcePlayerGstreamer*>(user_data);
281   if (!player || player->IsPlayerDestructing())
282     return;
283   player->OnStopDemuxedData(media::DemuxerStream::AUDIO);
284 }
285
286 #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT)
287 static void on_video_sink_caps_changed_cb(
288     GObject* gobject,
289     GParamSpec* gparamspec,
290     void* user_data) {
291   MediaSourcePlayerGstreamer* player =
292       static_cast<MediaSourcePlayerGstreamer*>(user_data);
293   if (!player || player->IsPlayerDestructing())
294     return;
295   player->OnVideoConfigsChanged();
296 }
297 #endif
298
299 // Generating Unique string from given width and height.
300 std::string ConvertWidthAndHeightToString(int width, int height) {
301   std::ostringstream width_stream, height_stream;
302   width_stream << width;
303   height_stream << height;
304   return width_stream.str() + "X" + height_stream.str();
305 }
306
307 MediaSourcePlayerGstreamer::MediaSourcePlayerGstreamer(
308     int player_id,
309     scoped_ptr<DemuxerTizen> demuxer,
310     MediaPlayerManager* manager)
311     : MediaPlayerTizen(player_id, manager),
312       demuxer_(demuxer.Pass()),
313       main_loop_(base::MessageLoopProxy::current()),
314 #if defined(OS_TIZEN_TV)
315       audio_session_manager_(AudioSessionManager::CreateAudioSessionManager()),
316 #endif
317       playing_(false),
318       weak_this_(this),
319 #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT)
320       pixmap_id_(0),
321       efl_pixmap_(NULL),
322       m_damage(0),
323       m_damageHandler(0),
324 #endif
325       is_xwindow_handle_set_(false),
326       is_backed_by_pixmap(false),
327       pipeline_(NULL),
328       video_appsrc_(NULL),
329       video_parse_(NULL),
330       video_decoder_(NULL),
331       video_sink_(NULL),
332       audio_appsrc_(NULL),
333       audio_decoder_(NULL),
334       audio_sink_(NULL),
335       video_queue_(NULL),
336       audio_queue_(NULL),
337       audio_parse_(NULL),
338       audio_convert_(NULL),
339       audio_resampler_(NULL),
340       audio_volume_(NULL),
341       video_sink_pad_(NULL),
342       should_feed_audio_(true),
343       should_feed_video_(false),
344       gst_width_(0),
345       gst_height_(0),
346       video_format_(0),
347       media_type(0),
348       play_rate_(1.0f),
349       duration_(0),
350       is_paused_due_underflow_(false),
351       shared_memory_size(0),
352       buffered_(0),
353       is_paused_(false),
354       is_seeking_(false),
355       is_demuxer_seeking_(false),
356       audio_buffered_(0),
357       video_buffered_(0),
358       is_gst_pipeline_constructed_(false),
359       is_download_finished_(false),
360       is_end_reached_(false),
361       error_occured_(false),
362       raw_video_frame_size_(0),
363       video_seek_offset_(0),
364       audio_seek_offset_(0),
365       is_seeking_iframe_(false) {
366   demuxer_->Initialize(this);
367   audio_buffer_queue_.clear();
368   video_buffer_queue_.clear();
369 #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT)
370   efl_pixmaps_map_.clear();
371 #endif
372 #if defined(OS_TIZEN_TV)
373   if (!audio_session_manager_->RegisterAudioSessionManager(
374       MM_SESSION_TYPE_SHARE,
375       media_player_private_audio_session_notify_cb, this))
376     return;
377 #endif
378 }
379
380 MediaSourcePlayerGstreamer::~MediaSourcePlayerGstreamer() {
381   VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__
382           << "Player ID:" << GetPlayerId();
383 }
384
385 void MediaSourcePlayerGstreamer::Destroy() {
386   if (IsPlayerDestructing())
387     return;
388
389   VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__
390           << "Player ID:" << GetPlayerId();
391   destructing_ = true;
392   Release();
393   main_loop_->DeleteSoon(FROM_HERE, this);
394 }
395
396 void MediaSourcePlayerGstreamer::Play() {
397   if (!pipeline_ || error_occured_)
398     return;
399   if (play_rate_ == 0.0) {
400     playing_ = true;
401     return;
402   }
403 #if defined(OS_TIZEN_TV)
404   if (!audio_session_manager_->SetSoundState(ASM_STATE_PLAYING))
405     return;
406 #endif
407   VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__
408           << "Player ID:" << GetPlayerId();
409
410 #if defined(OS_TIZEN_MOBILE) && (defined(TIZEN_V_2_3) || defined(TIZEN_V_2_4))
411   if (device_power_wakeup(false) != DEVICE_ERROR_NONE)
412     LOG(ERROR) << "|device_power_wakeup| request failed";
413
414   if (device_power_request_lock(POWER_LOCK_DISPLAY, 0) != DEVICE_ERROR_NONE)
415     LOG(ERROR) << "|device_power_request_lock| request failed";
416 #endif
417
418   gst_element_set_state(pipeline_, GST_STATE_PLAYING);
419   StartCurrentTimeUpdateTimer();
420   playing_ = true;
421   is_paused_due_underflow_ = false;
422 }
423
424 void MediaSourcePlayerGstreamer::Pause(bool is_media_related_action) {
425   if (!pipeline_ || error_occured_)
426     return;
427
428 #if defined(OS_TIZEN_TV)
429   if (!audio_session_manager_->SetSoundState(ASM_STATE_PAUSE))
430     return;
431 #endif
432
433   VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__;
434   gst_element_set_state(pipeline_, GST_STATE_PAUSED);
435
436   StopCurrentTimeUpdateTimer();
437   if (!is_media_related_action) {
438
439 #if defined(OS_TIZEN_MOBILE) && (defined(TIZEN_V_2_3) || defined(TIZEN_V_2_4))
440     if (device_power_release_lock(POWER_LOCK_DISPLAY) != DEVICE_ERROR_NONE)
441       LOG(ERROR) << "|device_power_release_lock| request failed";
442 #endif
443
444     is_paused_due_underflow_ = false;
445     playing_ = false;
446   }
447 }
448
449 void MediaSourcePlayerGstreamer::SetRate(double rate) {
450   VLOG(1) << "MediaSourcePlayerGstreamer::"
451           << __FUNCTION__ << " : " << rate;
452
453   if (play_rate_ == rate)
454     return;
455
456   if (rate == 0.0) {
457     play_rate_ = rate;
458     Pause(true);
459     return;
460   }
461
462   // If rate was zero and requested rate is non-zero, change the paused state
463   if(play_rate_ == 0.0 && rate != 0.0) {
464     Play();
465     StartCurrentTimeUpdateTimer();
466   }
467
468   play_rate_ = rate;
469
470   RequestPlayerSeek(GetCurrentTime());
471
472 #if defined(OS_TIZEN_TV)
473   if (!audio_session_manager_->SetSoundState(ASM_STATE_PAUSE))
474     return;
475 #endif
476 }
477
478 void MediaSourcePlayerGstreamer::RequestPlayerSeek(double seekTime) {
479   VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__
480           << " : " << seekTime;
481   if (is_demuxer_seeking_)
482     return;
483   GstState state;
484   gst_element_get_state(pipeline_, &state, NULL, 250 * GST_NSECOND);
485   is_demuxer_seeking_ = true;
486   if (state == GST_STATE_PLAYING)
487     Pause(true);
488   manager()->OnRequestSeek(GetPlayerId(), seekTime);
489 }
490
491 void MediaSourcePlayerGstreamer::Seek(const double time) {
492   GstState state;
493   gst_element_get_state(pipeline_, &state, NULL, 250 * GST_NSECOND);
494
495   is_seeking_iframe_ = false;
496   VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__
497           << " : " << time << " state : " << gst_element_state_get_name(state);
498
499   is_demuxer_seeking_ = true;
500   if (state == GST_STATE_PLAYING)
501     Pause(true);
502
503   // Input to |FromMicroseconds| is |int64|. Additional multiplication
504   // is done to avoid data loss.
505   base::TimeDelta seek_time = base::TimeDelta::FromMicroseconds(
506       static_cast<int64>(time * base::Time::kMicrosecondsPerSecond));
507   demuxer_->RequestDemuxerSeek(seek_time);
508 }
509
510 void MediaSourcePlayerGstreamer::SeekInternal(const GstClockTime position) {
511   if (!pipeline_ || error_occured_)
512     return;
513
514   GstClockTime startTime, endTime;
515
516   is_demuxer_seeking_ = false;
517
518   if (play_rate_ > 0) {
519     startTime = position;
520     endTime = GST_CLOCK_TIME_NONE;
521   } else {
522     startTime = 0;
523     endTime = position;
524   }
525
526   VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__
527           << " : " << position;
528
529   UpdateSeekState(true);
530   audio_buffer_queue_.clear();
531   video_buffer_queue_.clear();
532   if(!gst_element_seek(pipeline_, play_rate_, GST_FORMAT_TIME,
533       static_cast<GstSeekFlags>(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
534       GST_SEEK_TYPE_SET, startTime, GST_SEEK_TYPE_SET, endTime)) {
535     LOG(ERROR) << "Seek to " << position << " failed";
536     HandleError(MediaPlayerTizen::NetworkStateDecodeError);
537   }
538 }
539
540 double MediaSourcePlayerGstreamer::GetCurrentTime() {
541   if (!pipeline_ || error_occured_)
542     return 0.0;
543
544   gint64 current_time = 0;
545   GstFormat format = GST_FORMAT_TIME;
546   gst_element_query_position(pipeline_, &format, &current_time);
547   return ConvertNanoSecondsToSeconds(current_time);
548 }
549
550 void MediaSourcePlayerGstreamer::Release() {
551   VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__;
552   DCHECK(IsPlayerDestructing());
553   playing_ = false;
554   StopCurrentTimeUpdateTimer();
555   audio_buffer_queue_.clear();
556   video_buffer_queue_.clear();
557
558   if (pipeline_) {
559     GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline_));
560     if (bus) {
561       g_signal_handlers_disconnect_by_func(
562           bus, reinterpret_cast<gpointer>(gst_pipeline_message_cb), this);
563       gst_bus_set_sync_handler(bus, NULL, NULL);
564       gst_object_unref(bus);
565     }
566
567     gst_element_set_state(pipeline_, GST_STATE_NULL);
568     gst_object_unref(pipeline_);
569     pipeline_ = NULL;
570   }
571
572   if (video_sink_pad_)
573     gst_object_unref(video_sink_pad_);
574
575 #if defined(OS_TIZEN_TV)
576   if (!audio_session_manager_->SetSoundState(ASM_STATE_STOP))
577     return;
578   if (!audio_session_manager_->DeallocateResources())
579     return;
580 #endif
581 #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT)
582   UnregisterDamageHandler();
583   EflPixmapMap::iterator it = efl_pixmaps_map_.begin();
584   while (it != efl_pixmaps_map_.end()) {
585     efl_pixmap_ = it->second;
586     if (efl_pixmap_.get())
587       efl_pixmap_ = NULL;
588     it++;
589   }
590   efl_pixmaps_map_.clear();
591 #endif
592 }
593
594 #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT)
595 void MediaSourcePlayerGstreamer::UnregisterDamageHandler() {
596   if (m_damage) {
597     ecore_x_damage_free(m_damage);
598     m_damage = 0;
599   }
600   if (m_damageHandler) {
601     ecore_event_handler_del(m_damageHandler);
602     m_damageHandler = 0;
603   }
604 }
605 #endif
606
607 void MediaSourcePlayerGstreamer::SetVolume(double volume) {
608   if (audio_volume_)
609     g_object_set(G_OBJECT(audio_volume_), "volume", volume, NULL);
610 }
611
612 void MediaSourcePlayerGstreamer::OnDemuxerConfigsAvailable(
613     const DemuxerConfigs& configs) {
614   if (IsPlayerDestructing())
615     return;
616
617   if ((configs.video_codec == kUnknownVideoCodec ||
618       configs.video_codec != kCodecH264) &&
619       (configs.audio_codec == kUnknownAudioCodec ||
620       (configs.audio_codec != kCodecAAC &&
621       configs.audio_codec != kCodecMP3))) {
622     LOG(ERROR) << "Audio and Video codecs not supported for MediaSource";
623     HandleError(MediaPlayerTizen::NetworkStateFormatError);
624     return;
625   }
626
627   gst_width_ = configs.video_size.width();
628   gst_height_ = configs.video_size.height();
629
630   if (is_gst_pipeline_constructed_) {
631     return;
632   }
633   is_gst_pipeline_constructed_ = true;
634
635   GError* err = NULL;
636   if (!gst_is_initialized()) {
637     gst_init_check(NULL, NULL, &err);
638   }
639
640   if (gst_is_initialized() && !err) {
641     pipeline_ = gst_pipeline_new(kPipelineName);
642     if (!pipeline_) {
643       LOG(ERROR) << "Unable to Create |Pipeline|";
644       HandleError(MediaPlayerTizen::NetworkStateDecodeError);
645       return;
646     }
647
648     int i = 0;
649     while (VideoMapping[i].codec != kUnknownVideoCodec) {
650       if (configs.video_codec == VideoMapping[i].codec) {
651         media_type |= MEDIA_VIDEO_MASK;
652         video_appsrc_ = gst_element_factory_make("appsrc", "video-source");
653         video_parse_ = gst_element_factory_make(VideoMapping[i].elements[0],
654             "video-parse");
655         video_queue_ = gst_element_factory_make("queue2", "video-queue");
656         video_decoder_ = gst_element_factory_make(VideoMapping[i].elements[1],
657             "video-decoder");
658
659 #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT)
660         PrepareForVideoSink();
661 #else
662         PrepareForVideoFrame();
663 #endif
664
665 #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT)
666         if (is_backed_by_pixmap)
667           CreatePixmap();
668 #endif
669         if (!video_appsrc_ || !video_parse_ || !video_queue_ ||
670             !video_decoder_ || !video_sink_) {
671           LOG(ERROR) << "Not  all elements of video pipeline could be created";
672           ReleaseVideoElements();
673           HandleError(MediaPlayerTizen::NetworkStateDecodeError);
674           return;
675         }
676
677         g_object_set(GST_OBJECT(video_appsrc_), "format", GST_FORMAT_TIME, NULL);
678         g_object_set(GST_OBJECT(video_appsrc_), "stream-type",
679             GST_APP_STREAM_TYPE_SEEKABLE, NULL);
680         g_object_set(GST_OBJECT(video_appsrc_), "do-timestamp", false, NULL);
681
682         // Will make the queue to send GST_MESSAGE_BUFFERING
683         g_object_set(G_OBJECT(video_queue_), "use-buffering", true, NULL);
684
685         // Will trigger need-data callback if buffer goes below 30%,
686         // default is 10%. Data type of property "low-percent" differs
687         // on desktop and TIZEN platform.
688 #if defined(OS_TIZEN)
689         g_object_set(G_OBJECT(video_queue_), "low-percent", (double)30.0, NULL);
690 #else
691         g_object_set(G_OBJECT(video_queue_), "low-percent", 30, NULL);
692 #endif
693
694         gst_bin_add_many(GST_BIN(pipeline_), video_appsrc_, video_queue_,
695             video_parse_, video_decoder_, video_sink_, NULL);
696
697         // Why |video_queue_| is placed after |video_appsrc_|?
698         // For understanding puprose consider http://tinyurl.com/qos-iron url.
699         // For 1080p resolution of the video in above url, each decoded frame
700         // is of size 2304000 bytes ~ 2.19 MB. If video_queue_ is placed before
701         // |video_sink_| then queue will buffer decoded frames, so to buffer
702         // two second worth of data queue will require 2304000*24(fps)*2 ~ 96MB
703         // of queue size. This property can't be set for pixmap backed playback
704         // as frame size won't be available for pixmap backed | video_sink|.
705         // And this size varies from video to video.
706         //
707         // But if |video_queue_| is placed after |video_appsrc_|, queue will
708         // buffer encoded data. For the same video of 1080p, maximum encoded
709         // frame is of 115398byte ~ 0.110052109 MB. So for 2 sec data, queue
710         // need to buffer 5308308bytes in queue ~ 5MB, this can be set
711         // dynamically. Refer |OnDemuxerDataAvailable| for setting queue size.
712
713         gst_element_link_many(video_appsrc_,video_queue_, video_parse_,
714             video_decoder_, video_sink_, NULL);
715         static GstAppSrcCallbacks video_callbacks = {
716             on_gst_start_video_feed_cb,
717             on_gst_stop_video_feed_cb,
718             on_gst_seek_video_feed_cb, {NULL}};
719
720         // FIXME: Try fourth argument for destructy notification.
721         gst_app_src_set_callbacks(GST_APP_SRC(video_appsrc_), &video_callbacks,
722             this, NULL);
723         break;
724       }
725       i++;
726     }
727
728     i = 0;
729     while (AudioMapping[i].codec != kUnknownAudioCodec) {
730       if(configs.audio_codec == AudioMapping[i].codec) {
731         media_type |= MEDIA_AUDIO_MASK;
732         audio_appsrc_ = gst_element_factory_make("appsrc", "audio-source");
733         audio_queue_ = gst_element_factory_make("queue2", "audio-queue");
734         audio_parse_ = gst_element_factory_make(AudioMapping[i].elements[0],
735             "audio-parse");
736         audio_decoder_ = gst_element_factory_make(AudioMapping[i].elements[1],
737             "audio-decoder");
738         audio_convert_ = gst_element_factory_make("audioconvert", "audio-convert");
739         audio_resampler_ = gst_element_factory_make(
740             "audioresample", "audio-resample");
741         audio_volume_ = gst_element_factory_make("volume", "volume");
742         audio_sink_ = gst_element_factory_make(
743             AudioMapping[i].elements[2], "audio-sink");
744
745         if (!audio_appsrc_ || !audio_queue_ || !audio_parse_ ||
746             !audio_decoder_ || !audio_convert_ || !audio_resampler_ ||
747             !audio_volume_ || !audio_sink_) {
748           LOG(ERROR) << "Not  all elements of audio pipeline could be created";
749           ReleaseAudioElements();
750           HandleError(MediaPlayerTizen::NetworkStateDecodeError);
751           return;
752         }
753
754         g_object_set(
755             GST_OBJECT(audio_appsrc_),"format", GST_FORMAT_TIME, NULL);
756         g_object_set(GST_OBJECT(audio_appsrc_),"stream-type",
757             GST_APP_STREAM_TYPE_SEEKABLE, NULL);
758         g_object_set(GST_OBJECT(audio_appsrc_), "do-timestamp", false, NULL);
759
760         g_object_set(G_OBJECT(audio_queue_), "use-buffering", true, NULL);
761
762 #if defined(OS_TIZEN)
763         g_object_set(
764             G_OBJECT(audio_queue_), "low-percent", (double)30.0, NULL);
765 #else
766         g_object_set(G_OBJECT(audio_queue_), "low-percent", 30, NULL);
767 #endif
768
769         g_object_set(G_OBJECT(audio_volume_), "mute", false, NULL);
770
771 #if defined(OS_TIZEN_TV)
772         if (!audio_session_manager_->AllocateResources(audio_decoder_))
773           return;
774
775         g_object_set(audio_sink_, "provide-clock", true, "device", "hw:0,0", NULL);
776         if (!audio_session_manager_->AllocateResources(audio_sink_))
777           return;
778 #endif
779
780         gst_bin_add_many(GST_BIN(pipeline_), audio_appsrc_, audio_queue_,
781             audio_parse_, audio_decoder_, audio_convert_, audio_resampler_,
782             audio_volume_, audio_sink_, NULL);
783
784         gst_element_link_many(audio_appsrc_, audio_queue_, audio_parse_,
785             audio_decoder_, audio_convert_, audio_resampler_, audio_volume_,
786             audio_sink_, NULL);
787
788         static GstAppSrcCallbacks audio_callbacks = {
789             on_gst_start_audio_feed_cb,
790             on_gst_stop_audio_feed_cb,
791             on_gst_seek_audio_feed_cb, {NULL}};
792
793         gst_app_src_set_callbacks(GST_APP_SRC(audio_appsrc_), &audio_callbacks,
794             this, NULL);
795         break;
796       }
797       i++;
798     }
799
800     GstBus*bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline_));
801     if (!bus) {
802       LOG(ERROR) << "GStreamer bus creation failed";
803       HandleError(MediaPlayerTizen::NetworkStateDecodeError);
804       return;
805     }
806     gst_bus_set_sync_handler(
807         bus, (GstBusSyncHandler)gst_pipeline_message_cb, this);
808     gst_object_unref(bus);
809
810     manager()->OnMediaDataChange(GetPlayerId(), video_format_,
811         gst_height_, gst_width_, media_type);
812
813     manager()->OnReadyStateChange(GetPlayerId(),
814         MediaPlayerTizen::ReadyStateHaveMetadata);
815
816     if (gst_element_set_state(pipeline_, GST_STATE_PAUSED) ==
817         GST_STATE_CHANGE_FAILURE)
818       LOG(ERROR) << "GStreamer state change failed";
819   } else {
820     LOG(ERROR) << "Unable to initialize GST";
821     HandleError(MediaPlayerTizen::NetworkStateDecodeError);
822   }
823 }
824
825 #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT)
826 void MediaSourcePlayerGstreamer::PrepareForVideoSink() {
827   video_sink_ = gst_element_factory_make("xvimagesink", "sink");
828   if ( video_sink_ == NULL) {
829     PrepareForVideoFrame();
830   } else {
831     VLOG(1) << "MediaSource using |xvimagesink| for Video Playback";
832     is_backed_by_pixmap = true;
833     video_sink_pad_ = gst_element_get_static_pad(video_sink_, "sink");
834     if (video_sink_pad_) {
835       g_signal_connect(video_sink_pad_, "notify::caps",
836           G_CALLBACK(on_video_sink_caps_changed_cb), this);
837     } else {
838       LOG(ERROR) << " |video_sink_pad_| is NULL ?";
839     }
840   }
841 }
842 #endif
843
844 void MediaSourcePlayerGstreamer::PrepareForVideoFrame() {
845   is_xwindow_handle_set_ = true;
846   VLOG(1) << "MediaSource using |appsink| for Video Playback";
847   video_sink_ = gst_element_factory_make("appsink", "sink");
848   GstAppSinkCallbacks callbacks = {NULL,
849       on_gst_appsink_preroll,
850       on_gst_appsink_buffer,
851       NULL, {NULL, NULL, NULL}};
852   gst_app_sink_set_callbacks(GST_APP_SINK(video_sink_), &callbacks,
853       this, NULL);
854   g_object_set(G_OBJECT(video_sink_), "max-buffers", (guint)1, NULL);
855 }
856
857 void MediaSourcePlayerGstreamer::ReadDemuxedData(
858     media::DemuxerStream::Type type) {
859   if (IsPlayerDestructing())
860     return;
861
862   if (type == media::DemuxerStream::AUDIO) {
863     should_feed_audio_ = true;
864   } else if (type == media::DemuxerStream::VIDEO) {
865     should_feed_video_ = true;
866   } else {
867     LOG(ERROR) << "Unknown Media Type in MediaSourcePlayerGstreamer::"
868                << __FUNCTION__;
869     return;
870   }
871   demuxer_->RequestDemuxerData(type);
872 }
873
874 void MediaSourcePlayerGstreamer::OnReadDemuxedData(
875     media::DemuxerStream::Type type) {
876   if (IsPlayerDestructing()) {
877     LOG(ERROR) << __FUNCTION__ << "GST is deinitializing. Just return";
878     return;
879   }
880   main_loop_->PostTask(FROM_HERE, base::Bind(
881       &MediaSourcePlayerGstreamer::ReadDemuxedData, base::Unretained(this),
882       type));
883 }
884
885 void MediaSourcePlayerGstreamer::OnStopDemuxedData(
886     media::DemuxerStream::Type type) {
887   if (type == media::DemuxerStream::AUDIO)
888     should_feed_audio_ = false;
889   else if (type == media::DemuxerStream::VIDEO)
890     should_feed_video_ = false;
891   else
892     LOG(ERROR) << "Unknown Media Type in MediaSourcePlayerGstreamer::"
893                << __FUNCTION__;
894 }
895
896 void MediaSourcePlayerGstreamer::OnDemuxerDataAvailable(
897     base::SharedMemoryHandle foreign_memory_handle,
898     const media::DemuxedBufferMetaData& meta_data) {
899   if (!pipeline_ || error_occured_) {
900     LOG(ERROR) << "Pipeline_ null or error occured";
901     return;
902   }
903   if (meta_data.size <= 0) {
904     LOG(ERROR) << "ERROR : Size of shared memory is Zero";
905     return;
906   }
907
908   if (is_seeking_ && !is_seeking_iframe_) {
909     if (meta_data.type == media::DemuxerStream::VIDEO) {
910       is_seeking_iframe_ = true;
911       if (video_seek_offset_ >
912           (guint64)(meta_data.timestamp.InMicroseconds() * 1000)) {
913         RequestPlayerSeek((double)(ConvertNanoSecondsToSeconds(
914             meta_data.timestamp.InMicroseconds() * 1000
915             + kSixteenMilliSeconds)));
916         return;
917       }
918     } else if (meta_data.type == media::DemuxerStream::AUDIO) {
919         if ( audio_seek_offset_ >
920             (guint64)(meta_data.timestamp.InMicroseconds() * 1000))
921           return;
922     }
923   }
924
925   ReadFromQueueIfAny(meta_data.type);
926   if (meta_data.type == media::DemuxerStream::VIDEO) {
927     if (meta_data.size > raw_video_frame_size_) {
928       // Dynamically Changing Video Queue Size for Smooth Playback.
929       // The default queue size limits are 100 buffers, 2MB of data,
930       // or two seconds worth of data, whichever is reached first.
931       // Adjust queue to contain two seconds worth of data for smooth playback.
932       // So need to adjust number of buffers (max-size-buffers >= 2*fps) and
933       // maximum size of queue (max-size-bytes >= 2*fps*meta_data.size).
934       //
935       // 1000000 micro seconds = 1 second.
936       // 2097152 bytes = 2 MB.
937       int no_frames_per_two_second , queue_size_for_two_sec;
938       raw_video_frame_size_ = meta_data.size;
939       no_frames_per_two_second = 2 * (1000000 /
940           (meta_data.time_duration.InMicroseconds()));
941       queue_size_for_two_sec =
942           raw_video_frame_size_ * no_frames_per_two_second;
943       if (no_frames_per_two_second > 100) {
944         g_object_set(G_OBJECT(video_queue_), "max-size-buffers",
945             no_frames_per_two_second, NULL);
946       }
947       if (queue_size_for_two_sec > 2097152) {
948         g_object_set(G_OBJECT(video_queue_), "max-size-bytes",
949             queue_size_for_two_sec, NULL);
950       }
951     }
952   }
953   if (meta_data.type == media::DemuxerStream::AUDIO && !should_feed_audio_) {
954     // Why store the DecoderBuffer? we have requested for buffer
955     // from demuxer but gstreamer asked to stop. So need to save
956     // this buffer and use it on next |need_data| call.
957     SaveDecoderBuffer(foreign_memory_handle, meta_data);
958     return;
959   }
960   if (meta_data.type == media::DemuxerStream::VIDEO && !should_feed_video_) {
961     SaveDecoderBuffer(foreign_memory_handle, meta_data);
962     return;
963   }
964
965   base::SharedMemory shared_memory(foreign_memory_handle, false);
966   shared_memory.Map(meta_data.size);
967   void* ptr;
968   gint size = meta_data.size;
969   GstFlowReturn ret = GST_FLOW_OK;
970   ptr = g_malloc(size);
971   memcpy(ptr, shared_memory.memory(), size);
972
973   GstBuffer* buffer = gst_buffer_new();
974   GST_BUFFER_MALLOCDATA(buffer) = (uint8*)ptr;
975   GST_BUFFER_SIZE(buffer) = size;
976   GST_BUFFER_DATA(buffer) = GST_BUFFER_MALLOCDATA(buffer);
977   GST_BUFFER_TIMESTAMP (buffer) =
978       (guint64)(meta_data.timestamp.InMicroseconds() * 1000);
979   GST_BUFFER_DURATION (buffer) =
980       (guint64)(meta_data.time_duration.InMicroseconds() * 1000);
981
982   if (meta_data.type == media::DemuxerStream::AUDIO)
983     ret = gst_app_src_push_buffer(GST_APP_SRC(audio_appsrc_), buffer);
984   else if (meta_data.type == media::DemuxerStream::VIDEO)
985     ret = gst_app_src_push_buffer(GST_APP_SRC(video_appsrc_), buffer);
986
987   // gst_app_src_push_buffer() takes ownership of the buffer.
988   // Hence no need to unref buffer.
989   if (ret != GST_FLOW_OK) {
990     LOG(ERROR) << __FUNCTION__ << " : Gstreamer appsrc push failed : " << ret;
991     shared_memory.Close();
992     return;
993   }
994
995   if (meta_data.type == media::DemuxerStream::AUDIO && should_feed_audio_)
996     OnReadDemuxedData(media::DemuxerStream::AUDIO);
997   else if (meta_data.type == media::DemuxerStream::VIDEO && should_feed_video_)
998     OnReadDemuxedData(media::DemuxerStream::VIDEO);
999   shared_memory.Close();
1000   return;
1001 }
1002
1003 void MediaSourcePlayerGstreamer::OnBufferMetaDataAvailable(
1004     const media::DemuxedBufferMetaData& meta_data) {
1005
1006   if (!pipeline_ || error_occured_) {
1007     LOG(ERROR) << "Pipeline_ null or error occured";
1008     return;
1009   }
1010
1011   switch (meta_data.status) {
1012     case media::DemuxerStream::kAborted:
1013       // FIXME : Need to handle Aborted state Properly.
1014       if (meta_data.type == media::DemuxerStream::AUDIO && should_feed_audio_)
1015         OnReadDemuxedData(media::DemuxerStream::AUDIO);
1016       else if (meta_data.type == media::DemuxerStream::VIDEO &&
1017           should_feed_video_)
1018         OnReadDemuxedData(media::DemuxerStream::VIDEO);
1019       break;
1020
1021     case media::DemuxerStream::kConfigChanged:
1022       if (meta_data.type == media::DemuxerStream::AUDIO && should_feed_audio_)
1023         OnReadDemuxedData(media::DemuxerStream::AUDIO);
1024       else if (meta_data.type == media::DemuxerStream::VIDEO &&
1025           should_feed_video_)
1026         OnReadDemuxedData(media::DemuxerStream::VIDEO);
1027
1028       if (meta_data.type == media::DemuxerStream::AUDIO)
1029         VLOG(1) << "[BROWSER] : AUDIO::kConfigChanged";
1030       if (meta_data.type == media::DemuxerStream::VIDEO)
1031         VLOG(1) << "[BROWSER] : VIDEO::kConfigChanged";
1032       break;
1033
1034     case media::DemuxerStream::kOk:
1035       if (meta_data.end_of_stream) {
1036         ReadFromQueueIfAny(meta_data.type);
1037         LOG(ERROR) <<"[BROWSER] : DemuxerStream::kOk but |end_of_stream|";
1038         if (meta_data.type == media::DemuxerStream::AUDIO)
1039           gst_app_src_end_of_stream(GST_APP_SRC(audio_appsrc_));
1040         if (meta_data.type == media::DemuxerStream::VIDEO)
1041           gst_app_src_end_of_stream(GST_APP_SRC(video_appsrc_));
1042         if (playing_)
1043           Play();
1044       }
1045       break;
1046
1047     default:
1048       NOTREACHED();
1049   }
1050 }
1051
1052 void MediaSourcePlayerGstreamer::ReadFromQueueIfAny(
1053     DemuxerStream::Type type) {
1054   if (!pipeline_ || error_occured_) {
1055     LOG(ERROR) << "Pipeline_ null or error occured";
1056     return;
1057   }
1058
1059   if (type == media::DemuxerStream::AUDIO) {
1060     if (audio_buffer_queue_.empty() || !should_feed_audio_)
1061       return;
1062   }
1063
1064   if (type == media::DemuxerStream::VIDEO) {
1065     if (video_buffer_queue_.empty() || !should_feed_video_)
1066       return;
1067   }
1068
1069   scoped_refptr<DecoderBuffer> decoder_buffer;
1070   if (type == media::DemuxerStream::AUDIO) {
1071     decoder_buffer = audio_buffer_queue_.front();
1072     audio_buffer_queue_.pop_front();
1073   } else {
1074     decoder_buffer = video_buffer_queue_.front();
1075     video_buffer_queue_.pop_front();
1076   }
1077
1078   void* ptr;
1079   GstFlowReturn ret;
1080   gint size = decoder_buffer.get()->data_size();
1081   ptr = g_malloc(size);
1082   memcpy(ptr, (void*)decoder_buffer.get()->writable_data(), size);
1083   GstBuffer* buffer = gst_buffer_new();
1084   GST_BUFFER_MALLOCDATA(buffer) = (uint8*)ptr;
1085   GST_BUFFER_SIZE(buffer) = size;
1086   GST_BUFFER_DATA(buffer) = GST_BUFFER_MALLOCDATA(buffer);
1087   GST_BUFFER_TIMESTAMP (buffer) =
1088       (guint64)(decoder_buffer.get()->timestamp().InMicroseconds() * 1000);
1089   GST_BUFFER_DURATION (buffer) =
1090       (guint64)(decoder_buffer.get()->duration().InMicroseconds() * 1000);
1091
1092   if (type == media::DemuxerStream::AUDIO)
1093     ret = gst_app_src_push_buffer(GST_APP_SRC(audio_appsrc_), buffer);
1094   else
1095     ret = gst_app_src_push_buffer(GST_APP_SRC(video_appsrc_), buffer);
1096   if (ret != GST_FLOW_OK)
1097     return;
1098
1099   //Empty the Buffer before reading the new buffer from render process.
1100   ReadFromQueueIfAny(type);
1101   return;
1102 }
1103
1104 void MediaSourcePlayerGstreamer::SaveDecoderBuffer(
1105     base::SharedMemoryHandle foreign_memory_handle,
1106     const media::DemuxedBufferMetaData& meta_data) {
1107   if (!pipeline_ || error_occured_) {
1108     LOG(ERROR) << "Pipeline_ null or error occured";
1109     return;
1110   }
1111
1112   base::SharedMemory shared_memory(foreign_memory_handle, false);
1113   shared_memory.Map(meta_data.size);
1114   scoped_refptr<DecoderBuffer> buffer;
1115   buffer = DecoderBuffer::CopyFrom(static_cast<const uint8*> (
1116       shared_memory.memory()), meta_data.size);
1117
1118   if (!buffer.get()) {
1119     LOG(ERROR) << "DecoderBuffer::CopyFrom failed";
1120     shared_memory.Close();
1121     return;
1122   }
1123
1124   buffer->set_timestamp(meta_data.timestamp);
1125   buffer->set_duration(meta_data.time_duration);
1126
1127   if (meta_data.type == media::DemuxerStream::AUDIO)
1128     audio_buffer_queue_.push_back(buffer);
1129   else
1130     video_buffer_queue_.push_back(buffer);
1131
1132   shared_memory.Close();
1133 }
1134
1135 void MediaSourcePlayerGstreamer::GetFrameDetails() {
1136   if (!pipeline_ || error_occured_)
1137     return;
1138
1139   GstState state;
1140   GstState pending;
1141   GstStateChangeReturn ret = gst_element_get_state(pipeline_,
1142       &state, &pending, 250 * GST_NSECOND);
1143   VLOG(1) << "MediaSourcePlayerGstreamer::"
1144           << __FUNCTION__
1145           << " GstStateChangeReturn: "
1146           << gst_element_state_change_return_get_name(ret)
1147           << " state: "
1148           << gst_element_state_get_name(state)
1149           << " pending: "
1150           << gst_element_state_get_name(pending)
1151           << " ID " << GetPlayerId();
1152
1153   // Get details only after prerolling.
1154   if (pending >= GST_STATE_PAUSED)
1155     main_loop_->PostTask(FROM_HERE, base::Bind(
1156         &MediaSourcePlayerGstreamer::OnGetFrameDetails,
1157         base::Unretained(this)));
1158 }
1159
1160 void MediaSourcePlayerGstreamer::OnGetFrameDetails() {
1161   if (!pipeline_ || IsPlayerDestructing() || error_occured_)
1162     return;
1163
1164   GstBuffer* buffer = gst_app_sink_pull_preroll(GST_APP_SINK(video_sink_));
1165
1166   if (!buffer)
1167     return;
1168   GstCaps* caps = gst_buffer_get_caps(GST_BUFFER(buffer));
1169   if (!caps) {
1170     gst_buffer_unref(buffer);
1171     return;
1172   }
1173
1174   // No need to unref |GstStructure|
1175   const GstStructure* str = gst_caps_get_structure(caps, 0);
1176   gst_caps_unref(caps);
1177   gst_buffer_unref(buffer);
1178   if (!str)
1179     return;
1180
1181   if (!gst_structure_get_int(str, "width", &gst_width_) ||
1182       !gst_structure_get_int(str, "height", &gst_height_) ||
1183       !gst_structure_get_fourcc(str, "format", &video_format_)) {
1184     LOG(ERROR) << "Pre-rolled buffer information could not be obtained";
1185   }
1186
1187   if(video_format_ == GST_VIDEO_SN12) {
1188     uint tile_w_align = ((gst_width_ - 1) / SN12_TILE_WIDTH + 2) & ~1;
1189     bufsize_sn12_ =
1190         SN12_TILE_SIZE * tile_w_align * ((gst_height_-1)/SN12_TILE_HEIGHT+1)
1191         + (((gst_height_+1)&~1)/2) * tile_w_align * SN12_TILE_WIDTH;
1192   }
1193   manager()->OnMediaDataChange(GetPlayerId(), video_format_,
1194       gst_height_, gst_width_, media_type);
1195 }
1196
1197 GstBuffer* MediaSourcePlayerGstreamer::PullBuffer() {
1198   return gst_app_sink_pull_buffer(GST_APP_SINK(video_sink_));
1199 }
1200
1201 void MediaSourcePlayerGstreamer::OnNewFrameAvailable(const GstBuffer* buffer) {
1202   if (!pipeline_ || error_occured_)
1203     return;
1204   if (!buffer)
1205     return;
1206   if (!GST_BUFFER_DATA(buffer) || !GST_BUFFER_SIZE(buffer))
1207     return;
1208
1209   if (!gst_width_ || !gst_height_)
1210     GetFrameDetails();
1211   // FIXME: Cross check the end results.
1212   base::TimeDelta timestamp =
1213       base::TimeDelta::FromMicroseconds(
1214           GST_BUFFER_TIMESTAMP(buffer) /
1215           base::Time::kNanosecondsPerMicrosecond);
1216
1217   uint8* buffer_data = GST_BUFFER_DATA(buffer);
1218   gsize buffer_size = GST_BUFFER_SIZE(buffer);
1219
1220   if(video_format_ == GST_VIDEO_SN12)
1221     shared_memory_size = (bufsize_sn12_);
1222   else
1223     shared_memory_size = (buffer_size);
1224
1225   if (!shared_memory.CreateAndMapAnonymous(shared_memory_size)) {
1226     LOG (ERROR) << "Shared Memory creation failed.";
1227     gst_buffer_unref(GST_BUFFER(buffer));
1228     return;
1229   }
1230
1231   if (!shared_memory.ShareToProcess(base::Process::Current().Handle(),
1232       &foreign_memory_handle)) {
1233     LOG (ERROR) << "Shared Memory handle could not be obtained";
1234     shared_memory.Close();
1235     gst_buffer_unref(GST_BUFFER(buffer));
1236     return;
1237   }
1238
1239   memcpy(shared_memory.memory(), buffer_data, shared_memory_size);
1240   manager()->OnNewFrameAvailable(
1241       GetPlayerId(), foreign_memory_handle, shared_memory_size, timestamp);
1242
1243   shared_memory.Close();
1244   gst_buffer_unref(GST_BUFFER(buffer));
1245 }
1246
1247 #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT)
1248 void MediaSourcePlayerGstreamer::XWindowIdPrepared(GstMessage* message) {
1249   gint width, height;
1250   gst_structure_get_int(message->structure, "video-width", &width);
1251   gst_structure_get_int(message->structure, "video-height", &height);
1252   if ((gst_width_ != width) || (gst_height_ != height)) {
1253     LOG(ERROR) << "Demuxer Video Configs and Gstreamer Video Configs doesn't"
1254                <<" match.From Demuxer : width : "<<gst_width_
1255                << " and height :" <<gst_height_
1256                << " | From Gstreamer width : " <<width
1257                << " and Height : " <<height;
1258     gst_width_ = width;
1259     gst_height_ = height;
1260   }
1261   SetPixmap();
1262   manager()->OnMediaDataChange(
1263       GetPlayerId(), video_format_, gst_height_, gst_width_, media_type);
1264 }
1265
1266 void MediaSourcePlayerGstreamer::PlatformSurfaceUpdated() {
1267   gint64 current_time = 0;
1268   GstFormat format = GST_FORMAT_TIME;
1269   gst_element_query_position(pipeline_, &format, &current_time);
1270   base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(
1271       current_time / base::Time::kNanosecondsPerMicrosecond);
1272   manager()->OnPlatformSurfaceUpdated(GetPlayerId(), pixmap_id_, timestamp);
1273 }
1274
1275 int MediaSourcePlayerGstreamer::GetSurfaceID() const {
1276   return pixmap_id_;
1277 }
1278
1279 void MediaSourcePlayerGstreamer::SetPixmap() {
1280 #if defined(OS_TIZEN_TV)
1281   // Using below statements on mobile to set pixmap was causing two issue.
1282   // 1. Video size was different than the required one whenever configaration
1283   // changed
1284   // 2. Sometime black screen was appearing, while video was playing.
1285   // Hence for mobile keeping implementation which uses
1286   // |gst_x_overlay_set_window_handle|to sep Pixmap.
1287   g_object_set (video_sink_, "pixmap-id-callback", get_pixmap_id_cb, NULL);
1288   g_object_set (video_sink_, "pixmap-id-callback-userdata", this, NULL);
1289 #else
1290   gst_x_overlay_set_window_handle(GST_X_OVERLAY(video_sink_), pixmap_id_);
1291 #endif
1292   m_damage = ecore_x_damage_new(pixmap_id_,
1293       ECORE_X_DAMAGE_REPORT_RAW_RECTANGLES);
1294   m_damageHandler = ecore_event_handler_add(ECORE_X_EVENT_DAMAGE_NOTIFY,
1295       notify_damage_updated_cb, this);
1296   g_object_set(video_sink_, "rotate", 0, NULL);
1297   is_xwindow_handle_set_ = true;
1298 }
1299
1300 void MediaSourcePlayerGstreamer::OnVideoConfigsChanged() {
1301   if (!pipeline_ || error_occured_)
1302     return;
1303   main_loop_->PostTask(FROM_HERE, base::Bind(
1304       &MediaSourcePlayerGstreamer::VideoConfigsChanged,
1305           base::Unretained(this)));
1306 }
1307
1308 void MediaSourcePlayerGstreamer::VideoConfigsChanged() {
1309   if (!pipeline_ || IsPlayerDestructing() || error_occured_)
1310     return;
1311   VLOG(1) << "Video Configs Changed, so changing the pixmap";
1312   gint width, height;
1313
1314   if (gst_video_get_size(video_sink_pad_, &width, &height)) {
1315     if ((gst_width_ != width) || (gst_height_ != height)) {
1316       LOG(ERROR) << "Demuxer Video Configs and Gstreamer Video Configs doesn't"
1317                  <<" match.From Demuxer : width : "<<gst_width_
1318                  << " and height :" <<gst_height_
1319                  << " | From Gstreamer width : " <<width
1320                  << " and Height : " <<height;
1321       gst_width_ = width;
1322       gst_height_ = height;
1323       UnregisterDamageHandler();
1324       CreatePixmap();
1325       SetPixmap();
1326       manager()->OnMediaDataChange(
1327           GetPlayerId(), video_format_, gst_height_, gst_width_, media_type);
1328     }
1329   }
1330 }
1331
1332 void MediaSourcePlayerGstreamer::CreatePixmap() {
1333   bool is_create_new = false;
1334   std::string string_wh =
1335       ConvertWidthAndHeightToString(gst_width_, gst_height_);
1336   if (efl_pixmaps_map_.size() == 0)
1337     is_create_new = true;
1338
1339   if (!is_create_new) {
1340     EflPixmapMap::iterator it = efl_pixmaps_map_.find(string_wh);
1341     if (it != efl_pixmaps_map_.end()) {
1342       is_create_new = false;
1343       efl_pixmap_ = it->second;
1344       pixmap_id_ = efl_pixmap_->GetId();
1345     } else {
1346       is_create_new = true;
1347     }
1348   }
1349
1350   if (is_create_new) {
1351     efl_pixmap_ = gfx::EflPixmap::Create(gfx::EflPixmap::SURFACE,
1352         gfx::Size(gst_width_, gst_height_));
1353     if (!efl_pixmap_.get()) {
1354       LOG(ERROR) << "gfx::EflPixmap::Create() failed to create Pixmap";
1355       return;
1356     }
1357     pixmap_id_ = efl_pixmap_->GetId();
1358     efl_pixmaps_map_[string_wh] = efl_pixmap_;
1359   }
1360 }
1361 #endif
1362
1363 void MediaSourcePlayerGstreamer::OnDemuxerDurationChanged(
1364     base::TimeDelta duration) {
1365   duration_ = duration.InSecondsF();
1366 }
1367
1368 void MediaSourcePlayerGstreamer::OnDemuxerSeekDone(
1369     const base::TimeDelta& actual_browser_seek_time) {
1370   VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__ << " : "
1371           << actual_browser_seek_time.InSecondsF();
1372   SeekInternal(ConvertToGstClockTime(actual_browser_seek_time.InSecondsF()));
1373 }
1374
1375 bool MediaSourcePlayerGstreamer::HasVideo() {
1376   return media_type & MEDIA_VIDEO_MASK;
1377 }
1378
1379 bool MediaSourcePlayerGstreamer::HasAudio() {
1380   return media_type & MEDIA_AUDIO_MASK;
1381 }
1382
1383 void MediaSourcePlayerGstreamer::OnCurrentTimeUpdateTimerFired() {
1384   manager()->OnTimeUpdate(GetPlayerId(), GetCurrentTime());
1385 }
1386
1387 void MediaSourcePlayerGstreamer::StartCurrentTimeUpdateTimer() {
1388   if (!current_time_update_timer_.IsRunning()) {
1389     current_time_update_timer_.Start(
1390         FROM_HERE,
1391         base::TimeDelta::FromMilliseconds(kDurationUpdateInterval),
1392         this, &MediaSourcePlayerGstreamer::OnCurrentTimeUpdateTimerFired);
1393   }
1394 }
1395
1396 void MediaSourcePlayerGstreamer::StopCurrentTimeUpdateTimer() {
1397   if (current_time_update_timer_.IsRunning())
1398     current_time_update_timer_.Stop();
1399 }
1400
1401 void MediaSourcePlayerGstreamer::HandleMessage(GstMessage* message) {
1402   if (!pipeline_ || error_occured_)
1403     return;
1404   if (!strcmp(kPipelineName, GST_MESSAGE_SRC_NAME(message)))
1405     VLOG(1) << "MediaSourcePlayerGstreamer::" << __FUNCTION__
1406             << " Message " << GST_MESSAGE_TYPE_NAME(message)
1407             << " received from element " << GST_MESSAGE_SRC_NAME(message)
1408             << " ID " << GetPlayerId();
1409
1410 #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT)
1411   if (!IsXWindowHadleSet()) {
1412     if (message->structure && gst_structure_has_name(
1413         message->structure, "prepare-xid")) {
1414       VLOG(1) << "Received message-prepare-xid";
1415       XWindowIdPrepared(message);
1416       return;
1417     }
1418   }
1419 #endif
1420
1421   switch (GST_MESSAGE_TYPE(message)) {
1422   case GST_MESSAGE_ERROR:
1423     GError* error;
1424     gst_message_parse_error(message, &error, NULL);
1425     MediaPlayerTizen::NetworkState network_state_error;
1426     network_state_error = MediaPlayerTizen::NetworkStateEmpty;
1427     if (error->code == GST_STREAM_ERROR_CODEC_NOT_FOUND
1428         || error->code == GST_STREAM_ERROR_WRONG_TYPE
1429         || error->code == GST_STREAM_ERROR_FAILED
1430         || error->code == GST_RESOURCE_ERROR_NOT_FOUND) {
1431       network_state_error = MediaPlayerTizen::NetworkStateFormatError;
1432     } else if (error->domain == GST_RESOURCE_ERROR) {
1433       network_state_error = MediaPlayerTizen::NetworkStateNetworkError;
1434     } else {
1435       network_state_error = MediaPlayerTizen::NetworkStateDecodeError;
1436     }
1437 #if defined(OS_TIZEN_TV)
1438     if (!audio_session_manager_->SetSoundState(ASM_STATE_STOP))
1439       return;
1440     if (!audio_session_manager_->DeallocateResources())
1441       return;
1442 #endif
1443     LOG(ERROR) << "Error Message : " << error->message << " Recieved From : "
1444                << GST_MESSAGE_SRC_NAME(message)
1445                << ", and Blink Error Code  = " << network_state_error;
1446     g_error_free(error);
1447     HandleError(network_state_error);
1448     break;
1449   case GST_MESSAGE_EOS:
1450     VLOG(1) << "GST_MESSAGE_EOS";
1451 #if defined(OS_TIZEN_TV)
1452     if (!audio_session_manager_->SetSoundState(ASM_STATE_STOP))
1453       return;
1454     if (!audio_session_manager_->DeallocateResources())
1455       return;
1456 #endif
1457     main_loop_->PostTask(FROM_HERE, base::Bind(
1458         &MediaSourcePlayerGstreamer::OnPlaybackComplete,
1459         base::Unretained(this)));
1460     break;
1461   case GST_MESSAGE_ASYNC_DONE:
1462     VLOG(1) << "HandleMessage : GST_MESSAGE_ASYNC_DONE : is_seeking_ = "
1463             << is_seeking_;
1464     if (is_seeking_) {
1465       is_seeking_iframe_ = false;
1466       main_loop_->PostTask(FROM_HERE, base::Bind(
1467           &MediaSourcePlayerGstreamer::UpdateSeekState,
1468           base::Unretained(this), false));
1469
1470       // Initiate play for internal seeks.
1471       if (playing_)
1472         main_loop_->PostTask(FROM_HERE, base::Bind(
1473             &MediaSourcePlayerGstreamer::Play, base::Unretained(this)));
1474
1475       manager()->OnTimeUpdate(GetPlayerId(), GetCurrentTime());
1476       main_loop_->PostTask(FROM_HERE, base::Bind(
1477           &MediaSourcePlayerGstreamer::OnTimeChanged, base::Unretained(this)));
1478     }
1479
1480     // FIXME: Do we need to pull caps from PARSER? Can ignore if its of no use.
1481     break;
1482   case GST_MESSAGE_STATE_CHANGED:
1483     if (strcmp(kPipelineName, GST_MESSAGE_SRC_NAME(message)))
1484       break;
1485     main_loop_->PostTask(FROM_HERE, base::Bind(
1486         &MediaSourcePlayerGstreamer::OnUpdateStates, base::Unretained(this)));
1487     break;
1488   case GST_MESSAGE_BUFFERING:
1489     int buffered;
1490     gst_message_parse_buffering(message, &buffered);
1491
1492     if (audio_queue_ && GST_MESSAGE_SRC(message) == GST_OBJECT(audio_queue_))
1493       audio_buffered_ = buffered;
1494     if (video_queue_ && GST_MESSAGE_SRC(message) == GST_OBJECT(video_queue_))
1495       video_buffered_ = buffered;
1496
1497     if (!is_paused_due_underflow_ && playing_) {
1498       if (audio_buffered_ < 100 || video_buffered_ < 100) {
1499         main_loop_->PostTask(FROM_HERE, base::Bind(
1500             &MediaSourcePlayerGstreamer::HandleBufferingMessage,
1501             base::Unretained(this)));
1502       }
1503     } else if (is_paused_due_underflow_ && playing_) {
1504       if ((!HasAudio() || audio_buffered_ == 100) &&
1505           (!HasVideo() || video_buffered_ == 100)) {
1506         main_loop_->PostTask(FROM_HERE, base::Bind(
1507             &MediaSourcePlayerGstreamer::HandleBufferingMessage,
1508             base::Unretained(this)));
1509       }
1510     }
1511     break;
1512   default:
1513     VLOG(1) << "Unhandled GStreamer message type: "
1514             << GST_MESSAGE_TYPE_NAME(message);
1515     break;
1516   }
1517 }
1518
1519 void MediaSourcePlayerGstreamer::OnUpdateStates() {
1520   DCHECK(main_loop_->BelongsToCurrentThread());
1521   if (!pipeline_ || IsPlayerDestructing() || error_occured_)
1522     return;
1523
1524   GstState state;
1525   GstState pending;
1526   GstStateChangeReturn ret = gst_element_get_state(
1527       pipeline_, &state, &pending, 250 * GST_NSECOND);
1528
1529   VLOG(1) << "MediaSourcePlayerGstreamer::"
1530           << __FUNCTION__
1531           << " GstStateChangeReturn: "
1532           << gst_element_state_change_return_get_name(ret)
1533           << " state: "
1534           << gst_element_state_get_name(state)
1535           << " pending: "
1536           << gst_element_state_get_name(pending)
1537           << " ID " << GetPlayerId();
1538
1539   // FIXME: Handle all state changes
1540   switch (ret) {
1541   case GST_STATE_CHANGE_SUCCESS:
1542     switch (state) {
1543     case GST_STATE_PAUSED:
1544       manager()->OnReadyStateChange(
1545           GetPlayerId(), MediaPlayerTizen::ReadyStateHaveEnoughData);
1546       break;
1547     default:
1548       VLOG(1) << "GStreamer unhandled state "
1549               << gst_element_state_get_name(state);
1550       break;
1551     }
1552     break;
1553   case GST_STATE_CHANGE_FAILURE:
1554     LOG(ERROR) << "Failure: State: "
1555                << gst_element_state_get_name(state)
1556                << " pending: "
1557                << gst_element_state_get_name(pending);
1558     HandleError(MediaPlayerTizen::NetworkStateDecodeError);
1559     break;
1560   case GST_STATE_CHANGE_NO_PREROLL:
1561
1562     break;
1563   default:
1564     VLOG(1) << "Unhandled return type: " << ret;
1565     break;
1566   }
1567 }
1568
1569 void MediaSourcePlayerGstreamer::HandleBufferingMessage() {
1570   if (IsPlayerDestructing())
1571     return;
1572   if (!is_paused_due_underflow_ &&
1573       (audio_buffered_ < 100 || video_buffered_ < 100)) {
1574     is_paused_due_underflow_ = true;
1575     Pause(true);
1576     manager()->OnReadyStateChange(GetPlayerId(),
1577         MediaPlayerTizen::ReadyStateHaveCurrentData);
1578     manager()->OnNetworkStateChange(GetPlayerId(),
1579         MediaPlayerTizen::NetworkStateLoading);
1580   } else if (is_paused_due_underflow_ &&
1581       (!HasAudio() || audio_buffered_ == 100) &&
1582       (!HasVideo() || video_buffered_ == 100)) {
1583     is_paused_due_underflow_ = false;
1584     Play();
1585     manager()->OnReadyStateChange(GetPlayerId(),
1586         MediaPlayerTizen::ReadyStateHaveEnoughData);
1587     manager()->OnNetworkStateChange(GetPlayerId(),
1588         MediaPlayerTizen::NetworkStateLoaded);
1589   }
1590 }
1591
1592 void MediaSourcePlayerGstreamer::OnPlaybackComplete() {
1593   // GStreamer pipeline EOS time and media duration doesnt match.
1594   double time = GetCurrentTime() != duration_ ? duration_ : GetCurrentTime();
1595   is_end_reached_ = true;
1596   is_download_finished_ = false;
1597   StopCurrentTimeUpdateTimer();
1598   manager()->OnTimeUpdate(GetPlayerId(), time);
1599   manager()->OnTimeChanged(GetPlayerId());
1600
1601 #if defined(OS_TIZEN_MOBILE) && (defined(TIZEN_V_2_3) || defined(TIZEN_V_2_4))
1602   if (device_power_release_lock(POWER_LOCK_DISPLAY) != DEVICE_ERROR_NONE)
1603     LOG(ERROR) << "|device_power_release_lock| request failed";
1604 #endif
1605
1606 }
1607
1608 void MediaSourcePlayerGstreamer::UpdateSeekState(bool state) {
1609   manager()->OnSeekStateChange(GetPlayerId(), state);
1610   is_seeking_ = state;
1611 }
1612
1613 void MediaSourcePlayerGstreamer::OnTimeChanged() {
1614   VLOG(1) << "OnTimeChanged" << "Player ID : " << GetPlayerId();
1615   DCHECK(main_loop_->BelongsToCurrentThread());
1616   manager()->OnTimeChanged(GetPlayerId());
1617 }
1618
1619 void MediaSourcePlayerGstreamer::HandleError(
1620     media::MediaPlayerTizen::NetworkState state) {
1621   error_occured_ = true;
1622   manager()->OnNetworkStateChange(GetPlayerId(), state);
1623
1624 #if defined(OS_TIZEN_MOBILE) && (defined(TIZEN_V_2_3) || defined(TIZEN_V_2_4))
1625   if (device_power_release_lock(POWER_LOCK_DISPLAY) != DEVICE_ERROR_NONE)
1626     LOG(ERROR) << "|device_power_release_lock| request failed";
1627 #endif
1628
1629 }
1630
1631 void MediaSourcePlayerGstreamer::ReleaseAudioElements() {
1632   if (audio_appsrc_) {
1633     gst_object_unref(audio_appsrc_);
1634     audio_appsrc_ = NULL;
1635   }
1636
1637   if (audio_queue_) {
1638       gst_object_unref(audio_queue_);
1639       audio_queue_ = NULL;
1640   }
1641
1642   if (audio_parse_) {
1643       gst_object_unref(audio_parse_);
1644       audio_parse_ = NULL;
1645   }
1646
1647   if (audio_decoder_) {
1648       gst_object_unref(audio_decoder_);
1649       audio_decoder_ = NULL;
1650   }
1651
1652   if (audio_convert_) {
1653       gst_object_unref(audio_convert_);
1654       audio_convert_ = NULL;
1655   }
1656
1657   if (audio_resampler_) {
1658       gst_object_unref(audio_resampler_);
1659       audio_resampler_ = NULL;
1660   }
1661
1662   if (audio_volume_) {
1663       gst_object_unref(audio_volume_);
1664       audio_volume_ = NULL;
1665   }
1666
1667   if (audio_sink_) {
1668     gst_object_unref(audio_sink_);
1669     audio_sink_ = NULL;
1670   }
1671 }
1672
1673 void MediaSourcePlayerGstreamer::ReleaseVideoElements() {
1674   if(video_appsrc_) {
1675     gst_object_unref(video_appsrc_);
1676     video_appsrc_ = NULL;
1677   }
1678
1679   if(video_parse_) {
1680     gst_object_unref(video_parse_);
1681     video_parse_ = NULL;
1682   }
1683
1684   if(video_queue_) {
1685     gst_object_unref(video_queue_);
1686     video_queue_ = NULL;
1687   }
1688
1689   if(video_decoder_) {
1690     gst_object_unref(video_decoder_);
1691     video_decoder_ = NULL;
1692   }
1693
1694   if(video_sink_) {
1695     gst_object_unref(video_sink_);
1696     video_sink_ = NULL;
1697   }
1698 }
1699
1700 }  // namespace media