Unreviewed, add myself to some watch lists.
[WebKit-https.git] / Source / WebCore / platform / mediarecorder / MediaRecorderPrivateAVFImpl.cpp
1 /*
2  * Copyright (C) 2018 Apple Inc. All rights reserved.
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  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25
26 #include "config.h"
27 #include "MediaRecorderPrivateAVFImpl.h"
28
29 #if ENABLE(MEDIA_STREAM)
30
31 #include "AudioStreamDescription.h"
32 #include "MediaSample.h"
33 #include "MediaStreamPrivate.h"
34 #include "SharedBuffer.h"
35 #include "WebAudioBufferList.h"
36
37 namespace WebCore {
38
39 std::unique_ptr<MediaRecorderPrivateAVFImpl> MediaRecorderPrivateAVFImpl::create(const MediaStreamPrivate& stream)
40 {
41     auto instance = std::unique_ptr<MediaRecorderPrivateAVFImpl>(new MediaRecorderPrivateAVFImpl(stream));
42     if (!instance->m_isWriterReady)
43         return nullptr;
44     return instance;
45 }
46
47 MediaRecorderPrivateAVFImpl::MediaRecorderPrivateAVFImpl(const MediaStreamPrivate& stream)
48 {
49     if (!m_writer.setupWriter())
50         return;
51     auto tracks = stream.tracks();
52     bool videoSelected = false;
53     bool audioSelected = false;
54     for (auto& track : tracks) {
55         if (!track->enabled() || track->ended())
56             continue;
57         switch (track->type()) {
58         case RealtimeMediaSource::Type::Video: {
59             auto& settings = track->settings();
60             if (videoSelected || !settings.supportsWidth() || !settings.supportsHeight())
61                 break;
62             // FIXME: we will need to implement support for multiple video tracks, currently we only choose the first track as the recorded track.
63             // FIXME: we would better to throw an exception to JavaScript if setVideoInput failed
64             if (!m_writer.setVideoInput(settings.width(), settings.height()))
65                 return;
66             m_recordedVideoTrackID = track->id();
67             videoSelected = true;
68             break;
69         }
70         case RealtimeMediaSource::Type::Audio: {
71             if (audioSelected)
72                 break;
73             // FIXME: we will need to implement support for multiple audio tracks, currently we only choose the first track as the recorded track.
74             // FIXME: we would better to throw an exception to JavaScript if setAudioInput failed
75             if (!m_writer.setAudioInput())
76                 return;
77             m_recordedAudioTrackID = track->id();
78             audioSelected = true;
79             break;
80         }
81         case RealtimeMediaSource::Type::None:
82             break;
83         }
84     }
85     m_isWriterReady = true;
86 }
87
88 void MediaRecorderPrivateAVFImpl::sampleBufferUpdated(MediaStreamTrackPrivate& track, MediaSample& sampleBuffer)
89 {
90     if (track.id() != m_recordedVideoTrackID)
91         return;
92     m_writer.appendVideoSampleBuffer(sampleBuffer.platformSample().sample.cmSampleBuffer);
93 }
94
95 void MediaRecorderPrivateAVFImpl::audioSamplesAvailable(MediaStreamTrackPrivate& track, const WTF::MediaTime& mediaTime, const PlatformAudioData& data, const AudioStreamDescription& description, size_t sampleCount)
96 {
97     if (track.id() != m_recordedAudioTrackID)
98         return;
99     ASSERT(is<WebAudioBufferList>(data));
100     ASSERT(description.platformDescription().type == PlatformDescription::CAAudioStreamBasicType);
101     m_writer.appendAudioSampleBuffer(data, description, mediaTime, sampleCount);
102 }
103
104 void MediaRecorderPrivateAVFImpl::stopRecording()
105 {
106     m_writer.stopRecording();
107 }
108
109 RefPtr<SharedBuffer> MediaRecorderPrivateAVFImpl::fetchData()
110 {
111     return m_writer.fetchData();
112 }
113
114 const String& MediaRecorderPrivateAVFImpl::mimeType()
115 {
116     static NeverDestroyed<const String> mp4MimeType(MAKE_STATIC_STRING_IMPL("video/mp4"));
117     // FIXME: we will need to support more MIME types.
118     return mp4MimeType;
119 }
120
121 } // namespace WebCore
122
123 #endif // ENABLE(MEDIA_STREAM)