Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "modules/EventTargetModules.h" | 11 #include "modules/EventTargetModules.h" |
| 11 #include "modules/mediarecorder/BlobEvent.h" | 12 #include "modules/mediarecorder/BlobEvent.h" |
| 12 #include "platform/ContentType.h" | 13 #include "platform/ContentType.h" |
| 13 #include "platform/NotImplemented.h" | 14 #include "platform/NotImplemented.h" |
| 14 #include "platform/blob/BlobData.h" | 15 #include "platform/blob/BlobData.h" |
| 15 #include "public/platform/Platform.h" | 16 #include "public/platform/Platform.h" |
| 16 #include "public/platform/WebMediaStream.h" | 17 #include "public/platform/WebMediaStream.h" |
| 17 | 18 |
| 18 namespace blink { | 19 namespace blink { |
| 19 | 20 |
| 20 namespace { | 21 namespace { |
| 21 | 22 |
| 23 // Boundaries of Opus bitrate from https://www.opus-codec.org/. | |
| 24 const int kSmallestPossibleOpusBitRate = 6000; | |
| 25 const int kLargestAutoAllocatedOpusBitRate = 128000; | |
| 26 | |
| 27 // Smallest Vpx bitrate that can be requested. | |
| 28 const int kSmallestPossibleVpxBitRate = 100000; | |
| 29 | |
| 22 String stateToString(MediaRecorder::State state) | 30 String stateToString(MediaRecorder::State state) |
| 23 { | 31 { |
| 24 switch (state) { | 32 switch (state) { |
| 25 case MediaRecorder::State::Inactive: | 33 case MediaRecorder::State::Inactive: |
| 26 return "inactive"; | 34 return "inactive"; |
| 27 case MediaRecorder::State::Recording: | 35 case MediaRecorder::State::Recording: |
| 28 return "recording"; | 36 return "recording"; |
| 29 case MediaRecorder::State::Paused: | 37 case MediaRecorder::State::Paused: |
| 30 return "paused"; | 38 return "paused"; |
| 31 } | 39 } |
| 32 | 40 |
| 33 ASSERT_NOT_REACHED(); | 41 ASSERT_NOT_REACHED(); |
| 34 return String(); | 42 return String(); |
| 35 } | 43 } |
| 36 | 44 |
| 45 // Allocates the requested bit rates from |bitrateOptions| into the respective | |
| 46 // |{audio,video}BitsPerSecond| (where a value of zero indicates Platform to use | |
| 47 // 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 // 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 // This method throws NotSupportedError. | |
|
esprehn
2016/01/21 04:00:47
yay comments, thanks :)
mcasas
2016/01/21 18:42:46
Acknowledged.
| |
| 52 void AllocateVideoAndAudioBitrates(ExceptionState& exceptionState, ExecutionCont ext* 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.
| |
| 53 { | |
| 54 // Throw if any value would overflow an int32_t. | |
| 55 const unsigned long kInt32MaxValueAsULong = std::numeric_limits<int32_t>::ma x(); | |
|
miu
2016/01/21 00:51:05
Please use uint32_t instead of unsigned long.
mcasas
2016/01/21 18:42:46
Done.
| |
| 56 if (options.bitsPerSecond() >= kInt32MaxValueAsULong) { | |
| 57 exceptionState.throwDOMException(NotSupportedError, "Overall bit rate to o large " + String::number(options.bitsPerSecond()) + "bps)"); | |
| 58 return; | |
| 59 } | |
| 60 if (options.bitsPerSecond() == 0) { | |
| 61 if (options.videoBitsPerSecond() >= kInt32MaxValueAsULong) { | |
| 62 exceptionState.throwDOMException(NotSupportedError, "Video bit rate too large " + String::number(options.videoBitsPerSecond()) + "bps)"); | |
| 63 return; | |
| 64 } | |
| 65 if (options.audioBitsPerSecond() >= kInt32MaxValueAsULong) { | |
| 66 exceptionState.throwDOMException(NotSupportedError, "Audio bit rate too large " + String::number(options.audioBitsPerSecond()) + "bps)"); | |
| 67 return; | |
| 68 } | |
| 69 } | |
| 70 | |
| 71 int32_t videoBps = options.videoBitsPerSecond(); | |
| 72 int32_t audioBps = options.audioBitsPerSecond(); | |
| 73 if (useAudio) { | |
| 74 // |options.bitsPerSecond()| overrides the specific audio and video bit rates. | |
| 75 if (options.bitsPerSecond()) { | |
| 76 if (useVideo) | |
| 77 audioBps = options.bitsPerSecond() / 10; | |
| 78 else | |
| 79 audioBps = options.bitsPerSecond(); | |
| 80 } | |
| 81 // Limit audio bitrate values if set explicitly or calculated. | |
| 82 if (audioBps) { | |
| 83 if (audioBps > kLargestAutoAllocatedOpusBitRate) { | |
| 84 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 audioBps = kLargestAutoAllocatedOpusBitRate; | |
| 86 } | |
| 87 | |
| 88 if (audioBps < kSmallestPossibleOpusBitRate) { | |
| 89 context->addConsoleMessage(ConsoleMessage::create(JSMessageSourc e, WarningMessageLevel, "Clamping calculated audio bitrate (" + String::number(a udioBps) + "bps) to the minimum (" + String::number(kSmallestPossibleOpusBitRate ) + "bps)")); | |
| 90 audioBps = kSmallestPossibleOpusBitRate; | |
| 91 } | |
| 92 } | |
| 93 } else { | |
| 94 audioBps = 0; | |
| 95 } | |
| 96 if (useVideo) { | |
| 97 // Allocate the remaining overall |options.bitsPerSecond()|, if any, to video. | |
| 98 if (options.bitsPerSecond()) | |
| 99 videoBps = options.bitsPerSecond() - audioBps; | |
| 100 // Clamp the video bit rate if the user has set explicitly the video bit rate or has used the overall bitrate. | |
| 101 if ((options.videoBitsPerSecond() > 0 || options.bitsPerSecond() > 0) && (videoBps < kSmallestPossibleVpxBitRate)) { | |
| 102 context->addConsoleMessage(ConsoleMessage::create(JSMessageSource, W arningMessageLevel, "Clamping calculated video bitrate (" + String::number(video Bps) + "bps) to the minimum (" + String::number(kSmallestPossibleVpxBitRate) + " bps)")); | |
| 103 videoBps = kSmallestPossibleVpxBitRate; | |
| 104 } | |
| 105 } else { | |
| 106 videoBps = 0; | |
| 107 } | |
| 108 | |
| 109 *videoBitsPerSecond = videoBps; | |
| 110 *audioBitsPerSecond = audioBps; | |
| 111 return; | |
| 112 } | |
| 113 | |
| 37 } // namespace | 114 } // namespace |
| 38 | 115 |
| 39 MediaRecorder* MediaRecorder::create(ExecutionContext* context, MediaStream* str eam, ExceptionState& exceptionState) | 116 MediaRecorder* MediaRecorder::create(ExecutionContext* context, MediaStream* str eam, ExceptionState& exceptionState) |
| 40 { | 117 { |
| 41 MediaRecorder* recorder = new MediaRecorder(context, stream, MediaRecorderOp tions(), exceptionState); | 118 MediaRecorder* recorder = new MediaRecorder(context, stream, MediaRecorderOp tions(), exceptionState); |
| 42 recorder->suspendIfNeeded(); | 119 recorder->suspendIfNeeded(); |
| 43 | 120 |
| 44 return recorder; | 121 return recorder; |
| 45 } | 122 } |
| 46 | 123 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 60 , m_stopped(true) | 137 , m_stopped(true) |
| 61 , m_ignoreMutedMedia(true) | 138 , m_ignoreMutedMedia(true) |
| 62 , m_state(State::Inactive) | 139 , m_state(State::Inactive) |
| 63 , m_dispatchScheduledEventRunner(AsyncMethodRunner<MediaRecorder>::create(th is, &MediaRecorder::dispatchScheduledEvent)) | 140 , m_dispatchScheduledEventRunner(AsyncMethodRunner<MediaRecorder>::create(th is, &MediaRecorder::dispatchScheduledEvent)) |
| 64 { | 141 { |
| 65 ASSERT(m_stream->getTracks().size()); | 142 ASSERT(m_stream->getTracks().size()); |
| 66 | 143 |
| 67 m_recorderHandler = adoptPtr(Platform::current()->createMediaRecorderHandler ()); | 144 m_recorderHandler = adoptPtr(Platform::current()->createMediaRecorderHandler ()); |
| 68 ASSERT(m_recorderHandler); | 145 ASSERT(m_recorderHandler); |
| 69 | 146 |
| 70 // We deviate from the spec by not returning |UnsupportedOption|, see https: //github.com/w3c/mediacapture-record/issues/18 | |
| 71 if (!m_recorderHandler) { | 147 if (!m_recorderHandler) { |
| 72 exceptionState.throwDOMException(NotSupportedError, "No MediaRecorder ha ndler can be created."); | 148 exceptionState.throwDOMException(NotSupportedError, "No MediaRecorder ha ndler can be created."); |
| 73 return; | 149 return; |
| 74 } | 150 } |
| 75 ContentType contentType(m_mimeType); | 151 |
| 76 if (!m_recorderHandler->initialize(this, stream->descriptor(), contentType.t ype(), contentType.parameter("codecs"))) { | 152 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.
| |
| 77 exceptionState.throwDOMException(NotSupportedError, "Failed to initializ e native MediaRecorder, the type provided " + m_mimeType + "is unsupported." ); | 153 const bool useAudio = stream->getAudioTracks().size() > 0; |
| 154 int32_t audioBitsPerSecond = 0; | |
| 155 int32_t videoBitsPerSecond = 0; | |
| 156 | |
| 157 AllocateVideoAndAudioBitrates(exceptionState, context, options, useAudio, us eVideo, &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.
| |
| 158 | |
| 159 const ContentType contentType(m_mimeType); | |
| 160 if (!m_recorderHandler->initialize(this, stream->descriptor(), contentType.t ype(), contentType.parameter("codecs"), audioBitsPerSecond, videoBitsPerSecond)) { | |
| 161 exceptionState.throwDOMException(NotSupportedError, "Failed to initializ e native MediaRecorder the type provided (" + m_mimeType + ") is not supported." ); | |
| 78 return; | 162 return; |
| 79 } | 163 } |
| 80 m_stopped = false; | 164 m_stopped = false; |
| 81 } | 165 } |
| 82 | 166 |
| 83 String MediaRecorder::state() const | 167 String MediaRecorder::state() const |
| 84 { | 168 { |
| 85 return stateToString(m_state); | 169 return stateToString(m_state); |
| 86 } | 170 } |
| 87 | 171 |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 DEFINE_TRACE(MediaRecorder) | 352 DEFINE_TRACE(MediaRecorder) |
| 269 { | 353 { |
| 270 visitor->trace(m_stream); | 354 visitor->trace(m_stream); |
| 271 visitor->trace(m_dispatchScheduledEventRunner); | 355 visitor->trace(m_dispatchScheduledEventRunner); |
| 272 visitor->trace(m_scheduledEvents); | 356 visitor->trace(m_scheduledEvents); |
| 273 RefCountedGarbageCollectedEventTargetWithInlineData<MediaRecorder>::trace(vi sitor); | 357 RefCountedGarbageCollectedEventTargetWithInlineData<MediaRecorder>::trace(vi sitor); |
| 274 ActiveDOMObject::trace(visitor); | 358 ActiveDOMObject::trace(visitor); |
| 275 } | 359 } |
| 276 | 360 |
| 277 } // namespace blink | 361 } // namespace blink |
| OLD | NEW |