Advertisement
Guest User

Untitled

a guest
Jun 21st, 2012
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 19.42 KB | None | 0 0
  1. /*
  2.  *  Copyright (C) 2012 Collabora Ltd. All rights reserved.
  3.  *
  4.  *  This library is free software; you can redistribute it and/or
  5.  *  modify it under the terms of the GNU Lesser General Public
  6.  *  License as published by the Free Software Foundation; either
  7.  *  version 2 of the License, or (at your option) any later version.
  8.  *
  9.  *  This library is distributed in the hope that it will be useful,
  10.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12.  *  Lesser General Public License for more details.
  13.  *
  14.  *  You should have received a copy of the GNU Lesser General Public
  15.  *  License along with this library; if not, write to the Free Software
  16.  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  17.  */
  18.  
  19.  
  20. #include "config.h"
  21.  
  22. #if ENABLE(MEDIA_STREAM) && USE(GSTREAMER)
  23.  
  24. #include "StreamMediaPlayerPrivateGStreamer.h"
  25.  
  26. #include "CentralPipelineUnit.h"
  27. #include "MediaStream.h"
  28.  
  29. #include "GraphicsContext.h"
  30. #include "GraphicsTypes.h"
  31. #include "GStreamerGWorld.h"
  32. #include "ImageGStreamer.h"
  33. #include "IntRect.h"
  34. #include "KURL.h"
  35. #include "MediaPlayer.h"
  36. #include "MediaStreamRegistry.h"
  37. #include "VideoSinkGStreamer.h"
  38. #include "WebKitWebSourceGStreamer.h"
  39. #include <wtf/gobject/GOwnPtr.h>
  40. #include <gst/gst.h>
  41. #include <gst/video/video.h>
  42. #include <math.h>
  43.  
  44. #include "Logging.h"
  45.  
  46. namespace WebCore {
  47.  
  48. void streamMediaPlayerPrivateVolumeChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
  49. void streamMediaPlayerPrivateMuteChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
  50. gboolean streamMediaPlayerPrivateVolumeChangeTimeoutCallback(StreamMediaPlayerPrivateGStreamer*);
  51. gboolean streamMediaPlayerPrivateMuteChangeTimeoutCallback(StreamMediaPlayerPrivateGStreamer*);
  52.  
  53.  
  54. static bool doGstInit();
  55.  
  56. static int greatestCommonDivisor(int a, int b)
  57. {
  58.     while (b) {
  59.         int temp = a;
  60.         a = b;
  61.         b = temp % b;
  62.     }
  63.  
  64.     return ABS(a);
  65. }
  66.  
  67. void streamMediaPlayerPrivateVolumeChangedCallback(GObject *element, GParamSpec *pspec, gpointer data)
  68. {
  69.     StreamMediaPlayerPrivateGStreamer* mp = reinterpret_cast<StreamMediaPlayerPrivateGStreamer*>(data);
  70.     mp->volumeChanged();
  71. }
  72.  
  73. gboolean streamMediaPlayerPrivateVolumeChangeTimeoutCallback(StreamMediaPlayerPrivateGStreamer* player)
  74. {
  75.     player->notifyPlayerOfVolumeChange();
  76.     return FALSE;
  77. }
  78.  
  79. void streamMediaPlayerPrivateMuteChangedCallback(GObject *element, GParamSpec *pspec, gpointer data)
  80. {
  81.     StreamMediaPlayerPrivateGStreamer* mp = reinterpret_cast<StreamMediaPlayerPrivateGStreamer*>(data);
  82.     mp->muteChanged();
  83. }
  84.  
  85. gboolean streamMediaPlayerPrivateMuteChangeTimeoutCallback(StreamMediaPlayerPrivateGStreamer* player)
  86. {
  87.     player->notifyPlayerOfMute();
  88.     return FALSE;
  89. }
  90.  
  91.  
  92. StreamMediaPlayerPrivateGStreamer::StreamMediaPlayerPrivateGStreamer(MediaPlayer* player)
  93.     : m_player(player)
  94.     , m_webkitVideoSink(0)
  95.     , m_videoSinkBin(0)
  96.     , m_audioSinkBin(0)
  97.     , m_volume(0)
  98.     , m_buffer(0)
  99.     , m_networkState(MediaPlayer::Empty)
  100.     , m_readyState(MediaPlayer::HaveNothing)
  101.     , m_paused(true)
  102.     , m_stopped(true)
  103.     , m_volumeTimerHandler(0)
  104.     , m_muteTimerHandler(0)
  105.     , m_repaintCallbackHandlerId(0)
  106. {
  107.     //LOG(StreamAPI, "StreamAPI - Creating Stream media player");
  108.  
  109.     if (doGstInit()) {
  110.         createGSTVideoSinkBin();
  111.         createGSTAudioSinkBin();
  112.     }
  113. }
  114.  
  115. StreamMediaPlayerPrivateGStreamer::~StreamMediaPlayerPrivateGStreamer()
  116. {
  117.     LOG(MediaStream, "StreamMediaPlayerPrivateGStreamer destructor called.");
  118.  
  119.     g_signal_handler_disconnect(m_webkitVideoSink, m_repaintCallbackHandlerId);
  120.  
  121.     if (m_buffer)
  122.         gst_buffer_unref(m_buffer);
  123.     m_buffer = 0;
  124.  
  125.     stop();
  126.  
  127.     if (m_audioSinkBin) {
  128.         gst_object_unref(m_audioSinkBin);
  129.         m_audioSinkBin = 0;
  130.     }
  131.  
  132.     if (m_videoSinkBin) {
  133.         gst_object_unref(m_videoSinkBin);
  134.         m_videoSinkBin = 0;
  135.     }
  136.  
  137.     m_player = 0;
  138.  
  139.     if (m_muteTimerHandler)
  140.         g_source_remove(m_muteTimerHandler);
  141.  
  142.     if (m_volumeTimerHandler)
  143.         g_source_remove(m_volumeTimerHandler);
  144. }
  145.  
  146. void StreamMediaPlayerPrivateGStreamer::play()
  147. {
  148.     LOG(MediaStream, "StreamMediaPlayerPrivateGStreamer::play() called.");
  149.     m_paused = false;
  150.  
  151.     internalLoad();
  152. }
  153.  
  154. void StreamMediaPlayerPrivateGStreamer::pause()
  155. {
  156.     LOG(MediaStream, "StreamMediaPlayerPrivateGStreamer::pause() called.");
  157.     m_paused = true;
  158.     stop();
  159. }
  160.  
  161.  
  162. bool StreamMediaPlayerPrivateGStreamer::hasVideo() const
  163. {
  164.     return !m_videoSourceId.isEmpty();
  165. }
  166.  
  167. bool StreamMediaPlayerPrivateGStreamer::hasAudio() const
  168. {
  169.     return !m_audioSourceId.isEmpty();
  170. }
  171.  
  172. void StreamMediaPlayerPrivateGStreamer::setVolume(float volume)
  173. {
  174.     if (!m_volume)
  175.         return;
  176.     g_object_set(m_volume, "volume", static_cast<double>(volume), NULL);
  177. }
  178.  
  179. void StreamMediaPlayerPrivateGStreamer::notifyPlayerOfVolumeChange()
  180. {
  181.     m_volumeTimerHandler = 0;
  182.  
  183.     if (!m_player || !m_volume)
  184.         return;
  185.     double volume;
  186.     g_object_get(m_volume, "volume", &volume, NULL);
  187.     m_player->volumeChanged(static_cast<float>(volume));
  188. }
  189.  
  190. void StreamMediaPlayerPrivateGStreamer::volumeChanged()
  191. {
  192.     if (m_volumeTimerHandler)
  193.         g_source_remove(m_volumeTimerHandler);
  194.     m_volumeTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(streamMediaPlayerPrivateVolumeChangeTimeoutCallback), this);
  195. }
  196.  
  197.  
  198. bool StreamMediaPlayerPrivateGStreamer::supportsMuting() const
  199. {
  200.     return true;
  201. }
  202.  
  203. void StreamMediaPlayerPrivateGStreamer::setMuted(bool muted)
  204. {
  205.     if (!m_volume)
  206.         return;
  207.  
  208.     g_object_set(m_volume, "mute", muted, NULL);
  209. }
  210.  
  211. void StreamMediaPlayerPrivateGStreamer::notifyPlayerOfMute()
  212. {
  213.     m_muteTimerHandler = 0;
  214.  
  215.     if (!m_player || !m_volume)
  216.         return;
  217.  
  218.     gboolean muted;
  219.     g_object_get(m_volume, "mute", &muted, NULL);
  220.     m_player->muteChanged(static_cast<bool>(muted));
  221. }
  222.  
  223. void StreamMediaPlayerPrivateGStreamer::muteChanged()
  224. {
  225.     if (m_muteTimerHandler)
  226.         g_source_remove(m_muteTimerHandler);
  227.     m_muteTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(streamMediaPlayerPrivateMuteChangeTimeoutCallback), this);
  228. }
  229.  
  230.  
  231. void StreamMediaPlayerPrivateGStreamer::load(const String &url)
  232. {
  233.     //LOG(StreamAPI, "StreamAPI - Stream media player - load");
  234.  
  235.     m_streamDescriptor = MediaStreamRegistry::registry().lookupMediaStreamDescriptor(url);
  236.     if (!m_streamDescriptor || m_streamDescriptor->ended()) {
  237.         loadingFailed(MediaPlayer::NetworkError);
  238.         return;
  239.     }
  240.  
  241.     m_readyState = MediaPlayer::HaveNothing;
  242.     m_networkState = MediaPlayer::Empty;
  243.     m_player->networkStateChanged();
  244.     m_player->readyStateChanged();
  245.  
  246.     if (!internalLoad())
  247.         return;
  248.  
  249.     if (hasVideo()) {
  250.         // Wait for first video frame to set HaveEnoughData
  251.         m_readyState = MediaPlayer::HaveNothing;
  252.     } else {
  253.         m_readyState = MediaPlayer::HaveEnoughData;
  254.     }
  255.  
  256.     m_networkState = MediaPlayer::Loaded;
  257.     m_player->networkStateChanged();
  258.     m_player->readyStateChanged();
  259.  
  260. }
  261.  
  262. void StreamMediaPlayerPrivateGStreamer::loadingFailed(MediaPlayer::NetworkState error)
  263. {
  264.  
  265.     if (m_networkState != error) {
  266.         m_networkState = error;
  267.         m_player->networkStateChanged();
  268.     }
  269.     if (m_readyState != MediaPlayer::HaveNothing) {
  270.         m_readyState = MediaPlayer::HaveNothing;
  271.         m_player->readyStateChanged();
  272.     }
  273. }
  274.  
  275. bool StreamMediaPlayerPrivateGStreamer::didLoadingProgress() const
  276. {
  277.     return true;
  278. }
  279.  
  280. bool StreamMediaPlayerPrivateGStreamer::internalLoad()
  281. {
  282.     if (m_stopped) {
  283.         m_stopped = false;
  284.         if (!m_streamDescriptor || m_streamDescriptor->ended()) {
  285.             loadingFailed(MediaPlayer::NetworkError);
  286.             return false;
  287.         }
  288.         return connectToGSTLiveStream(m_streamDescriptor.get());
  289.     }
  290.     return false;
  291. }
  292.  
  293. void StreamMediaPlayerPrivateGStreamer::stop()
  294. {
  295.     if (!m_stopped) {
  296.         m_stopped = true;
  297.         CentralPipelineUnit &cpu = centralPipelineUnit();
  298.         if (!m_audioSourceId.isEmpty()) {
  299.             LOG(MediaStream, "StreamMediaPlayerPrivateGStreamer stop: disconnecting audio");
  300.             cpu.disconnectFromSource(m_audioSourceId, m_audioSinkBin);
  301.         }
  302.         if (!m_videoSourceId.isEmpty()) {
  303.             LOG(MediaStream, "StreamMediaPlayerPrivateGStreamer stop: disconnecting video");
  304.             cpu.disconnectFromSource(m_videoSourceId, m_videoSinkBin);
  305.         }
  306.         m_audioSourceId = "";
  307.         m_videoSourceId = "";
  308.     }
  309. }
  310.  
  311.  
  312. void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer *buffer, StreamMediaPlayerPrivateGStreamer* playerPrivate)
  313. {
  314.     g_return_if_fail(GST_IS_BUFFER(buffer));
  315.  
  316.     if (!playerPrivate->m_buffer) {
  317.         playerPrivate->m_readyState = MediaPlayer::HaveEnoughData;
  318.         playerPrivate->m_player->readyStateChanged();
  319.     }
  320.  
  321.     if (!playerPrivate->m_paused || !playerPrivate->m_buffer) {
  322.         gst_buffer_replace(&playerPrivate->m_buffer, buffer);
  323.  
  324.         IntSize size = playerPrivate->calculateSize();
  325.         playerPrivate->updateCurrentSize(size);
  326.  
  327.         playerPrivate->repaint();
  328.     }
  329. }
  330.  
  331.  
  332. PassOwnPtr<MediaPlayerPrivateInterface> StreamMediaPlayerPrivateGStreamer::create(MediaPlayer* player)
  333. {
  334.     return adoptPtr(new StreamMediaPlayerPrivateGStreamer(player));
  335. }
  336.  
  337. void StreamMediaPlayerPrivateGStreamer::registerMediaEngine(MediaEngineRegistrar registrar)
  338. {
  339.     if (isAvailable())
  340.         registrar(create, getSupportedTypes, supportsType, 0, 0, 0);
  341. }
  342.  
  343. void StreamMediaPlayerPrivateGStreamer::getSupportedTypes(HashSet<String>& types)
  344. {
  345.     types.add(String("video/x-raw-yuv"));
  346.     types.add(String("audio/x-raw-int"));
  347. }
  348.  
  349. MediaPlayer::SupportsType StreamMediaPlayerPrivateGStreamer::supportsType(const String& type, const String& codecs, const String& url)
  350. {
  351.     UNUSED_PARAM(type);
  352.     UNUSED_PARAM(codecs);
  353.  
  354.     if (url.isNull() || url.isEmpty())
  355.         return MediaPlayer::IsNotSupported;
  356.  
  357.     return MediaStreamRegistry::registry().lookupMediaStreamDescriptor(url) ? MediaPlayer::IsSupported : MediaPlayer::IsNotSupported;
  358. }
  359.  
  360. static bool gstInitialized = false;
  361.  
  362. static bool doGstInit()
  363. {
  364.     if (!gstInitialized) {
  365.         GOwnPtr<GError> error;
  366.         gstInitialized = gst_init_check(0, 0, &error.outPtr());
  367.     }
  368.     return gstInitialized;
  369. }
  370.  
  371.  
  372. bool StreamMediaPlayerPrivateGStreamer::isAvailable()
  373. {
  374.  
  375.     if (!doGstInit())
  376.         return false;
  377.  
  378.     return true;
  379. }
  380.  
  381.  
  382. void StreamMediaPlayerPrivateGStreamer::repaint()
  383. {
  384.     m_player->repaint();
  385. }
  386.  
  387. void StreamMediaPlayerPrivateGStreamer::paint(GraphicsContext* context, const IntRect& rect)
  388. {
  389.     if (context->paintingDisabled())
  390.         return;
  391.  
  392.     if (!m_player->visible())
  393.         return;
  394.     if (!m_buffer)
  395.         return;
  396.  
  397.     RefPtr<ImageGStreamer> gstImage = ImageGStreamer::createImage(m_buffer);
  398.     if (!gstImage)
  399.         return;
  400.  
  401.     context->drawImage(reinterpret_cast<Image*>(gstImage->image().get()), ColorSpaceSRGB,
  402.                        rect, CompositeCopy, WebCore::DoNotRespectImageOrientation, false);
  403. }
  404.  
  405.  
  406. // Returns the size of the video
  407. IntSize StreamMediaPlayerPrivateGStreamer::naturalSize() const
  408. {
  409.     return m_currentSize;
  410. }
  411.  
  412. bool StreamMediaPlayerPrivateGStreamer::supportsFullscreen() const
  413. {
  414.     return false;
  415. }
  416.  
  417. PlatformMedia StreamMediaPlayerPrivateGStreamer::platformMedia() const
  418. {
  419.     PlatformMedia p;
  420.     p.type = PlatformMedia::GStreamerGWorldType;
  421.     p.media.gstreamerGWorld = m_gstGWorld.get();
  422.     return p;
  423. }
  424.  
  425.  
  426. void StreamMediaPlayerPrivateGStreamer::createGSTVideoSinkBin()
  427. {
  428.     LOG(MediaStream, "createGSTVideoSinkBin called");
  429.     m_gstGWorld = GStreamerGWorld::createGWorld(0);
  430.     m_webkitVideoSink = webkitVideoSinkNew(m_gstGWorld.get());
  431.  
  432.     gchar* name = gst_element_get_name(m_webkitVideoSink);
  433.     LOG(MediaStream, "m_webkitVideoSink=%p name=%s", m_webkitVideoSink, name);
  434.  
  435.     m_repaintCallbackHandlerId = g_signal_connect(m_webkitVideoSink, "repaint-requested", G_CALLBACK(mediaPlayerPrivateRepaintCallback), this);
  436.  
  437.     m_videoSinkBin = gst_bin_new(0);
  438.     GstElement* colorspace = gst_element_factory_make("ffmpegcolorspace", 0);
  439.     GstElement* videoTee = gst_element_factory_make("tee", "videoTee");
  440.     GstElement* queue = gst_element_factory_make("queue", 0);
  441.     GstElement* identity = gst_element_factory_make("identity", "videoValve");
  442.  
  443.     // Take ownership.
  444.     gst_object_ref_sink(m_videoSinkBin);
  445.  
  446.     // Build a new video sink consisting of a bin containing a tee
  447.     // (meant to distribute data to multiple video sinks) and our
  448.     // internal video sink. For fullscreen we create an autovideosink
  449.     // and initially block the data flow towards it and configure it
  450.  
  451.     gst_bin_add_many(GST_BIN(m_videoSinkBin), colorspace, videoTee, queue, identity, m_webkitVideoSink, NULL);
  452.  
  453.     gst_element_link(colorspace, videoTee);
  454.     // Link a new src pad from tee to queue1.
  455.     GstPad* srcPad = gst_element_get_request_pad(videoTee, "src%d");
  456.     GstPad* sinkPad = gst_element_get_static_pad(queue, "sink");
  457.     gst_pad_link(srcPad, sinkPad);
  458.     gst_object_unref(GST_OBJECT(srcPad));
  459.     gst_object_unref(GST_OBJECT(sinkPad));
  460.     gst_element_link_many(queue, identity, m_webkitVideoSink, NULL);
  461.  
  462.     g_object_set(m_webkitVideoSink, "async", FALSE, NULL);
  463.  
  464.     // Add a ghostpad to the bin so it can proxy to tee.
  465.     GstPad* pad = gst_element_get_static_pad(colorspace, "sink");
  466.     gst_element_add_pad(m_videoSinkBin, gst_ghost_pad_new("sink", pad));
  467.     gst_object_unref(GST_OBJECT(pad));
  468.  
  469. }
  470.  
  471. void StreamMediaPlayerPrivateGStreamer::createGSTAudioSinkBin()
  472. {
  473.  
  474.     m_audioSinkBin = gst_bin_new(0);
  475.     gst_object_ref_sink(m_audioSinkBin);
  476.  
  477.     m_volume = gst_element_factory_make("volume", "volume");
  478.  
  479.     g_object_set(m_volume, "mute", m_player->muted(), "volume", m_player->volume(), NULL);
  480.  
  481.     g_signal_connect(m_volume, "notify::volume", G_CALLBACK(streamMediaPlayerPrivateVolumeChangedCallback), this);
  482.     g_signal_connect(m_volume, "notify::mute", G_CALLBACK(streamMediaPlayerPrivateMuteChangedCallback), this);
  483.  
  484.  
  485.     GstElement *audioSink = gst_element_factory_make("autoaudiosink", 0);
  486.     gst_bin_add_many(GST_BIN(m_audioSinkBin), m_volume, audioSink, NULL);
  487.     gst_element_link_many(m_volume, audioSink, NULL);
  488.  
  489.     GstPad* pad = gst_element_get_static_pad(m_volume, "sink");
  490.     gst_element_add_pad(m_audioSinkBin, gst_ghost_pad_new("sink", pad));
  491.     gst_object_unref(GST_OBJECT(pad));
  492. }
  493.  
  494. bool StreamMediaPlayerPrivateGStreamer::connectToGSTLiveStream(MediaStreamDescriptor* streamDescriptor)
  495. {
  496.     LOG(MediaStream, "connectToGSTLiveStream called");
  497.     if (!streamDescriptor)
  498.         return false;
  499.  
  500.     // FIXME: Error handling.. this could fail.. and this method never returns false.
  501.  
  502.     CentralPipelineUnit &cpu = centralPipelineUnit();
  503.  
  504.     if (!m_audioSourceId.isEmpty()) {
  505.         cpu.disconnectFromSource(m_audioSourceId, m_audioSinkBin);
  506.         m_audioSourceId = "";
  507.     }
  508.  
  509.     if (!m_videoSourceId.isEmpty()) {
  510.         cpu.disconnectFromSource(m_videoSourceId, m_videoSinkBin);
  511.         m_videoSourceId = "";
  512.     }
  513.  
  514.     for (unsigned i = 0; i < streamDescriptor->numberOfAudioComponents(); i++) {
  515.         MediaStreamComponent* component = streamDescriptor->audioComponent(i);
  516.         if (!component->enabled())
  517.             continue;
  518.  
  519.         MediaStreamSource* source = component->source();
  520.         if (source->type() == MediaStreamSource::TypeAudio) {
  521.             if (cpu.connectToSource(source->id(), m_audioSinkBin)) {
  522.                 m_audioSourceId = source->id();
  523.                 // FIXME: Break since we don't support mixing of audio tracks yet.
  524.                 break;
  525.             }
  526.         }
  527.     }
  528.  
  529.     for (unsigned i = 0; i < streamDescriptor->numberOfVideoComponents(); i++) {
  530.         MediaStreamComponent* component = streamDescriptor->videoComponent(i);
  531.         if (!component->enabled())
  532.             continue;
  533.  
  534.         MediaStreamSource* source = component->source();
  535.         if (source->type() == MediaStreamSource::TypeVideo) {
  536.             if (cpu.connectToSource(source->id(), m_videoSinkBin)) {
  537.                 m_audioSourceId = source->id();
  538.                 // FIXME: Break since we don't support mixing of audio tracks yet.
  539.                 break;
  540.             }
  541.         }
  542.     }
  543.  
  544.     return true;
  545. }
  546.  
  547. IntSize StreamMediaPlayerPrivateGStreamer::calculateSize()
  548. {
  549.  
  550.     if (!hasVideo())
  551.         return IntSize();
  552.  
  553.     GstPad* pad = gst_element_get_static_pad(m_webkitVideoSink, "sink");
  554.     if (!pad)
  555.         return IntSize();
  556.  
  557.     guint64 width = 0, height = 0;
  558.     GstCaps* caps = GST_PAD_CAPS(pad);
  559.     int pixelAspectRatioNumerator, pixelAspectRatioDenominator;
  560.     int displayWidth, displayHeight, displayAspectRatioGCD;
  561.     int originalWidth = 0, originalHeight = 0;
  562.  
  563.     // TODO: handle possible clean aperture data. See
  564.     // https://bugzilla.gnome.org/show_bug.cgi?id=596571
  565.     // TODO: handle possible transformation matrix. See
  566.     // https://bugzilla.gnome.org/show_bug.cgi?id=596326
  567.  
  568.     // Get the video PAR and original size.
  569.     if (!GST_IS_CAPS(caps) || !gst_caps_is_fixed(caps)
  570.         || !gst_video_format_parse_caps(caps, 0, &originalWidth, &originalHeight)
  571.         || !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator,
  572.                                                     &pixelAspectRatioDenominator)) {
  573.         gst_object_unref(GST_OBJECT(pad));
  574.         return IntSize();
  575.     }
  576.  
  577.     gst_object_unref(GST_OBJECT(pad));
  578.  
  579.     //LOG_VERBOSE(Media, "Original video size: %dx%d", originalWidth, originalHeight);
  580.     //LOG_VERBOSE(Media, "Pixel aspect ratio: %d/%d", pixelAspectRatioNumerator, pixelAspectRatioDenominator);
  581.  
  582.     // Calculate DAR based on PAR and video size.
  583.     displayWidth = originalWidth * pixelAspectRatioNumerator;
  584.     displayHeight = originalHeight * pixelAspectRatioDenominator;
  585.  
  586.     // Divide display width and height by their GCD to avoid possible overflows.
  587.     displayAspectRatioGCD = greatestCommonDivisor(displayWidth, displayHeight);
  588.     displayWidth /= displayAspectRatioGCD;
  589.     displayHeight /= displayAspectRatioGCD;
  590.  
  591.     // Apply DAR to original video size. This is the same behavior as in xvimagesink's setcaps function.
  592.     if (!(originalHeight % displayHeight)) {
  593.         //LOG_VERBOSE(Media, "Keeping video original height");
  594.         width = gst_util_uint64_scale_int(originalHeight, displayWidth, displayHeight);
  595.         height = static_cast<guint64>(originalHeight);
  596.     } else if (!(originalWidth % displayWidth)) {
  597.         // LOG_VERBOSE(Media, "Keeping video original width");
  598.         height = gst_util_uint64_scale_int(originalWidth, displayHeight, displayWidth);
  599.         width = static_cast<guint64>(originalWidth);
  600.     } else {
  601.         // LOG_VERBOSE(Media, "Approximating while keeping original video height");
  602.         width = gst_util_uint64_scale_int(originalHeight, displayWidth, displayHeight);
  603.         height = static_cast<guint64>(originalHeight);
  604.     }
  605.  
  606.     // LOG_VERBOSE(Media, "Natural size: %" G_GUINT64_FORMAT "x%" G_GUINT64_FORMAT, width, height);
  607.     return IntSize(static_cast<int>(width), static_cast<int>(height));
  608. }
  609.  
  610. void StreamMediaPlayerPrivateGStreamer::updateCurrentSize(IntSize& size)
  611. {
  612.     m_currentSize.setWidth(size.width());
  613.     m_currentSize.setHeight(size.height());
  614.     m_player->sizeChanged();
  615. }
  616.  
  617. } // namespace WebCore
  618.  
  619. #endif // ENABLE(MEDIA_STREAM) && USE(GSTREAMER)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement