Index: third_party/WebKit/Source/modules/mediarecorder/MediaRecorder.cpp |
diff --git a/third_party/WebKit/Source/modules/mediarecorder/MediaRecorder.cpp b/third_party/WebKit/Source/modules/mediarecorder/MediaRecorder.cpp |
index d92ecf7d97ad00a489c532be4af2d30d2025720c..41c4ce8193992b625036dc17c99b1e29715330cf 100644 |
--- a/third_party/WebKit/Source/modules/mediarecorder/MediaRecorder.cpp |
+++ b/third_party/WebKit/Source/modules/mediarecorder/MediaRecorder.cpp |
@@ -7,6 +7,7 @@ |
#include "bindings/core/v8/Dictionary.h" |
#include "core/events/Event.h" |
#include "core/fileapi/Blob.h" |
+#include "core/inspector/ConsoleMessage.h" |
#include "modules/EventTargetModules.h" |
#include "modules/mediarecorder/BlobEvent.h" |
#include "platform/ContentType.h" |
@@ -19,6 +20,13 @@ namespace blink { |
namespace { |
+// Boundaries of Opus bitrate from https://www.opus-codec.org/. |
+const int kSmallestPossibleOpusBitRate = 6000; |
+const int kLargestAutoAllocatedOpusBitRate = 128000; |
+ |
+// Smallest Vpx bitrate that can be requested. |
+const int kSmallestPossibleVpxBitRate = 100000; |
+ |
String stateToString(MediaRecorder::State state) |
{ |
switch (state) { |
@@ -34,6 +42,75 @@ String stateToString(MediaRecorder::State state) |
return String(); |
} |
+// Allocates the requested bit rates from |bitrateOptions| into the respective |
+// |{audio,video}BitsPerSecond| (where a value of zero indicates Platform to use |
+// whatever it sees fit). If |options.bitsPerSecond()| is specified, it |
+// overrides any specific bitrate, and the UA is free to allocate as desired: |
+// here a 90%/10% video/audio is used. In all cases where a value is explicited |
+// or calculated, values are clamped in sane ranges. |
+// This method throws NotSupportedError. |
esprehn
2016/01/21 04:00:47
yay comments, thanks :)
mcasas
2016/01/21 18:42:46
Acknowledged.
|
+void AllocateVideoAndAudioBitrates(ExceptionState& exceptionState, ExecutionContext* context, const MediaRecorderOptions& options, bool useAudio, bool useVideo, int32_t* audioBitsPerSecond, int32_t* videoBitsPerSecond) |
esprehn
2016/01/21 04:00:47
take the stream for fewer bools. :)
mcasas
2016/01/21 18:42:46
Done.
|
+{ |
+ // Throw if any value would overflow an int32_t. |
+ const unsigned long kInt32MaxValueAsULong = std::numeric_limits<int32_t>::max(); |
miu
2016/01/21 00:51:05
Please use uint32_t instead of unsigned long.
mcasas
2016/01/21 18:42:46
Done.
|
+ if (options.bitsPerSecond() >= kInt32MaxValueAsULong) { |
+ exceptionState.throwDOMException(NotSupportedError, "Overall bit rate too large " + String::number(options.bitsPerSecond()) + "bps)"); |
+ return; |
+ } |
+ if (options.bitsPerSecond() == 0) { |
+ if (options.videoBitsPerSecond() >= kInt32MaxValueAsULong) { |
+ exceptionState.throwDOMException(NotSupportedError, "Video bit rate too large " + String::number(options.videoBitsPerSecond()) + "bps)"); |
+ return; |
+ } |
+ if (options.audioBitsPerSecond() >= kInt32MaxValueAsULong) { |
+ exceptionState.throwDOMException(NotSupportedError, "Audio bit rate too large " + String::number(options.audioBitsPerSecond()) + "bps)"); |
+ return; |
+ } |
+ } |
+ |
+ int32_t videoBps = options.videoBitsPerSecond(); |
+ int32_t audioBps = options.audioBitsPerSecond(); |
+ if (useAudio) { |
+ // |options.bitsPerSecond()| overrides the specific audio and video bit rates. |
+ if (options.bitsPerSecond()) { |
+ if (useVideo) |
+ audioBps = options.bitsPerSecond() / 10; |
+ else |
+ audioBps = options.bitsPerSecond(); |
+ } |
+ // Limit audio bitrate values if set explicitly or calculated. |
+ if (audioBps) { |
+ if (audioBps > kLargestAutoAllocatedOpusBitRate) { |
+ context->addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, "Clamping calculated audio bitrate (" + String::number(audioBps) + "bps) to the maximum (" + String::number(kLargestAutoAllocatedOpusBitRate) + "bps)")); |
+ audioBps = kLargestAutoAllocatedOpusBitRate; |
+ } |
+ |
+ if (audioBps < kSmallestPossibleOpusBitRate) { |
+ context->addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, "Clamping calculated audio bitrate (" + String::number(audioBps) + "bps) to the minimum (" + String::number(kSmallestPossibleOpusBitRate) + "bps)")); |
+ audioBps = kSmallestPossibleOpusBitRate; |
+ } |
+ } |
+ } else { |
+ audioBps = 0; |
+ } |
+ if (useVideo) { |
+ // Allocate the remaining overall |options.bitsPerSecond()|, if any, to video. |
+ if (options.bitsPerSecond()) |
+ videoBps = options.bitsPerSecond() - audioBps; |
+ // Clamp the video bit rate if the user has set explicitly the video bit rate or has used the overall bitrate. |
+ if ((options.videoBitsPerSecond() > 0 || options.bitsPerSecond() > 0) && (videoBps < kSmallestPossibleVpxBitRate)) { |
+ context->addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, "Clamping calculated video bitrate (" + String::number(videoBps) + "bps) to the minimum (" + String::number(kSmallestPossibleVpxBitRate) + "bps)")); |
+ videoBps = kSmallestPossibleVpxBitRate; |
+ } |
+ } else { |
+ videoBps = 0; |
+ } |
+ |
+ *videoBitsPerSecond = videoBps; |
+ *audioBitsPerSecond = audioBps; |
+ return; |
+} |
+ |
} // namespace |
MediaRecorder* MediaRecorder::create(ExecutionContext* context, MediaStream* stream, ExceptionState& exceptionState) |
@@ -67,14 +144,21 @@ MediaRecorder::MediaRecorder(ExecutionContext* context, MediaStream* stream, con |
m_recorderHandler = adoptPtr(Platform::current()->createMediaRecorderHandler()); |
ASSERT(m_recorderHandler); |
- // We deviate from the spec by not returning |UnsupportedOption|, see https://github.com/w3c/mediacapture-record/issues/18 |
if (!m_recorderHandler) { |
exceptionState.throwDOMException(NotSupportedError, "No MediaRecorder handler can be created."); |
return; |
} |
- ContentType contentType(m_mimeType); |
- if (!m_recorderHandler->initialize(this, stream->descriptor(), contentType.type(), contentType.parameter("codecs"))) { |
- exceptionState.throwDOMException(NotSupportedError, "Failed to initialize native MediaRecorder, the type provided " + m_mimeType + "is unsupported." ); |
+ |
+ const bool useVideo = stream->getVideoTracks().size() > 0; |
esprehn
2016/01/21 04:00:47
remove these, we also don't usually const local bo
mcasas
2016/01/21 18:42:46
Done.
|
+ const bool useAudio = stream->getAudioTracks().size() > 0; |
+ int32_t audioBitsPerSecond = 0; |
+ int32_t videoBitsPerSecond = 0; |
+ |
+ AllocateVideoAndAudioBitrates(exceptionState, context, options, useAudio, useVideo, &audioBitsPerSecond, &videoBitsPerSecond); |
esprehn
2016/01/21 04:00:47
pass the stream into this instead of the two bools
mcasas
2016/01/21 18:42:46
Done.
|
+ |
+ const ContentType contentType(m_mimeType); |
+ if (!m_recorderHandler->initialize(this, stream->descriptor(), contentType.type(), contentType.parameter("codecs"), audioBitsPerSecond, videoBitsPerSecond)) { |
+ exceptionState.throwDOMException(NotSupportedError, "Failed to initialize native MediaRecorder the type provided (" + m_mimeType + ") is not supported."); |
return; |
} |
m_stopped = false; |