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

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@opera.com 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 to a signed integer's maximum.
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 , see https://github.com/w3c/mediacapture-record/issues/48.
philipj_slow 2016/02/04 03:03:10 I like https://github.com/w3c/mediacapture-record/
mcasas 2016/02/05 02:39:14 I do! Will follow up with Gecko and hopefully deal
philipj_slow 2016/02/05 07:48:49 Sounds good.
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() < kMaxIntAsUnsigned);
philipj_slow 2016/02/04 03:03:10 Actually you can't assert this, a script can hit t
mcasas 2016/02/05 02:39:14 Done.
73 int32_t audioBps = options.audioBitsPerSecond(); 60 const int overallBps = std::min(options.bitsPerSecond(), kMaxIntAsUnsigned);
74 bool useVideo = stream->getVideoTracks().size() > 0; 61
75 bool useAudio = stream->getAudioTracks().size() > 0; 62 ASSERT(overallBps != 0 || options.videoBitsPerSecond() < kMaxIntAsUnsigned);
philipj_slow 2016/02/04 03:03:10 These asserts would have to go too.
mcasas 2016/02/05 02:39:14 Done, I think.
63 int videoBps = std::min(options.videoBitsPerSecond(), kMaxIntAsUnsigned);
64
65 ASSERT(overallBps != 0 || options.audioBitsPerSecond() < kMaxIntAsUnsigned);
66 int audioBps = std::min(options.audioBitsPerSecond(), kMaxIntAsUnsigned);
67
68 const bool useVideo = stream->getVideoTracks().size() > 0;
69 const bool useAudio = stream->getAudioTracks().size() > 0;
76 70
77 if (useAudio) { 71 if (useAudio) {
78 // |options.bitsPerSecond()| overrides the specific audio and video bit rates. 72 // |overallBps| overrides the specific audio and video bit rates.
79 if (options.bitsPerSecond()) { 73 if (overallBps) {
80 if (useVideo) 74 if (useVideo)
81 audioBps = options.bitsPerSecond() / 10; 75 audioBps = overallBps / 10;
82 else 76 else
83 audioBps = options.bitsPerSecond(); 77 audioBps = overallBps;
84 } 78 }
85 // Limit audio bitrate values if set explicitly or calculated. 79 // Limit audio bitrate values if set explicitly or calculated.
86 if (audioBps) { 80 if (audioBps) {
87 if (audioBps > kLargestAutoAllocatedOpusBitRate) { 81 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)")); 82 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; 83 audioBps = kLargestAutoAllocatedOpusBitRate;
90 } 84 }
91 85
92 if (audioBps < kSmallestPossibleOpusBitRate) { 86 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)")); 87 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; 88 audioBps = kSmallestPossibleOpusBitRate;
95 } 89 }
96 } 90 }
97 } else { 91 } else {
98 audioBps = 0; 92 audioBps = 0;
99 } 93 }
100 if (useVideo) { 94 if (useVideo) {
101 // Allocate the remaining overall |options.bitsPerSecond()|, if any, to video. 95 // Allocate the remaining overall |overallBps|, if any, to video.
philipj_slow 2016/02/04 03:03:10 Can drop "overall" now.
mcasas 2016/02/05 02:39:14 Done.
102 if (options.bitsPerSecond()) 96 if (overallBps)
103 videoBps = options.bitsPerSecond() - audioBps; 97 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. 98 // Clamp the video bit rate if the user has set explicitly the video bit rate or has used the overall bitrate.
105 if ((options.videoBitsPerSecond() > 0 || options.bitsPerSecond() > 0) && (videoBps < kSmallestPossibleVpxBitRate)) { 99 if ((options.videoBitsPerSecond() > 0 || overallBps > 0) && (videoBps < kSmallestPossibleVpxBitRate)) {
philipj_slow 2016/02/04 03:03:10 Look at videoBps here instead? It'd be nice to dea
mcasas 2016/02/05 02:39:14 In this case the idea is to check if the original
philipj_slow 2016/02/05 07:48:49 Oh, I see. If the IDL matched the spec and didn't
mcasas 2016/02/06 00:26:25 Using hasVideoBitsPerSecond().
philipj_slow 2016/02/08 09:39:44 This bit is still using options.videoBitsPerSecond
mcasas 2016/02/08 21:54:40 Darn, something was missing indeed. What I (think
106 context->addConsoleMessage(ConsoleMessage::create(JSMessageSource, W arningMessageLevel, "Clamping calculated video bitrate (" + String::number(video Bps) + "bps) to the minimum (" + String::number(kSmallestPossibleVpxBitRate) + " bps)")); 100 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; 101 videoBps = kSmallestPossibleVpxBitRate;
108 } 102 }
109 } else { 103 } else {
110 videoBps = 0; 104 videoBps = 0;
111 } 105 }
112 106
113 *videoBitsPerSecond = videoBps; 107 *videoBitsPerSecond = videoBps;
114 *audioBitsPerSecond = audioBps; 108 *audioBitsPerSecond = audioBps;
115 return; 109 return;
(...skipping 17 matching lines...) Expand all
133 return recorder; 127 return recorder;
134 } 128 }
135 129
136 MediaRecorder::MediaRecorder(ExecutionContext* context, MediaStream* stream, con st MediaRecorderOptions& options, ExceptionState& exceptionState) 130 MediaRecorder::MediaRecorder(ExecutionContext* context, MediaStream* stream, con st MediaRecorderOptions& options, ExceptionState& exceptionState)
137 : ActiveDOMObject(context) 131 : ActiveDOMObject(context)
138 , m_stream(stream) 132 , m_stream(stream)
139 , m_streamAmountOfTracks(stream->getTracks().size()) 133 , m_streamAmountOfTracks(stream->getTracks().size())
140 , m_mimeType(options.mimeType()) 134 , m_mimeType(options.mimeType())
141 , m_stopped(true) 135 , m_stopped(true)
142 , m_ignoreMutedMedia(true) 136 , m_ignoreMutedMedia(true)
137 , m_audioBitsPerSecond(0)
138 , m_videoBitsPerSecond(0)
143 , m_state(State::Inactive) 139 , m_state(State::Inactive)
144 , m_dispatchScheduledEventRunner(AsyncMethodRunner<MediaRecorder>::create(th is, &MediaRecorder::dispatchScheduledEvent)) 140 , m_dispatchScheduledEventRunner(AsyncMethodRunner<MediaRecorder>::create(th is, &MediaRecorder::dispatchScheduledEvent))
145 { 141 {
146 ASSERT(m_stream->getTracks().size()); 142 ASSERT(m_stream->getTracks().size());
147 143
148 m_recorderHandler = adoptPtr(Platform::current()->createMediaRecorderHandler ()); 144 m_recorderHandler = adoptPtr(Platform::current()->createMediaRecorderHandler ());
149 ASSERT(m_recorderHandler); 145 ASSERT(m_recorderHandler);
150 146
151 if (!m_recorderHandler) { 147 if (!m_recorderHandler) {
152 exceptionState.throwDOMException(NotSupportedError, "No MediaRecorder ha ndler can be created."); 148 exceptionState.throwDOMException(NotSupportedError, "No MediaRecorder ha ndler can be created.");
153 return; 149 return;
154 } 150 }
155 151
156 int32_t audioBitsPerSecond = 0; 152 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 153
160 const ContentType contentType(m_mimeType); 154 const ContentType contentType(m_mimeType);
161 if (!m_recorderHandler->initialize(this, stream->descriptor(), contentType.t ype(), contentType.parameter("codecs"), audioBitsPerSecond, videoBitsPerSecond)) { 155 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." ); 156 exceptionState.throwDOMException(NotSupportedError, "Failed to initializ e native MediaRecorder the type provided (" + m_mimeType + ") is not supported." );
163 return; 157 return;
164 } 158 }
165 m_stopped = false; 159 m_stopped = false;
166 } 160 }
167 161
168 String MediaRecorder::state() const 162 String MediaRecorder::state() const
169 { 163 {
170 return stateToString(m_state); 164 return stateToString(m_state);
171 } 165 }
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 DEFINE_TRACE(MediaRecorder) 347 DEFINE_TRACE(MediaRecorder)
354 { 348 {
355 visitor->trace(m_stream); 349 visitor->trace(m_stream);
356 visitor->trace(m_dispatchScheduledEventRunner); 350 visitor->trace(m_dispatchScheduledEventRunner);
357 visitor->trace(m_scheduledEvents); 351 visitor->trace(m_scheduledEvents);
358 RefCountedGarbageCollectedEventTargetWithInlineData<MediaRecorder>::trace(vi sitor); 352 RefCountedGarbageCollectedEventTargetWithInlineData<MediaRecorder>::trace(vi sitor);
359 ActiveDOMObject::trace(visitor); 353 ActiveDOMObject::trace(visitor);
360 } 354 }
361 355
362 } // namespace blink 356 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698