1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
/*
* Copyright (C) 2017-2022 Igalia S.L. All rights reserved.
* Copyright (C) 2022 Metrological Group B.V.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#if USE(GSTREAMER_WEBRTC)
#include "RealtimeIncomingVideoSourceGStreamer.h"
#include "GStreamerCommon.h"
#include "GStreamerWebRTCUtils.h"
#include "VideoFrameGStreamer.h"
#include <wtf/text/MakeString.h>
GST_DEBUG_CATEGORY(webkit_webrtc_incoming_video_debug);
#define GST_CAT_DEFAULT webkit_webrtc_incoming_video_debug
namespace WebCore {
RealtimeIncomingVideoSourceGStreamer::RealtimeIncomingVideoSourceGStreamer(AtomString&& videoTrackId)
: RealtimeIncomingSourceGStreamer(CaptureDevice { WTFMove(videoTrackId), CaptureDevice::DeviceType::Camera, emptyString() })
{
static std::once_flag debugRegisteredFlag;
std::call_once(debugRegisteredFlag, [] {
GST_DEBUG_CATEGORY_INIT(webkit_webrtc_incoming_video_debug, "webkitwebrtcincomingvideo", 0, "WebKit WebRTC incoming video");
});
}
const RealtimeMediaSourceSettings& RealtimeIncomingVideoSourceGStreamer::settings()
{
if (m_currentSettings)
return m_currentSettings.value();
RealtimeMediaSourceSettings settings;
RealtimeMediaSourceSupportedConstraints constraints;
auto& size = this->size();
if (!size.isZero()) {
constraints.setSupportsWidth(true);
constraints.setSupportsHeight(true);
settings.setWidth(size.width());
settings.setHeight(size.height());
}
if (double frameRate = this->frameRate()) {
constraints.setSupportsFrameRate(true);
settings.setFrameRate(frameRate);
}
settings.setSupportedConstraints(constraints);
m_currentSettings = WTFMove(settings);
return m_currentSettings.value();
}
void RealtimeIncomingVideoSourceGStreamer::settingsDidChange(OptionSet<RealtimeMediaSourceSettings::Flag> settings)
{
if (settings.containsAny({ RealtimeMediaSourceSettings::Flag::Width, RealtimeMediaSourceSettings::Flag::Height, RealtimeMediaSourceSettings::Flag::FrameRate }))
m_currentSettings = std::nullopt;
}
void RealtimeIncomingVideoSourceGStreamer::ensureSizeAndFramerate(const GRefPtr<GstCaps>& caps)
{
if (auto size = getVideoResolutionFromCaps(caps.get()))
setIntrinsicSize({ static_cast<int>(size->width()), static_cast<int>(size->height()) });
int frameRateNumerator, frameRateDenominator;
auto* structure = gst_caps_get_structure(caps.get(), 0);
if (!gst_structure_get_fraction(structure, "framerate", &frameRateNumerator, &frameRateDenominator))
return;
double framerate;
gst_util_fraction_to_double(frameRateNumerator, frameRateDenominator, &framerate);
setFrameRate(framerate);
}
void RealtimeIncomingVideoSourceGStreamer::dispatchSample(GRefPtr<GstSample>&& sample)
{
ASSERT(isMainThread());
auto* buffer = gst_sample_get_buffer(sample.get());
auto* caps = gst_sample_get_caps(sample.get());
if (!caps) {
GST_WARNING_OBJECT(bin(), "Received sample without caps, bailing out.");
return;
}
ensureSizeAndFramerate(GRefPtr<GstCaps>(caps));
videoFrameAvailable(VideoFrameGStreamer::create(WTFMove(sample), intrinsicSize(), fromGstClockTime(GST_BUFFER_PTS(buffer))), { });
}
const GstStructure* RealtimeIncomingVideoSourceGStreamer::stats()
{
m_stats.reset(gst_structure_new_empty("incoming-video-stats"));
forEachVideoFrameObserver([&](auto& observer) {
auto stats = observer.queryAdditionalStats();
if (!stats)
return;
gstStructureForeach(stats.get(), [&](auto id, auto value) -> bool {
gstStructureIdSetValue(m_stats.get(), id, value);
return TRUE;
});
});
return m_stats.get();
}
#undef GST_CAT_DEFAULT
} // namespace WebCore
#endif // USE(GSTREAMER_WEBRTC)
|