1/*
2 * Copyright (C) 2013 Cable Television Laboratories, Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27
28#if ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK)
29
30#include "InbandTextTrackPrivateGStreamer.h"
31
32#include "GStreamerCommon.h"
33#include "Logging.h"
34#include <glib-object.h>
35#include <gst/gst.h>
36
37GST_DEBUG_CATEGORY_EXTERN(webkit_media_player_debug);
38#define GST_CAT_DEFAULT webkit_media_player_debug
39
40namespace WebCore {
41
42InbandTextTrackPrivateGStreamer::InbandTextTrackPrivateGStreamer(gint index, GRefPtr<GstPad> pad)
43 : InbandTextTrackPrivate(WebVTT)
44 , TrackPrivateBaseGStreamer(this, index, pad)
45{
46 m_eventProbe = gst_pad_add_probe(m_pad.get(), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, [] (GstPad*, GstPadProbeInfo* info, gpointer userData) -> GstPadProbeReturn {
47 auto* track = static_cast<InbandTextTrackPrivateGStreamer*>(userData);
48 switch (GST_EVENT_TYPE(gst_pad_probe_info_get_event(info))) {
49 case GST_EVENT_STREAM_START:
50 track->streamChanged();
51 break;
52 default:
53 break;
54 }
55 return GST_PAD_PROBE_OK;
56 }, this, nullptr);
57
58 notifyTrackOfStreamChanged();
59}
60
61#if GST_CHECK_VERSION(1, 10, 0)
62InbandTextTrackPrivateGStreamer::InbandTextTrackPrivateGStreamer(gint index, GRefPtr<GstStream> stream)
63 : InbandTextTrackPrivate(WebVTT)
64 , TrackPrivateBaseGStreamer(this, index, stream)
65{
66 m_streamId = gst_stream_get_stream_id(stream.get());
67 GST_INFO("Track %d got stream start for stream %s.", m_index, m_streamId.utf8().data());
68}
69#endif
70
71void InbandTextTrackPrivateGStreamer::disconnect()
72{
73 if (m_pad)
74 gst_pad_remove_probe(m_pad.get(), m_eventProbe);
75
76 TrackPrivateBaseGStreamer::disconnect();
77}
78
79void InbandTextTrackPrivateGStreamer::handleSample(GRefPtr<GstSample> sample)
80{
81 {
82 LockHolder lock(m_sampleMutex);
83 m_pendingSamples.append(sample);
84 }
85
86 RefPtr<InbandTextTrackPrivateGStreamer> protectedThis(this);
87 m_notifier->notify(MainThreadNotification::NewSample, [protectedThis] {
88 protectedThis->notifyTrackOfSample();
89 });
90}
91
92void InbandTextTrackPrivateGStreamer::streamChanged()
93{
94 RefPtr<InbandTextTrackPrivateGStreamer> protectedThis(this);
95 m_notifier->notify(MainThreadNotification::StreamChanged, [protectedThis] {
96 protectedThis->notifyTrackOfStreamChanged();
97 });
98}
99
100void InbandTextTrackPrivateGStreamer::notifyTrackOfSample()
101{
102 Vector<GRefPtr<GstSample> > samples;
103 {
104 LockHolder lock(m_sampleMutex);
105 m_pendingSamples.swap(samples);
106 }
107
108 for (size_t i = 0; i < samples.size(); ++i) {
109 GRefPtr<GstSample> sample = samples[i];
110 GstBuffer* buffer = gst_sample_get_buffer(sample.get());
111 if (!buffer) {
112 GST_WARNING("Track %d got sample with no buffer.", m_index);
113 continue;
114 }
115 auto mappedBuffer = GstMappedBuffer::create(buffer, GST_MAP_READ);
116 ASSERT(mappedBuffer);
117 if (!mappedBuffer) {
118 GST_WARNING("Track %d unable to map buffer.", m_index);
119 continue;
120 }
121
122 GST_INFO("Track %d parsing sample: %.*s", m_index, static_cast<int>(mappedBuffer->size()),
123 reinterpret_cast<char*>(mappedBuffer->data()));
124 client()->parseWebVTTCueData(reinterpret_cast<char*>(mappedBuffer->data()), mappedBuffer->size());
125 }
126}
127
128void InbandTextTrackPrivateGStreamer::notifyTrackOfStreamChanged()
129{
130 GRefPtr<GstEvent> event = adoptGRef(gst_pad_get_sticky_event(m_pad.get(),
131 GST_EVENT_STREAM_START, 0));
132 if (!event)
133 return;
134
135 const gchar* streamId;
136 gst_event_parse_stream_start(event.get(), &streamId);
137 GST_INFO("Track %d got stream start for stream %s.", m_index, streamId);
138 m_streamId = streamId;
139}
140
141} // namespace WebCore
142
143#endif // ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(VIDEO_TRACK)
144