Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Side by Side Diff: third_party/WebKit/Source/modules/mediarecorder/MediaRecorder.cpp

Issue 1652373004: MediaRecorder: add and wire read {video,audio}BitsPerSecond props (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: philipj@ second round of comments Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "modules/mediarecorder/MediaRecorder.h" 5 #include "modules/mediarecorder/MediaRecorder.h"
6 6
7 #include "bindings/core/v8/Dictionary.h" 7 #include "bindings/core/v8/Dictionary.h"
8 #include "core/events/Event.h" 8 #include "core/events/Event.h"
9 #include "core/fileapi/Blob.h" 9 #include "core/fileapi/Blob.h"
10 #include "core/inspector/ConsoleMessage.h" 10 #include "core/inspector/ConsoleMessage.h"
11 #include "modules/EventTargetModules.h" 11 #include "modules/EventTargetModules.h"
12 #include "modules/mediarecorder/BlobEvent.h" 12 #include "modules/mediarecorder/BlobEvent.h"
13 #include "platform/ContentType.h" 13 #include "platform/ContentType.h"
14 #include "platform/NotImplemented.h" 14 #include "platform/NotImplemented.h"
15 #include "platform/blob/BlobData.h" 15 #include "platform/blob/BlobData.h"
16 #include "public/platform/Platform.h" 16 #include "public/platform/Platform.h"
17 #include "public/platform/WebMediaStream.h" 17 #include "public/platform/WebMediaStream.h"
18 #include <algorithm>
18 19
19 namespace blink { 20 namespace blink {
20 21
21 namespace { 22 namespace {
22 23
23 // Boundaries of Opus bitrate from https://www.opus-codec.org/. 24 // Boundaries of Opus bitrate from https://www.opus-codec.org/.
24 const int kSmallestPossibleOpusBitRate = 6000; 25 const int kSmallestPossibleOpusBitRate = 6000;
25 const int kLargestAutoAllocatedOpusBitRate = 128000; 26 const int kLargestAutoAllocatedOpusBitRate = 128000;
26 27
27 // Smallest Vpx bitrate that can be requested. 28 // Smallest Vpx bitrate that can be requested.
(...skipping 14 matching lines...) Expand all
42 return String(); 43 return String();
43 } 44 }
44 45
45 // Allocates the requested bit rates from |bitrateOptions| into the respective 46 // Allocates the requested bit rates from |bitrateOptions| into the respective
46 // |{audio,video}BitsPerSecond| (where a value of zero indicates Platform to use 47 // |{audio,video}BitsPerSecond| (where a value of zero indicates Platform to use
47 // whatever it sees fit). If |options.bitsPerSecond()| is specified, it 48 // whatever it sees fit). If |options.bitsPerSecond()| is specified, it
48 // overrides any specific bitrate, and the UA is free to allocate as desired: 49 // overrides any specific bitrate, and the UA is free to allocate as desired:
49 // here a 90%/10% video/audio is used. In all cases where a value is explicited 50 // here a 90%/10% video/audio is used. In all cases where a value is explicited
50 // or calculated, values are clamped in sane ranges. 51 // or calculated, values are clamped in sane ranges.
51 // This method throws NotSupportedError. 52 // This method throws NotSupportedError.
52 void AllocateVideoAndAudioBitrates(ExceptionState& exceptionState, ExecutionCont ext* context, const MediaRecorderOptions& options, MediaStream* stream, int32_t* audioBitsPerSecond, int32_t* videoBitsPerSecond) 53 void AllocateVideoAndAudioBitrates(ExceptionState& exceptionState, ExecutionCont ext* context, const MediaRecorderOptions& options, MediaStream* stream, int* aud ioBitsPerSecond, int* videoBitsPerSecond)
53 { 54 {
54 // Throw if any value would overflow an int32_t. 55 // Clamp incoming values into a signed integer's range.
55 // TODO(mcasas): This section would no be needed if the bit rates are signed , see https://github.com/w3c/mediacapture-record/issues/48. 56 // TODO(mcasas): This section would no be needed if the bit rates are signed or double, see https://github.com/w3c/mediacapture-record/issues/48.
56 const uint32_t kInt32MaxValueAsULong = std::numeric_limits<int32_t>::max(); 57 const unsigned kMaxIntAsUnsigned = std::numeric_limits<int>::max();
57 if (options.bitsPerSecond() >= kInt32MaxValueAsULong) {
58 exceptionState.throwDOMException(NotSupportedError, "Overall bit rate to o large " + String::number(options.bitsPerSecond()) + "bps)");
59 return;
60 }
61 if (options.bitsPerSecond() == 0) {
62 if (options.videoBitsPerSecond() >= kInt32MaxValueAsULong) {
63 exceptionState.throwDOMException(NotSupportedError, "Video bit rate too large " + String::number(options.videoBitsPerSecond()) + "bps)");
64 return;
65 }
66 if (options.audioBitsPerSecond() >= kInt32MaxValueAsULong) {
67 exceptionState.throwDOMException(NotSupportedError, "Audio bit rate too large " + String::number(options.audioBitsPerSecond()) + "bps)");
68 return;
69 }
70 }
71 58
72 int32_t videoBps = options.videoBitsPerSecond(); 59 ASSERT(options.bitsPerSecond() >= 0);
philipj_slow 2016/02/05 07:48:49 This ought to result in a tautological compare war
mcasas 2016/02/06 00:26:25 Done.
philipj_slow 2016/02/08 09:34:11 You didn't remove it :)
73 int32_t audioBps = options.audioBitsPerSecond(); 60 ASSERT(options.bitsPerSecond() < kMaxIntAsUnsigned);
74 bool useVideo = stream->getVideoTracks().size() > 0; 61 const int overallBps = std::min(options.bitsPerSecond(), kMaxIntAsUnsigned);
75 bool useAudio = stream->getAudioTracks().size() > 0; 62
63 ASSERT(overallBps != 0 || options.videoBitsPerSecond() >= 0);
philipj_slow 2016/02/05 07:48:49 If the trailing "||true" is dropped, note that thi
mcasas 2016/02/06 00:26:25 These are basically ASSERT(if a then b) implemente
64 ASSERT(overallBps != 0 || options.videoBitsPerSecond() < kMaxIntAsUnsigned);
65 int videoBps = std::min(options.videoBitsPerSecond(), kMaxIntAsUnsigned);
66
67 ASSERT(overallBps != 0 || options.audioBitsPerSecond() >= 0);
68 ASSERT(overallBps != 0 || options.audioBitsPerSecond() < kMaxIntAsUnsigned);
69 int audioBps = std::min(options.audioBitsPerSecond(), kMaxIntAsUnsigned);
70
71 const bool useVideo = stream->getVideoTracks().size() > 0;
72 const bool useAudio = stream->getAudioTracks().size() > 0;
76 73
77 if (useAudio) { 74 if (useAudio) {
78 // |options.bitsPerSecond()| overrides the specific audio and video bit rates. 75 // |overallBps| overrides the specific audio and video bit rates.
79 if (options.bitsPerSecond()) { 76 if (overallBps) {
80 if (useVideo) 77 if (useVideo)
81 audioBps = options.bitsPerSecond() / 10; 78 audioBps = overallBps / 10;
82 else 79 else
83 audioBps = options.bitsPerSecond(); 80 audioBps = overallBps;
84 } 81 }
85 // Limit audio bitrate values if set explicitly or calculated. 82 // Limit audio bitrate values if set explicitly or calculated.
86 if (audioBps) { 83 if (audioBps) {
87 if (audioBps > kLargestAutoAllocatedOpusBitRate) { 84 if (audioBps > kLargestAutoAllocatedOpusBitRate) {
88 context->addConsoleMessage(ConsoleMessage::create(JSMessageSourc e, WarningMessageLevel, "Clamping calculated audio bitrate (" + String::number(a udioBps) + "bps) to the maximum (" + String::number(kLargestAutoAllocatedOpusBit Rate) + "bps)")); 85 context->addConsoleMessage(ConsoleMessage::create(JSMessageSourc e, WarningMessageLevel, "Clamping calculated audio bitrate (" + String::number(a udioBps) + "bps) to the maximum (" + String::number(kLargestAutoAllocatedOpusBit Rate) + "bps)"));
89 audioBps = kLargestAutoAllocatedOpusBitRate; 86 audioBps = kLargestAutoAllocatedOpusBitRate;
90 } 87 }
91 88
92 if (audioBps < kSmallestPossibleOpusBitRate) { 89 if (audioBps < kSmallestPossibleOpusBitRate) {
93 context->addConsoleMessage(ConsoleMessage::create(JSMessageSourc e, WarningMessageLevel, "Clamping calculated audio bitrate (" + String::number(a udioBps) + "bps) to the minimum (" + String::number(kSmallestPossibleOpusBitRate ) + "bps)")); 90 context->addConsoleMessage(ConsoleMessage::create(JSMessageSourc e, WarningMessageLevel, "Clamping calculated audio bitrate (" + String::number(a udioBps) + "bps) to the minimum (" + String::number(kSmallestPossibleOpusBitRate ) + "bps)"));
94 audioBps = kSmallestPossibleOpusBitRate; 91 audioBps = kSmallestPossibleOpusBitRate;
95 } 92 }
96 } 93 }
97 } else { 94 } else {
98 audioBps = 0; 95 audioBps = 0;
99 } 96 }
100 if (useVideo) { 97 if (useVideo) {
101 // Allocate the remaining overall |options.bitsPerSecond()|, if any, to video. 98 // Allocate the remaining |overallBps|, if any, to video.
102 if (options.bitsPerSecond()) 99 if (overallBps)
103 videoBps = options.bitsPerSecond() - audioBps; 100 videoBps = overallBps - audioBps;
104 // Clamp the video bit rate if the user has set explicitly the video bit rate or has used the overall bitrate. 101 // Clamp the video bit rate if the user has set it explicitly or has use d the overall bitrate.
105 if ((options.videoBitsPerSecond() > 0 || options.bitsPerSecond() > 0) && (videoBps < kSmallestPossibleVpxBitRate)) { 102 if ((options.videoBitsPerSecond() > 0 || overallBps > 0) && (videoBps < kSmallestPossibleVpxBitRate)) {
106 context->addConsoleMessage(ConsoleMessage::create(JSMessageSource, W arningMessageLevel, "Clamping calculated video bitrate (" + String::number(video Bps) + "bps) to the minimum (" + String::number(kSmallestPossibleVpxBitRate) + " bps)")); 103 context->addConsoleMessage(ConsoleMessage::create(JSMessageSource, W arningMessageLevel, "Clamping calculated video bitrate (" + String::number(video Bps) + "bps) to the minimum (" + String::number(kSmallestPossibleVpxBitRate) + " bps)"));
107 videoBps = kSmallestPossibleVpxBitRate; 104 videoBps = kSmallestPossibleVpxBitRate;
108 } 105 }
109 } else { 106 } else {
110 videoBps = 0; 107 videoBps = 0;
111 } 108 }
112 109
113 *videoBitsPerSecond = videoBps; 110 *videoBitsPerSecond = videoBps;
114 *audioBitsPerSecond = audioBps; 111 *audioBitsPerSecond = audioBps;
115 return; 112 return;
(...skipping 17 matching lines...) Expand all
133 return recorder; 130 return recorder;
134 } 131 }
135 132
136 MediaRecorder::MediaRecorder(ExecutionContext* context, MediaStream* stream, con st MediaRecorderOptions& options, ExceptionState& exceptionState) 133 MediaRecorder::MediaRecorder(ExecutionContext* context, MediaStream* stream, con st MediaRecorderOptions& options, ExceptionState& exceptionState)
137 : ActiveDOMObject(context) 134 : ActiveDOMObject(context)
138 , m_stream(stream) 135 , m_stream(stream)
139 , m_streamAmountOfTracks(stream->getTracks().size()) 136 , m_streamAmountOfTracks(stream->getTracks().size())
140 , m_mimeType(options.mimeType()) 137 , m_mimeType(options.mimeType())
141 , m_stopped(true) 138 , m_stopped(true)
142 , m_ignoreMutedMedia(true) 139 , m_ignoreMutedMedia(true)
140 , m_audioBitsPerSecond(0)
141 , m_videoBitsPerSecond(0)
143 , m_state(State::Inactive) 142 , m_state(State::Inactive)
144 , m_dispatchScheduledEventRunner(AsyncMethodRunner<MediaRecorder>::create(th is, &MediaRecorder::dispatchScheduledEvent)) 143 , m_dispatchScheduledEventRunner(AsyncMethodRunner<MediaRecorder>::create(th is, &MediaRecorder::dispatchScheduledEvent))
145 { 144 {
146 ASSERT(m_stream->getTracks().size()); 145 ASSERT(m_stream->getTracks().size());
147 146
148 m_recorderHandler = adoptPtr(Platform::current()->createMediaRecorderHandler ()); 147 m_recorderHandler = adoptPtr(Platform::current()->createMediaRecorderHandler ());
149 ASSERT(m_recorderHandler); 148 ASSERT(m_recorderHandler);
150 149
151 if (!m_recorderHandler) { 150 if (!m_recorderHandler) {
152 exceptionState.throwDOMException(NotSupportedError, "No MediaRecorder ha ndler can be created."); 151 exceptionState.throwDOMException(NotSupportedError, "No MediaRecorder ha ndler can be created.");
153 return; 152 return;
154 } 153 }
155 154
156 int32_t audioBitsPerSecond = 0; 155 AllocateVideoAndAudioBitrates(exceptionState, context, options, stream, &m_a udioBitsPerSecond, &m_videoBitsPerSecond);
157 int32_t videoBitsPerSecond = 0;
158 AllocateVideoAndAudioBitrates(exceptionState, context, options, stream, &aud ioBitsPerSecond, &videoBitsPerSecond);
159 156
160 const ContentType contentType(m_mimeType); 157 const ContentType contentType(m_mimeType);
161 if (!m_recorderHandler->initialize(this, stream->descriptor(), contentType.t ype(), contentType.parameter("codecs"), audioBitsPerSecond, videoBitsPerSecond)) { 158 if (!m_recorderHandler->initialize(this, stream->descriptor(), contentType.t ype(), contentType.parameter("codecs"), m_audioBitsPerSecond, m_videoBitsPerSeco nd)) {
162 exceptionState.throwDOMException(NotSupportedError, "Failed to initializ e native MediaRecorder the type provided (" + m_mimeType + ") is not supported." ); 159 exceptionState.throwDOMException(NotSupportedError, "Failed to initializ e native MediaRecorder the type provided (" + m_mimeType + ") is not supported." );
163 return; 160 return;
164 } 161 }
165 m_stopped = false; 162 m_stopped = false;
166 } 163 }
167 164
168 String MediaRecorder::state() const 165 String MediaRecorder::state() const
169 { 166 {
170 return stateToString(m_state); 167 return stateToString(m_state);
171 } 168 }
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 DEFINE_TRACE(MediaRecorder) 350 DEFINE_TRACE(MediaRecorder)
354 { 351 {
355 visitor->trace(m_stream); 352 visitor->trace(m_stream);
356 visitor->trace(m_dispatchScheduledEventRunner); 353 visitor->trace(m_dispatchScheduledEventRunner);
357 visitor->trace(m_scheduledEvents); 354 visitor->trace(m_scheduledEvents);
358 RefCountedGarbageCollectedEventTargetWithInlineData<MediaRecorder>::trace(vi sitor); 355 RefCountedGarbageCollectedEventTargetWithInlineData<MediaRecorder>::trace(vi sitor);
359 ActiveDOMObject::trace(visitor); 356 ActiveDOMObject::trace(visitor);
360 } 357 }
361 358
362 } // namespace blink 359 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698