Chromium Code Reviews| 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..44dcbd6f651931b98b1ae356a0099655fa7f734e 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,64 @@ String stateToString(MediaRecorder::State state) |
| return String(); |
| } |
| +// Allocates the requested bit rates from |bitrateOptions| into the respective |
| +// |{audio,video}BitsPerSecond|, calculating and clamping if needed. |
|
Peter Beverloo
2016/01/20 18:35:35
nit: A comment here explaining *why* certain ratio
mcasas
2016/01/20 21:13:22
Commented.
|
| +bool AllocateVideoAndAudioBitrates(ExecutionContext* context, const MediaRecorderOptions& options, bool useAudio, bool useVideo, int32_t* audioBitsPerSecond, int32_t* videoBitsPerSecond) |
| +{ |
| + // Check that |options| don't overflow an int32_t. |
| + const unsigned long kInt32MaxValueAsULong = std::numeric_limits<int32_t>::max(); |
| + if (options.bitsPerSecond() >= kInt32MaxValueAsULong || (options.bitsPerSecond() == 0 && (options.videoBitsPerSecond() >= kInt32MaxValueAsULong || options.audioBitsPerSecond() >= kInt32MaxValueAsULong))) { |
| + const String message = "bitrates too large (audio: " + String::number(options.audioBitsPerSecond()) + "bps, video: " + String::number(options.videoBitsPerSecond()) + "bps, overall: " + String::number(options.bitsPerSecond()) + "bps)"; |
| + context->addConsoleMessage(ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, message)); |
| + return false; |
| + } |
| + |
|
Peter Beverloo
2016/01/20 18:35:35
[Comment applies to lines 49-55.]
I think this is
mcasas
2016/01/20 21:13:22
I'd love to but Gecko had it as ulong beforehand,
Peter Beverloo
2016/01/21 11:04:36
It is unfortunate that we can't rely on the standa
mcasas
2016/01/21 18:42:46
I filed https://github.com/w3c/mediacapture-record
|
| + *videoBitsPerSecond = options.videoBitsPerSecond(); |
| + *audioBitsPerSecond = options.audioBitsPerSecond(); |
|
Peter Beverloo
2016/01/20 18:35:35
nit: There's a lot of stars in the code. Might be
mcasas
2016/01/20 21:13:22
Done.
|
| + |
| + // |options.bitsPerSecond()| overrides the specific audio and video bit |
| + // rates, and we are free to allocate as desired. |
| + if (useAudio) { |
| + if (options.bitsPerSecond()) { |
| + if (useVideo) |
| + *audioBitsPerSecond = options.bitsPerSecond() / 10; |
| + else |
| + *audioBitsPerSecond = options.bitsPerSecond(); |
| + } |
| + // Limit audio bitrate values if they are too large or too small. |
| + if (*audioBitsPerSecond) { |
| + if (*audioBitsPerSecond > kLargestAutoAllocatedOpusBitRate) { |
| + const String message = "clamping calculated audio bitrate (" + String::number(*audioBitsPerSecond) + "bps) to the maximum (" + String::number(kLargestAutoAllocatedOpusBitRate) + "bps)"; |
|
Peter Beverloo
2016/01/20 18:35:35
nit: s/clamping/Clamping/. These are sentences.
mcasas
2016/01/20 21:13:22
Done.
|
| + context->addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message)); |
| + *audioBitsPerSecond = kLargestAutoAllocatedOpusBitRate; |
| + } |
| + |
| + if (*audioBitsPerSecond < kSmallestPossibleOpusBitRate) { |
| + const String message = "clamping calculated audio bitrate (" + String::number(*audioBitsPerSecond) + "bps) to the minimum (" + String::number(kSmallestPossibleOpusBitRate) + "bps)"; |
| + context->addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message)); |
| + *audioBitsPerSecond = kSmallestPossibleOpusBitRate; |
| + } |
| + } |
| + } else { |
| + *audioBitsPerSecond = 0; |
| + } |
| + // If there is video bit rate allocated it should be larger than a minimum. |
| + if (useVideo) { |
| + if (options.bitsPerSecond()) |
| + *videoBitsPerSecond = options.bitsPerSecond() - *audioBitsPerSecond; |
| + // Clamp the video bit rate if there is any configured (explicitly or |
|
Peter Beverloo
2016/01/20 18:35:35
nit: it's a bit odd to break this comment given th
mcasas
2016/01/20 21:13:22
Yup, sorry, came from Cr side 80-char limit. Done.
|
| + // implicitly via |options.bitsPerSecond()|). |
| + if ((*videoBitsPerSecond || options.bitsPerSecond()) && (*videoBitsPerSecond < kSmallestPossibleVpxBitRate)) { |
|
Peter Beverloo
2016/01/20 18:35:35
In which situation is the "(*videoBitsPerSecond ||
mcasas
2016/01/20 21:13:22
It's a peculiar case indeed, as miu@ detailed:
- t
|
| + const String message = "clamping calculated video bitrate (" + String::number(*videoBitsPerSecond) + "bps) to the minimum (" + String::number(kSmallestPossibleVpxBitRate) + "bps)"; |
| + context->addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message)); |
| + *videoBitsPerSecond = kSmallestPossibleVpxBitRate; |
| + } |
| + } else { |
| + *videoBitsPerSecond = 0; |
| + } |
| + return true; |
| +} |
| + |
| } // namespace |
| MediaRecorder* MediaRecorder::create(ExecutionContext* context, MediaStream* stream, ExceptionState& exceptionState) |
| @@ -67,14 +133,24 @@ 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 ContentType contentType(m_mimeType); |
| + const bool useVideo = stream->getVideoTracks().size() > 0; |
| + const bool useAudio = stream->getAudioTracks().size() > 0; |
| + int32_t audioBitsPerSecond = 0; |
| + int32_t videoBitsPerSecond = 0; |
| + // If bit rate calculation fails, throw an exception but allow continuing with defaults. |
|
Peter Beverloo
2016/01/20 18:35:35
This could do with a few more blank lines for read
mcasas
2016/01/20 21:13:22
cleaned up.
|
| + if (!AllocateVideoAndAudioBitrates(context, options, useAudio, useVideo, &audioBitsPerSecond, &videoBitsPerSecond)) { |
| + const String message = "target bitrates too large (audio: " + String::number(options.audioBitsPerSecond()) + "bps, video: " + String::number(options.videoBitsPerSecond()) + "bps, overall: " + String::number(options.bitsPerSecond()) + "bps)"; |
| + exceptionState.throwDOMException(NotSupportedError, message); |
| + } |
| + |
| + if (!m_recorderHandler->initialize(this, stream->descriptor(), contentType.type(), contentType.parameter("codecs"), audioBitsPerSecond, videoBitsPerSecond)) { |
| + exceptionState.throwDOMException(NotSupportedError, "Failed to initialize native MediaRecorder, the bitrates supplied, or the type provided (" + m_mimeType + ") are unsupported."); |
| return; |
| } |
| m_stopped = false; |