From 2e02aab9a70fc3cfea254ab7390f691096cc679e Mon Sep 17 00:00:00 2001 From: roytam1 Date: Thu, 6 Apr 2023 15:48:27 +0800 Subject: [PATCH] import changes from `dev' branch of rmottola/Arctic-Fox: - Bug 1198458: Webrtc updated to branch 43; pull made 2015-09-29 09:00AM PDT rs=jesup (c45a789c99) - Bug 1159489: WebRTC bitrate limits for video depend on input resolution and framerate r=pkerr (e3691a247c) - Bug 1132318: merge SelectSendFrameRate with SelectSendResolution r=bwc (bcc232994c) - Bug 1182289: Clean up dispatches in WebrtcGmpVideoEncoder/Decoder. r=jesup, a=abillings (b5e2030b07) - Bug 1167306: Fix preprocessor goof that disabled the load manager and some preference handling. r=jesup (0cc0dee688) - Bug 1198458: Rollup of changes previously applied to media/webrtc/trunk/webrtc and fixes to those rs=jesup r=froyd,jib,bwc,jesup,gcp,sotaro,pkerr,pehrsons (fe384d5e63) - Bug 1198458 Unbreak build on BSDs by fixing non-POSIX thread includes/usage. r=jesup (4ad8e88c17) - Bug 1198458: Fix typo in merges in OMX rs=bustage,kwierso on a CLOSED TREE (211b3b1a3f) - Bug 1226146: fix sndio audio_device backend after webrtc 43 landing in bug 1198458 r=jesup NPOTB (2b10ba3e86) - Bug 1231106 - Make BSDs fall-through to ASSERT as well. r=jesup (775d4fedae) - Bug 1231109 - Drop FreeBSD checks for unsupported versions. r=jld r=jesup (3cd55166fd) - Bug 1161079: Fix VideoCodecStats to allow for collecting encoder and decoder stats r=jib (1f98af8939) - add limits to fix gcc12 compile (d78098980f) - Bug 1193495 - Part 1: Test case. r=mt (add2ded009) - Bug 1193495 - Part 2: Maintain clones of supported codecs for each level, and do necessary checking to prevent payload-type clashes. r=mt (d45a24dba7) - Bug 1191301 - Re-enable the use of media.navigator.video.use_tmmbr pref. r=bwc (d2723821d4) - Bug 1094447 - Use UDP/TLS/RTP/SAVPF for audio/video m-lines. r=drno (e8e1dafd0a) - Bug 1173599 - a=imageattr support. r=mt (612fc343d7) - Bug 1173601 - Add a=simulcast support. r=mt (7c5303bacb) - Bug 1203246 - Factor track negotiation stuff out of JsepSessionImpl, and other simplification. r=mt (b71c809b78) - Bug 1212907 - a=rid support. r=mt (7479ab6984) - Bug 1212908 - Update a=simulcast to match new grammar in 03 draft. r=mt (e205d3b0dd) - Bug 1192390 - Part 1: Lay architectural groundwork for simulcast negotiation. r=mt r=jesup (e75dda3139) - Bug 1223160 - added SDP parser file reader. r=bwc (6752195791) - Bug 1192390 - Part 2: Simulcast and RID negotiation. r=mt (51b151ef52) - fix some warnings stuff (fed8f513a8) - Bug 1161317: Fix bug where sendonly video RTCP would be treated as outgoing RTP r=jesup (e24371fbe0) - Bug 1226347: Import cherry-pick of AEC changes from 43->48 (delay-agnostic AEC). r=pkerr (d3a074f4d8) - Bug 1226347 - Part 2: Allow control of AEC via prefs. r=rjesup (58f142005b) - Bug 1228788 - Force QT device release to happen on the main thread. r=jesup (885e9d1236) - Bug 1162218 - Make worker idle thread timeouts more strict, r=baku. (a7d2106987) - No bug. Remove a stray debugging printf of mine. r=me. (77b84cda62) - minor (22564a666e) - Bug 1224237 - Remove the !baseURL check from ServiceWorkerContainer::Register;r=bkelly (8b13c4dc49) - Bug 1196157 - Marks left by performance marks should print the domain of the application and not the complete URL. r=baku (d133708d8d) - Bug 1211970 - "Muted errors in workers are not correctly reported to the console". r=bz (42c15275f4) - Bug 1208559 - Tests. r=bholley (e16a30caa5) - Bug 1045891 - Tests for child-src r=ckerschb (90aa832cd0) - Bug 1223647: CSP erroneously inherited into dedicated workers. r=ckerschb (6fd8d9bfc9) - Bug 1218433 - Use AsyncOpen2 in dom/workers/ScriptLoader.cpp - part 1, r=sicking (a7e9187e52) - Bug 1218433 - Use AsyncOpen2 in dom/workers/ScriptLoader.cpp - part 3 - WPT, r=sicking, r=Ms2ger (e5e3c69f6a) - Bug 1218433 - Use AsyncOpen2 in dom/workers/ScriptLoader.cpp - part 2 - WPT, r=sicking, r=Ms2ger (1dd2d871ec) - Bug 1211967 - Fix how we report errors when loading a worker from a data url, r=bz (8517368daa) - nsRefPtr - RefPtr (34bb404530) - Bug 1231055 - Fix tags usage in PluginProvider. r=dtownsend (870b0e71eb) - bug 1228792 - remove use of array comprehensions r=mossop (3e31f18e83) - bug 1228792 - use standard version of catch r=mossop (f306557ca2) - Bug 1228009. Geolocation code needs to handle failures on its ErrorResults. r=smaug (8778a9e264) - Bug 1228707. Add a away to call Web IDL callbacks while ignoring any errors from them, and use it in a few places. r=smaug (a414e0d711) - Bug 1201692. Add a fast path to ExplicitChildIterator::Seek for the common case of seeking an actual DOM child of the parent node. r=wchen (01234ad43a) - Bug 1202186 - use nsISensitiveInfoHidden for console methods, r=baku (888b4506ad) - Bug 1223774 - Console API should check if the outer window exists, r=smaug (e0d7f408dc) - Bug 1200551 - Handle multiple %c formatters without a string between them by using only the last one for styling;r=baku,r=past (463550117a) - Bug 1213719 - Back out bug 1170314 for duplicate functionality. r=smaug (ae74e0ad52) - Bug 1154076 followup: Mark ConsoleRunnable::Run() as override. rs=ehsan (337181faab) - Bug 1127703 - "Support iteration on FormData" r=bz (4ddd461e99) - Bug 1230509 - BlobImplFile should return false in IsDateUnknown and IsSizeUnknown, r=bz (1079bfe2ab) - Bug 1198095 - FileReader should dispatch an error if the blob changes size in the meantime the read is executed, r=bz (263993a172) - Bug 1231094 - patch 1 - nsDOMFileReader to mozilla::dom::FileReader, r=sicking (aa8c3ff373) - Bug 1231094 - patch 2 - Get rid of FileIOObject, r=sicking (44af1e17dd) - Bug 1231100 - Get rid of nsIDOMFileReader - patch 1, r=sicking (c909d9d793) - Bug 1231100 - Get rid of nsIDOMFileReader - patch 2, r=sicking (4d3da1c566) - Bug 1161183: Don't show the add-on version in the list view. r=dao (002d8f6fb1) - Bug 1229519: Fix toolkit/modules to pass eslint checks. r=mak (8bbd9c8fe0) --- b2g/components/LogCapture.jsm | 5 +- build/clang-plugin/clang-plugin.cpp | 1 + build/gyp.mozbuild | 12 +- dom/apps/ImportExport.jsm | 5 +- dom/base/BlobSet.h | 3 +- dom/base/ChildIterator.cpp | 24 + dom/base/ChildIterator.h | 12 +- dom/base/Console.cpp | 58 +- dom/base/Console.h | 4 - dom/base/File.cpp | 33 +- dom/base/File.h | 7 +- dom/base/FileIOObject.cpp | 246 - dom/base/FileIOObject.h | 103 - .../{nsDOMFileReader.cpp => FileReader.cpp} | 509 +- dom/base/{nsDOMFileReader.h => FileReader.h} | 145 +- dom/base/MultipartBlobImpl.cpp | 67 +- dom/base/MultipartBlobImpl.h | 47 +- dom/base/ShadowRoot.cpp | 2 +- dom/base/StructuredCloneHolder.cpp | 85 +- dom/base/WindowOrientationObserver.cpp | 2 + dom/base/moz.build | 5 +- dom/base/nsContentUtils.cpp | 16 - dom/base/nsContentUtils.h | 5 - dom/base/nsDOMClassInfo.cpp | 3 +- dom/base/nsDOMMutationObserver.cpp | 3 +- dom/base/nsFormData.cpp | 107 +- dom/base/nsFormData.h | 44 +- dom/base/nsIDOMFileReader.idl | 47 - dom/base/nsXMLHttpRequest.cpp | 23 +- dom/base/nsXMLHttpRequest.h | 2 +- dom/base/test/file_bug1198095.js | 26 + dom/base/test/mochitest.ini | 2 + dom/base/test/test_bug1198095.html | 77 + .../test/test_ipc_messagemanager_blob.html | 4 +- dom/bindings/Bindings.conf | 1 - dom/bindings/Codegen.py | 58 +- dom/bindings/ErrorResult.h | 10 + dom/fetch/FetchUtil.cpp | 14 +- dom/geolocation/nsGeolocation.cpp | 6 +- dom/html/test/file_iframe_sandbox_g_if1.html | 9 +- dom/html/test/formData_test.js | 51 + .../test/test_message_manager_ipc.html | 13 +- .../test/unit/test_blob_file_backed.js | 13 +- .../test/unit/xpcshell-head-parent-process.js | 12 +- dom/ipc/Blob.cpp | 12 +- .../test_blob_sliced_from_parent_process.html | 9 +- dom/media/moz.build | 5 + dom/media/omx/OMXCodecWrapper.cpp | 23 +- dom/media/omx/OMXCodecWrapper.h | 3 +- dom/media/systemservices/CamerasChild.cpp | 2 +- dom/media/systemservices/CamerasChild.h | 6 +- dom/media/systemservices/CamerasParent.cpp | 25 +- dom/media/systemservices/CamerasParent.h | 5 +- dom/media/systemservices/LoadManager.cpp | 8 - dom/media/systemservices/MediaUtils.h | 1 + dom/media/systemservices/PCameras.ipdl | 2 +- dom/media/systemservices/moz.build | 5 + .../webrtc/MediaEngineRemoteVideoSource.cpp | 4 +- .../webrtc/MediaEngineRemoteVideoSource.h | 8 +- dom/media/webrtc/MediaEngineWebRTC.cpp | 2 +- dom/media/webrtc/moz.build | 4 + dom/mobilemessage/gonk/MmsService.js | 5 +- .../test/csp/file_child-src_iframe.html | 61 + .../test/csp/file_child-src_inner_frame.html | 21 + .../csp/file_child-src_service_worker.html | 29 + .../test/csp/file_child-src_service_worker.js | 3 + ...file_child-src_shared_worker-redirect.html | 47 + .../csp/file_child-src_shared_worker.html | 34 + .../test/csp/file_child-src_shared_worker.js | 8 + .../file_child-src_shared_worker_data.html | 37 + .../csp/file_child-src_worker-redirect.html | 50 + .../test/csp/file_child-src_worker.html | 32 + .../test/csp/file_child-src_worker.js | 4 + .../test/csp/file_child-src_worker_data.html | 33 + dom/security/test/csp/file_main.html^headers^ | 2 +- dom/security/test/csp/file_main.js | 38 +- dom/security/test/csp/file_main_worker.js | 28 + .../test/csp/file_redirect_worker.sjs | 34 + .../test/csp/file_redirects_main.html | 23 +- dom/security/test/csp/file_redirects_page.sjs | 34 +- .../test/csp/file_redirects_resource.sjs | 43 +- .../test/csp/file_service_worker.html | 19 + dom/security/test/csp/file_service_worker.js | 1 + .../test/csp/file_worker_redirect.html | 9 - .../test/csp/file_worker_redirect.sjs | 37 - dom/security/test/csp/mochitest.ini | 26 +- dom/security/test/csp/test_CSP.html | 19 +- .../test/csp/test_child-src_iframe.html | 114 + .../csp/test_child-src_worker-redirect.html | 125 + .../test/csp/test_child-src_worker.html | 131 + .../test/csp/test_child-src_worker_data.html | 126 + dom/security/test/csp/test_redirects.html | 14 +- .../test/csp/test_service_worker.html | 62 + .../test/csp/test_worker_redirect.html | 76 - .../general/frameStoragePrevented.html | 24 +- dom/webidl/FileReader.webidl | 3 +- dom/webidl/FormData.webidl | 6 +- dom/workers/Performance.cpp | 9 +- dom/workers/RuntimeService.cpp | 81 +- dom/workers/ScriptLoader.cpp | 275 +- dom/workers/ServiceWorkerContainer.cpp | 6 - dom/workers/ServiceWorkerManagerChild.cpp | 6 +- dom/workers/ServiceWorkerManagerChild.h | 8 +- dom/workers/ServiceWorkerManagerParent.cpp | 8 +- dom/workers/ServiceWorkerManagerService.cpp | 6 +- dom/workers/ServiceWorkerManagerService.h | 8 +- dom/workers/ServiceWorkerRegistrar.h | 2 +- dom/workers/ServiceWorkerRegistration.h | 2 +- dom/workers/ServiceWorkerWindowClient.cpp | 2 +- dom/workers/WorkerPrivate.cpp | 24 +- dom/workers/WorkerScope.cpp | 2 +- dom/workers/XMLHttpRequest.h | 4 +- dom/workers/test/csp_worker.js | 30 +- dom/workers/test/serviceworkers/mochitest.ini | 3 +- .../serviceworkers/test_eval_allowed.html | 9 +- ...aders^ => test_eval_allowed.html^headers^} | 0 .../serviceworkers/test_eval_not_allowed.html | 46 - dom/workers/test/test_csp.html^headers^ | 2 +- dom/workers/test/test_csp.js | 86 +- dom/workers/test/test_loadError.html | 76 +- .../src/base/platform_thread_posix.cc | 11 +- ipc/glue/moz.build | 2 + js/xpconnect/src/Sandbox.cpp | 6 + js/xpconnect/src/xpcprivate.h | 1 + .../tests/mochitest/test_bug790732.html | 1 - js/xpconnect/tests/unit/test_fileReader.js | 13 + js/xpconnect/tests/unit/xpcshell.ini | 1 + layout/base/nsRefreshDriver.cpp | 4 +- layout/build/nsLayoutModule.cpp | 7 - layout/media/symbols.def.in | 1 + media/mtransport/nr_socket_prsock.cpp | 8 +- .../third_party/nICEr/src/util/mbslen.c | 9 +- media/webrtc/moz.build | 14 +- media/webrtc/signaling/signaling.gyp | 5 +- .../src/common/EncodingConstraints.h | 46 + .../signaling/src/common/NullTransport.h | 4 +- .../signaling/src/jsep/JsepCodecDescription.h | 308 +- media/webrtc/signaling/src/jsep/JsepSession.h | 2 +- .../signaling/src/jsep/JsepSessionImpl.cpp | 482 +- .../signaling/src/jsep/JsepSessionImpl.h | 34 +- media/webrtc/signaling/src/jsep/JsepTrack.cpp | 469 + media/webrtc/signaling/src/jsep/JsepTrack.h | 133 +- .../signaling/src/jsep/JsepTrackEncoding.h | 50 + .../webrtc/signaling/src/jsep/JsepTrackImpl.h | 92 - .../src/media-conduit/AudioConduit.cpp | 64 +- .../src/media-conduit/AudioConduit.h | 12 +- .../signaling/src/media-conduit/CodecConfig.h | 26 +- .../src/media-conduit/CodecStatistics.cpp | 27 +- .../src/media-conduit/CodecStatistics.h | 6 +- .../src/media-conduit/GmpVideoCodec.cpp | 4 +- .../src/media-conduit/MediaConduitInterface.h | 13 +- .../src/media-conduit/VideoConduit.cpp | 801 +- .../src/media-conduit/VideoConduit.h | 81 +- .../src/media-conduit/WebrtcGmpVideoCodec.cpp | 544 +- .../src/media-conduit/WebrtcGmpVideoCodec.h | 482 +- .../WebrtcMediaCodecVP8VideoCodec.cpp | 2 +- .../WebrtcMediaCodecVP8VideoCodec.h | 2 +- .../media-conduit/WebrtcOMXH264VideoCodec.cpp | 23 +- .../media-conduit/WebrtcOMXH264VideoCodec.h | 2 +- .../src/mediapipeline/MediaPipeline.cpp | 65 +- .../src/mediapipeline/MediaPipeline.h | 32 +- .../peerconnection/MediaPipelineFactory.cpp | 208 +- .../src/peerconnection/PeerConnectionImpl.cpp | 134 +- .../src/peerconnection/PeerConnectionImpl.h | 12 + .../webrtc/signaling/src/sdp/SdpAttribute.cpp | 1045 +- media/webrtc/signaling/src/sdp/SdpAttribute.h | 261 +- .../signaling/src/sdp/SdpAttributeList.h | 4 +- media/webrtc/signaling/src/sdp/SdpEnum.h | 17 + media/webrtc/signaling/src/sdp/SdpHelper.cpp | 27 +- media/webrtc/signaling/src/sdp/SdpHelper.h | 7 +- .../signaling/src/sdp/SdpMediaSection.cpp | 176 + .../signaling/src/sdp/SdpMediaSection.h | 101 +- .../src/sdp/SipccSdpAttributeList.cpp | 138 +- .../signaling/src/sdp/SipccSdpAttributeList.h | 9 +- .../src/sdp/SipccSdpMediaSection.cpp | 85 +- .../signaling/src/sdp/SipccSdpMediaSection.h | 10 +- media/webrtc/signaling/src/sdp/sipcc/ccsdp.h | 3 + .../signaling/src/sdp/sipcc/sdp_attr_access.c | 5 +- .../webrtc/signaling/src/sdp/sipcc/sdp_main.c | 6 + .../signaling/test/jsep_session_unittest.cpp | 264 +- .../signaling/test/jsep_track_unittest.cpp | 475 + .../signaling/test/mediaconduit_unittests.cpp | 39 +- .../signaling/test/mediapipeline_unittest.cpp | 6 +- media/webrtc/signaling/test/moz.build | 2 + .../webrtc/signaling/test/sdp_file_parser.cpp | 81 + media/webrtc/signaling/test/sdp_unittests.cpp | 1677 + .../signaling/test/signaling_unittests.cpp | 98 +- media/webrtc/trunk/AUTHORS | 42 + media/webrtc/trunk/DEPS | 358 +- media/webrtc/trunk/OWNERS | 26 +- .../trunk/build/android/cpufeatures.gypi | 6 + media/webrtc/trunk/peerconnection.gyp | 2 +- media/webrtc/trunk/webrtc/BUILD.gn | 65 +- media/webrtc/trunk/webrtc/LICENSE_THIRD_PARTY | 20 +- media/webrtc/trunk/webrtc/base/BUILD.gn | 75 +- media/webrtc/trunk/webrtc/base/OWNERS | 1 - media/webrtc/trunk/webrtc/base/arraysize.h | 40 + .../trunk/webrtc/base/asynchttprequest.cc | 2 +- .../trunk/webrtc/base/asynchttprequest.h | 10 +- .../trunk/webrtc/base/asyncinvoker-inl.h | 5 +- .../webrtc/trunk/webrtc/base/asyncinvoker.cc | 11 +- media/webrtc/trunk/webrtc/base/asyncinvoker.h | 19 +- .../trunk/webrtc/base/asyncpacketsocket.cc | 29 + .../trunk/webrtc/base/asyncpacketsocket.h | 10 +- .../webrtc/base/asyncresolverinterface.cc | 20 + .../webrtc/base/asyncresolverinterface.h | 4 +- media/webrtc/trunk/webrtc/base/asyncsocket.cc | 97 +- media/webrtc/trunk/webrtc/base/asyncsocket.h | 90 +- .../webrtc/trunk/webrtc/base/asynctcpsocket.h | 39 +- .../webrtc/trunk/webrtc/base/asyncudpsocket.h | 29 +- .../trunk/webrtc/base/autodetectproxy.cc | 8 +- .../trunk/webrtc/base/autodetectproxy.h | 13 +- .../trunk/webrtc/base/bandwidthsmoother.cc | 8 +- .../trunk/webrtc/base/bandwidthsmoother.h | 1 + media/webrtc/trunk/webrtc/base/base.gyp | 57 +- media/webrtc/trunk/webrtc/base/base_tests.gyp | 3 +- media/webrtc/trunk/webrtc/base/basictypes.h | 9 - media/webrtc/trunk/webrtc/base/buffer.cc | 37 + media/webrtc/trunk/webrtc/base/buffer.h | 65 +- .../trunk/webrtc/base/buffer_unittest.cc | 42 +- media/webrtc/trunk/webrtc/base/bytebuffer.cc | 4 +- media/webrtc/trunk/webrtc/base/callback.h | 1 - media/webrtc/trunk/webrtc/base/checks.h | 43 +- media/webrtc/trunk/webrtc/base/common.h | 29 +- .../webrtc/trunk/webrtc/base/compile_assert.h | 82 - media/webrtc/trunk/webrtc/base/cpumonitor.h | 4 +- .../trunk/webrtc/base/criticalsection.cc | 33 + .../trunk/webrtc/base/criticalsection.h | 93 +- .../webrtc/base/criticalsection_unittest.cc | 205 +- media/webrtc/trunk/webrtc/base/cryptstring.cc | 75 + media/webrtc/trunk/webrtc/base/cryptstring.h | 48 +- media/webrtc/trunk/webrtc/base/dbus.cc | 4 + media/webrtc/trunk/webrtc/base/diskcache.cc | 5 +- .../trunk/webrtc/base/diskcache_win32.cc | 3 +- media/webrtc/trunk/webrtc/base/event.cc | 32 +- media/webrtc/trunk/webrtc/base/event.h | 14 +- .../webrtc/trunk/webrtc/base/event_tracer.cc | 60 + media/webrtc/trunk/webrtc/base/event_tracer.h | 71 + .../webrtc/base/event_tracer_unittest.cc | 82 + .../trunk/webrtc/base/filelock_unittest.cc | 6 +- media/webrtc/trunk/webrtc/base/fileutils.cc | 8 + media/webrtc/trunk/webrtc/base/fileutils.h | 8 +- .../trunk/webrtc/base/firewallsocketserver.cc | 26 +- .../trunk/webrtc/base/firewallsocketserver.h | 22 +- .../webrtc/trunk/webrtc/base/format_macros.h | 94 + media/webrtc/trunk/webrtc/base/helpers.cc | 24 +- media/webrtc/trunk/webrtc/base/httpbase.cc | 27 +- media/webrtc/trunk/webrtc/base/httpbase.h | 28 +- .../trunk/webrtc/base/httpbase_unittest.cc | 5 +- media/webrtc/trunk/webrtc/base/httpclient.cc | 8 +- media/webrtc/trunk/webrtc/base/httpclient.h | 10 +- media/webrtc/trunk/webrtc/base/httpcommon.cc | 22 +- media/webrtc/trunk/webrtc/base/httpcommon.h | 12 +- media/webrtc/trunk/webrtc/base/httprequest.cc | 2 + media/webrtc/trunk/webrtc/base/httprequest.h | 1 + media/webrtc/trunk/webrtc/base/httpserver.h | 12 +- media/webrtc/trunk/webrtc/base/ipaddress.cc | 21 +- media/webrtc/trunk/webrtc/base/ipaddress.h | 2 + .../trunk/webrtc/base/ipaddress_unittest.cc | 35 + media/webrtc/trunk/webrtc/base/json.cc | 4 + media/webrtc/trunk/webrtc/base/json.h | 4 +- .../webrtc/trunk/webrtc/base/json_unittest.cc | 10 +- media/webrtc/trunk/webrtc/base/logging.cc | 13 +- .../webrtc/trunk/webrtc/base/macasyncsocket.h | 39 +- .../trunk/webrtc/base/maccocoasocketserver.h | 6 +- .../trunk/webrtc/base/macsocketserver.cc | 8 + .../trunk/webrtc/base/macsocketserver.h | 22 +- .../trunk/webrtc/base/macwindowpicker.h | 17 +- media/webrtc/trunk/webrtc/base/md5.h | 3 - media/webrtc/trunk/webrtc/base/md5digest.cc | 32 + media/webrtc/trunk/webrtc/base/md5digest.h | 20 +- .../webrtc/trunk/webrtc/base/messagedigest.cc | 1 + .../webrtc/trunk/webrtc/base/messagequeue.cc | 24 +- media/webrtc/trunk/webrtc/base/messagequeue.h | 18 +- media/webrtc/trunk/webrtc/base/move.h | 40 +- media/webrtc/trunk/webrtc/base/multipart.cc | 4 +- media/webrtc/trunk/webrtc/base/multipart.h | 26 +- media/webrtc/trunk/webrtc/base/natserver.h | 2 +- .../trunk/webrtc/base/natsocketfactory.cc | 60 +- .../trunk/webrtc/base/natsocketfactory.h | 42 +- media/webrtc/trunk/webrtc/base/nattypes.cc | 24 +- media/webrtc/trunk/webrtc/base/nethelpers.cc | 10 + media/webrtc/trunk/webrtc/base/nethelpers.h | 14 +- media/webrtc/trunk/webrtc/base/network.cc | 220 +- media/webrtc/trunk/webrtc/base/network.h | 83 +- .../trunk/webrtc/base/network_unittest.cc | 118 +- media/webrtc/trunk/webrtc/base/nssidentity.cc | 11 + media/webrtc/trunk/webrtc/base/nssidentity.h | 34 +- .../trunk/webrtc/base/nssstreamadapter.cc | 48 +- .../trunk/webrtc/base/nssstreamadapter.h | 50 +- .../webrtc/base/nullsocketserver_unittest.cc | 2 +- .../trunk/webrtc/base/openssladapter.cc | 67 +- .../webrtc/trunk/webrtc/base/openssladapter.h | 35 +- .../webrtc/trunk/webrtc/base/openssldigest.h | 8 +- .../trunk/webrtc/base/opensslidentity.cc | 75 +- .../trunk/webrtc/base/opensslidentity.h | 52 +- .../trunk/webrtc/base/opensslstreamadapter.cc | 133 +- .../trunk/webrtc/base/opensslstreamadapter.h | 66 +- media/webrtc/trunk/webrtc/base/optionsfile.cc | 2 + media/webrtc/trunk/webrtc/base/optionsfile.h | 1 + .../trunk/webrtc/base/physicalsocketserver.cc | 133 +- .../trunk/webrtc/base/physicalsocketserver.h | 14 +- media/webrtc/trunk/webrtc/base/profiler.cc | 10 +- media/webrtc/trunk/webrtc/base/profiler.h | 3 +- media/webrtc/trunk/webrtc/base/proxyinfo.cc | 4 + media/webrtc/trunk/webrtc/base/proxyinfo.h | 3 +- media/webrtc/trunk/webrtc/base/proxyserver.cc | 10 +- media/webrtc/trunk/webrtc/base/proxyserver.h | 7 +- media/webrtc/trunk/webrtc/base/ratetracker.cc | 13 +- .../trunk/webrtc/base/ratetracker_unittest.cc | 7 + media/webrtc/trunk/webrtc/base/refcount.h | 53 +- .../trunk/webrtc/base/rollingaccumulator.h | 5 +- .../trunk/webrtc/base/safe_conversions.h | 17 +- .../trunk/webrtc/base/safe_conversions_impl.h | 10 +- .../trunk/webrtc/base/schanneladapter.cc | 17 +- .../trunk/webrtc/base/schanneladapter.h | 4 +- media/webrtc/trunk/webrtc/base/scoped_ptr.h | 223 +- media/webrtc/trunk/webrtc/base/sha1digest.cc | 32 + media/webrtc/trunk/webrtc/base/sha1digest.h | 17 +- .../trunk/webrtc/base/sharedexclusivelock.cc | 2 +- .../webrtc/trunk/webrtc/base/signalthread.cc | 8 + media/webrtc/trunk/webrtc/base/signalthread.h | 8 +- media/webrtc/trunk/webrtc/base/sigslot.cc | 54 + media/webrtc/trunk/webrtc/base/sigslot.h | 80 +- .../trunk/webrtc/base/socketadapters.cc | 15 +- .../webrtc/trunk/webrtc/base/socketadapters.h | 67 +- media/webrtc/trunk/webrtc/base/socketpool.h | 36 +- media/webrtc/trunk/webrtc/base/socketserver.h | 2 + media/webrtc/trunk/webrtc/base/socketstream.h | 18 +- media/webrtc/trunk/webrtc/base/ssladapter.h | 4 + .../trunk/webrtc/base/ssladapter_unittest.cc | 133 +- .../trunk/webrtc/base/sslfingerprint.cc | 3 +- media/webrtc/trunk/webrtc/base/sslidentity.cc | 14 + media/webrtc/trunk/webrtc/base/sslidentity.h | 15 +- .../trunk/webrtc/base/sslsocketfactory.cc | 40 +- .../trunk/webrtc/base/sslsocketfactory.h | 15 +- .../trunk/webrtc/base/sslstreamadapter.cc | 31 + .../trunk/webrtc/base/sslstreamadapter.h | 22 +- .../webrtc/base/sslstreamadapter_unittest.cc | 21 + .../webrtc/base/sslstreamadapterhelper.cc | 10 + .../webrtc/base/sslstreamadapterhelper.h | 31 +- media/webrtc/trunk/webrtc/base/stream.cc | 137 +- media/webrtc/trunk/webrtc/base/stream.h | 319 +- media/webrtc/trunk/webrtc/base/systeminfo.cc | 5 + media/webrtc/trunk/webrtc/base/systeminfo.h | 3 +- media/webrtc/trunk/webrtc/base/task.cc | 9 + media/webrtc/trunk/webrtc/base/task.h | 9 +- media/webrtc/trunk/webrtc/base/taskparent.cc | 3 + media/webrtc/trunk/webrtc/base/taskparent.h | 2 +- media/webrtc/trunk/webrtc/base/taskrunner.h | 2 +- .../webrtc/trunk/webrtc/base/template_util.h | 8 +- media/webrtc/trunk/webrtc/base/testclient.cc | 14 +- media/webrtc/trunk/webrtc/base/testclient.h | 12 +- media/webrtc/trunk/webrtc/base/testutils.h | 3 +- media/webrtc/trunk/webrtc/base/thread.cc | 10 + media/webrtc/trunk/webrtc/base/thread.h | 19 +- .../trunk/webrtc/base/thread_checker_impl.cc | 74 +- .../trunk/webrtc/base/thread_checker_impl.h | 25 +- .../webrtc/base/thread_checker_unittest.cc | 8 +- media/webrtc/trunk/webrtc/base/trace_event.h | 916 + .../trunk/webrtc/base/transformadapter.cc | 12 + .../trunk/webrtc/base/transformadapter.h | 24 +- .../webrtc/trunk/webrtc/base/unixfilesystem.h | 54 +- .../webrtc/base/virtualsocket_unittest.cc | 33 +- .../trunk/webrtc/base/virtualsocketserver.cc | 768 +- .../trunk/webrtc/base/virtualsocketserver.h | 120 +- media/webrtc/trunk/webrtc/base/win32.cc | 6 +- media/webrtc/trunk/webrtc/base/win32.h | 9 +- .../trunk/webrtc/base/win32_unittest.cc | 33 + .../trunk/webrtc/base/win32filesystem.cc | 23 +- .../trunk/webrtc/base/win32filesystem.h | 2 +- .../trunk/webrtc/base/win32regkey_unittest.cc | 11 +- .../trunk/webrtc/base/win32socketserver.cc | 10 +- media/webrtc/trunk/webrtc/base/winping.cc | 4 +- media/webrtc/trunk/webrtc/base/worker.h | 4 +- .../trunk/webrtc/base/x11windowpicker.cc | 2 +- .../trunk/webrtc/base/x11windowpicker.h | 17 +- media/webrtc/trunk/webrtc/build/OWNERS | 1 - .../trunk/webrtc/build/android/test_runner.py | 83 + media/webrtc/trunk/webrtc/build/apk_tests.gyp | 28 +- .../trunk/webrtc/build/apk_tests_noop.gyp | 4 + media/webrtc/trunk/webrtc/build/arm_neon.gypi | 32 +- media/webrtc/trunk/webrtc/build/common.gypi | 126 +- .../trunk/webrtc/build/find_directx_sdk.py | 43 + media/webrtc/trunk/webrtc/build/ios-webrtc.sh | 25 - .../trunk/webrtc/build/sanitizers/OWNERS | 2 + .../trunk/webrtc/build/sanitizers/README | 3 + .../sanitizers/lsan_suppressions_webrtc.cc | 129 + .../tsan_suppressions_webrtc.cc | 20 +- media/webrtc/trunk/webrtc/build/version.py | 61 - media/webrtc/trunk/webrtc/build/vie-webrtc.sh | 69 - media/webrtc/trunk/webrtc/build/webrtc.gni | 30 +- .../webrtc/trunk/webrtc/build/whitespace.txt | 5 + media/webrtc/trunk/webrtc/call.h | 35 +- media/webrtc/trunk/webrtc/codereview.settings | 9 + media/webrtc/trunk/webrtc/common.gyp | 11 + .../webrtc/trunk/webrtc/common_audio/BUILD.gn | 70 +- .../webrtc/common_audio/audio_converter.cc | 247 +- .../webrtc/common_audio/audio_converter.h | 43 +- .../common_audio/audio_converter_unittest.cc | 34 +- .../webrtc/common_audio/audio_ring_buffer.cc | 64 + .../webrtc/common_audio/audio_ring_buffer.h | 52 + .../audio_ring_buffer_unittest.cc | 108 + .../trunk/webrtc/common_audio/blocker.cc | 98 +- .../trunk/webrtc/common_audio/blocker.h | 18 +- .../webrtc/common_audio/blocker_unittest.cc | 149 +- .../webrtc/common_audio/channel_buffer.cc | 73 + .../webrtc/common_audio/channel_buffer.h | 170 + .../webrtc/common_audio/common_audio.gyp | 54 +- .../common_audio_unittests.isolate | 8 - .../utility => common_audio}/fft4g.c | 0 .../webrtc/trunk/webrtc/common_audio/fft4g.h | 26 + .../trunk/webrtc/common_audio/fir_filter.cc | 10 +- .../webrtc/common_audio/fir_filter_neon.h | 8 +- .../webrtc/common_audio/fir_filter_sse.h | 8 +- .../common_audio/fir_filter_unittest.cc | 32 +- .../webrtc/common_audio/include/audio_util.h | 2 +- .../webrtc/common_audio/lapped_transform.cc | 48 +- .../webrtc/common_audio/lapped_transform.h | 37 +- .../common_audio/lapped_transform_unittest.cc | 35 +- .../trunk/webrtc/common_audio/real_fourier.cc | 64 +- .../trunk/webrtc/common_audio/real_fourier.h | 42 +- .../webrtc/common_audio/real_fourier_ooura.cc | 85 + .../webrtc/common_audio/real_fourier_ooura.h | 45 + .../common_audio/real_fourier_openmax.cc | 69 + .../common_audio/real_fourier_openmax.h | 44 + .../common_audio/real_fourier_unittest.cc | 87 +- .../resampler/include/push_resampler.h | 14 +- .../resampler/include/resampler.h | 28 +- .../resampler/push_sinc_resampler.cc | 32 +- .../resampler/push_sinc_resampler.h | 25 +- .../resampler/push_sinc_resampler_unittest.cc | 151 +- .../common_audio/resampler/resampler.cc | 70 +- .../resampler/resampler_unittest.cc | 19 +- .../common_audio/resampler/sinc_resampler.cc | 3 +- .../common_audio/resampler/sinc_resampler.h | 12 +- .../resampler/sinc_resampler_unittest.cc | 13 +- .../sinusoidal_linear_chirp_source.h | 2 +- .../utility => common_audio}/ring_buffer.c | 11 +- .../utility => common_audio}/ring_buffer.h | 18 +- .../ring_buffer_unittest.cc | 19 +- .../signal_processing/complex_fft_mips.c | 10 +- .../cross_correlation_neon.S | 159 - .../cross_correlation_neon.c | 92 + .../signal_processing/downsample_fast_neon.S | 215 - .../signal_processing/downsample_fast_neon.c | 217 + .../common_audio/signal_processing/energy.c | 4 +- .../signal_processing/filter_ma_fast_q12.c | 4 +- .../ilbc_specific_functions.c | 6 +- .../signal_processing/include/real_fft.h | 47 +- .../include/signal_processing_library.h | 81 +- .../signal_processing/include/spl_inl_armv7.h | 9 +- .../signal_processing/levinson_durbin.c | 2 +- .../min_max_operations_neon.S | 283 - .../min_max_operations_neon.c | 294 + .../common_audio/signal_processing/real_fft.c | 44 +- .../signal_processing/refl_coef_to_lpc.c | 3 +- .../signal_processing_unittest.cc | 29 +- .../common_audio/signal_processing/spl_init.c | 24 +- .../signal_processing/splitting_filter.c | 2 +- .../vector_scaling_operations.c | 13 +- .../vector_scaling_operations_neon.S | 82 - .../webrtc/common_audio/vad/include/vad.h | 6 +- .../webrtc/common_audio/vad/mock/mock_vad.h | 2 +- .../trunk/webrtc/common_audio/vad/vad_core.c | 26 +- .../webrtc/common_audio/vad/vad_filterbank.c | 15 +- .../trunk/webrtc/common_audio/vad/vad_gmm.c | 12 +- .../trunk/webrtc/common_audio/vad/vad_sp.c | 14 +- .../trunk/webrtc/common_audio/wav_file.cc | 32 +- .../trunk/webrtc/common_audio/wav_file.h | 1 + .../webrtc/common_audio/wav_file_unittest.cc | 48 +- .../trunk/webrtc/common_audio/wav_header.cc | 32 +- .../trunk/webrtc/common_audio/wav_header.h | 14 +- .../common_audio/wav_header_unittest.cc | 342 +- media/webrtc/trunk/webrtc/common_types.cc | 50 + media/webrtc/trunk/webrtc/common_types.h | 201 +- .../webrtc/trunk/webrtc/common_video/BUILD.gn | 18 +- .../webrtc/common_video/common_video.gyp | 14 +- .../common_video/common_video_unittests.gyp | 5 +- .../common_video_unittests.isolate | 6 +- .../webrtc/common_video/i420_buffer_pool.cc | 87 + .../common_video/i420_buffer_pool_unittest.cc | 74 + .../webrtc/common_video/i420_video_frame.cc | 274 +- .../common_video/i420_video_frame_unittest.cc | 387 +- .../common_video/interface/i420_buffer_pool.h | 43 + .../common_video/interface/native_handle.h | 2 +- .../interface/texture_video_frame.h | 73 - .../interface/video_frame_buffer.h | 147 + .../common_video/libyuv/include/scaler.h | 5 +- .../libyuv/include/webrtc_libyuv.h | 39 +- .../common_video/libyuv/libyuv_unittest.cc | 148 +- .../webrtc/common_video/libyuv/scaler.cc | 37 +- .../common_video/libyuv/scaler_unittest.cc | 143 +- .../common_video/libyuv/webrtc_libyuv.cc | 81 +- .../webrtc/trunk/webrtc/common_video/plane.cc | 4 +- .../webrtc/trunk/webrtc/common_video/plane.h | 4 +- .../webrtc/common_video/plane_unittest.cc | 97 - .../trunk/webrtc/common_video/rotation.h | 26 + .../common_video/texture_video_frame.cc | 105 - .../texture_video_frame_unittest.cc | 79 - .../webrtc/common_video/video_frame_buffer.cc | 218 + media/webrtc/trunk/webrtc/config.cc | 18 + media/webrtc/trunk/webrtc/config.h | 49 +- .../trunk/webrtc/engine_configurations.h | 1 - media/webrtc/trunk/webrtc/frame_callback.h | 6 +- .../webrtc/modules/audio_coding/BUILD.gn | 169 +- .../trunk/webrtc/modules/audio_coding/OWNERS | 12 + .../audio_codec_speed_tests.isolate | 10 +- .../modules/audio_coding/audio_coding.gypi | 35 + .../audio_coding/audio_coding_tests.gypi | 72 + .../webrtc/modules/audio_coding/codecs/OWNERS | 5 + .../audio_coding/codecs/audio_decoder.cc | 102 + .../interface => codecs}/audio_decoder.h | 89 +- .../audio_coding/codecs/audio_encoder.cc | 39 + .../audio_coding/codecs/audio_encoder.h | 107 +- .../codecs/cng/audio_encoder_cng.cc | 232 + .../codecs/cng/audio_encoder_cng_unittest.cc | 458 + .../modules/audio_coding/codecs/cng/cng.gypi | 3 + .../codecs/cng/include/audio_encoder_cng.h | 87 + .../codecs/cng/include/webrtc_cng.h | 3 +- .../audio_coding/codecs/cng/webrtc_cng.c | 42 +- .../codecs/g711/audio_encoder_pcm.cc | 70 +- .../audio_coding/codecs/g711/g711.gypi | 3 + .../audio_coding/codecs/g711/g711_interface.c | 128 +- .../codecs/g711/include/audio_encoder_pcm.h | 69 +- .../codecs/g711/include/g711_interface.h | 20 +- .../audio_coding/codecs/g711/test/testG711.cc | 2 +- .../codecs/g722/audio_encoder_g722.cc | 137 + .../audio_coding/codecs/g722/g722.gypi | 5 + .../audio_coding/codecs/g722/g722_decode.c | 17 +- .../audio_coding/codecs/g722/g722_enc_dec.h | 24 +- .../audio_coding/codecs/g722/g722_encode.c | 14 +- .../audio_coding/codecs/g722/g722_interface.c | 24 +- .../codecs/g722/include/audio_encoder_g722.h | 68 + .../codecs/g722/include/g722_interface.h | 11 +- .../audio_coding/codecs/g722/test/testG722.cc | 5 +- .../audio_coding/codecs/ilbc/abs_quant.c | 2 +- .../audio_coding/codecs/ilbc/abs_quant.h | 2 +- .../codecs/ilbc/audio_encoder_ilbc.cc | 115 + .../audio_coding/codecs/ilbc/bw_expand.c | 2 +- .../audio_coding/codecs/ilbc/cb_construct.c | 6 +- .../audio_coding/codecs/ilbc/cb_mem_energy.c | 4 +- .../codecs/ilbc/cb_mem_energy_augmentation.c | 5 +- .../codecs/ilbc/cb_mem_energy_calc.c | 5 +- .../audio_coding/codecs/ilbc/cb_search.c | 11 +- .../audio_coding/codecs/ilbc/cb_search.h | 2 +- .../audio_coding/codecs/ilbc/cb_search_core.c | 4 +- .../codecs/ilbc/cb_update_best_index.c | 4 +- .../audio_coding/codecs/ilbc/chebyshev.c | 16 +- .../modules/audio_coding/codecs/ilbc/decode.c | 2 +- .../modules/audio_coding/codecs/ilbc/decode.h | 2 +- .../codecs/ilbc/decode_residual.c | 2 +- .../codecs/ilbc/decode_residual.h | 2 +- .../codecs/ilbc/decoder_interpolate_lsf.c | 2 +- .../codecs/ilbc/decoder_interpolate_lsf.h | 2 +- .../audio_coding/codecs/ilbc/defines.h | 8 +- .../modules/audio_coding/codecs/ilbc/do_plc.c | 46 +- .../modules/audio_coding/codecs/ilbc/do_plc.h | 2 +- .../modules/audio_coding/codecs/ilbc/encode.c | 4 +- .../modules/audio_coding/codecs/ilbc/encode.h | 2 +- .../audio_coding/codecs/ilbc/enh_upsample.c | 40 +- .../codecs/ilbc/enhancer_interface.c | 44 +- .../codecs/ilbc/enhancer_interface.h | 2 +- .../audio_coding/codecs/ilbc/frame_classify.c | 4 +- .../audio_coding/codecs/ilbc/frame_classify.h | 2 +- .../audio_coding/codecs/ilbc/gain_dequant.c | 2 +- .../audio_coding/codecs/ilbc/gain_quant.c | 19 +- .../audio_coding/codecs/ilbc/get_cd_vec.c | 2 +- .../audio_coding/codecs/ilbc/get_lsp_poly.c | 5 +- .../audio_coding/codecs/ilbc/get_sync_seq.c | 32 +- .../audio_coding/codecs/ilbc/hp_input.c | 18 +- .../audio_coding/codecs/ilbc/hp_output.c | 18 +- .../modules/audio_coding/codecs/ilbc/ilbc.c | 171 +- .../audio_coding/codecs/ilbc/ilbc.gypi | 3 + .../audio_coding/codecs/ilbc/init_decode.c | 2 +- .../audio_coding/codecs/ilbc/init_decode.h | 2 +- .../audio_coding/codecs/ilbc/init_encode.c | 2 +- .../audio_coding/codecs/ilbc/init_encode.h | 2 +- .../ilbc/interface/audio_encoder_ilbc.h | 59 + .../audio_coding/codecs/ilbc/interface/ilbc.h | 65 +- .../codecs/ilbc/interpolate_samples.c | 4 +- .../audio_coding/codecs/ilbc/lpc_encode.c | 2 +- .../audio_coding/codecs/ilbc/lpc_encode.h | 2 +- .../audio_coding/codecs/ilbc/lsf_to_lsp.c | 4 +- .../audio_coding/codecs/ilbc/lsp_to_lsf.c | 2 +- .../audio_coding/codecs/ilbc/my_corr.c | 2 +- .../codecs/ilbc/nearest_neighbor.c | 2 +- .../audio_coding/codecs/ilbc/poly_to_lsp.c | 8 +- .../audio_coding/codecs/ilbc/refiner.c | 4 +- .../codecs/ilbc/simple_interpolate_lsf.c | 2 +- .../codecs/ilbc/simple_interpolate_lsf.h | 2 +- .../codecs/ilbc/simple_lpc_analysis.c | 2 +- .../codecs/ilbc/simple_lpc_analysis.h | 2 +- .../codecs/ilbc/simple_lsf_dequant.c | 12 +- .../modules/audio_coding/codecs/ilbc/smooth.c | 24 +- .../codecs/ilbc/smooth_out_data.c | 2 +- .../codecs/ilbc/state_construct.c | 9 +- .../audio_coding/codecs/ilbc/state_search.c | 2 +- .../audio_coding/codecs/ilbc/state_search.h | 2 +- .../audio_coding/codecs/ilbc/test/iLBC_test.c | 9 +- .../codecs/ilbc/test/iLBC_testLib.c | 4 +- .../codecs/ilbc/test/iLBC_testprogram.c | 8 +- .../modules/audio_coding/codecs/ilbc/vq3.c | 4 +- .../modules/audio_coding/codecs/ilbc/vq4.c | 4 +- .../audio_coding/codecs/ilbc/window32_w32.c | 11 +- .../audio_coding/codecs/ilbc/xcorr_coef.c | 2 +- .../codecs/interfaces.gypi} | 23 +- .../codecs/isac/audio_encoder_isac_t.h | 132 + .../codecs/isac/audio_encoder_isac_t_impl.h | 284 + .../fix/interface/audio_encoder_isacfix.h | 108 + .../isac/fix/source/arith_routines_hist.c | 17 +- .../isac/fix/source/arith_routines_logist.c | 9 +- .../isac/fix/source/audio_encoder_isacfix.cc | 23 + .../isac/fix/source/bandwidth_estimator.c | 33 +- .../codecs/isac/fix/source/codec.h | 8 +- .../codecs/isac/fix/source/decode.c | 6 +- .../codecs/isac/fix/source/decode_plc.c | 23 +- .../codecs/isac/fix/source/encode.c | 12 +- .../codecs/isac/fix/source/entropy_coding.c | 104 +- .../codecs/isac/fix/source/entropy_coding.h | 8 +- .../audio_coding/codecs/isac/fix/source/fft.c | 20 +- .../codecs/isac/fix/source/filterbanks.c | 42 +- .../codecs/isac/fix/source/filterbanks_neon.S | 64 +- .../codecs/isac/fix/source/filterbanks_neon.c | 275 + .../codecs/isac/fix/source/filters.c | 19 +- .../codecs/isac/fix/source/filters_neon.c | 114 + .../codecs/isac/fix/source/initialize.c | 8 +- .../codecs/isac/fix/source/isacfix.c | 2 +- .../codecs/isac/fix/source/isacfix.gypi | 156 - .../codecs/isac/fix/source/lattice.c | 24 +- .../codecs/isac/fix/source/lattice_neon.c | 195 + .../isac/fix/source/lpc_masking_model.c | 62 +- .../codecs/isac/fix/source/pitch_estimator.c | 28 +- .../isac/fix/source/pitch_estimator_c.c | 4 +- .../isac/fix/source/pitch_estimator_mips.c | 3 +- .../codecs/isac/fix/source/pitch_filter.c | 15 +- .../codecs/isac/fix/source/pitch_filter_c.c | 6 +- .../codecs/isac/fix/source/structs.h | 12 +- .../codecs/isac/fix/source/transform.c | 28 +- .../codecs/isac/fix/source/transform_mips.c | 3 + .../codecs/isac/fix/source/transform_neon.S | 10 +- .../codecs/isac/fix/source/transform_neon.c | 479 + .../codecs/isac/fix/test/isac_speed_test.cc | 4 +- .../audio_coding/codecs/isac/isac.gypi | 93 + .../audio_coding/codecs/isac/isacfix.gypi | 164 + .../isac/main/interface/audio_encoder_isac.h | 106 + .../isac/main/source/audio_encoder_isac.cc | 21 + .../codecs/isac/main/source/codec.h | 2 +- .../codecs/isac/main/source/encode.c | 2 +- .../codecs/isac/main/source/entropy_coding.c | 16 +- .../codecs/isac/main/source/entropy_coding.h | 12 +- .../codecs/isac/main/source/isac.c | 7 + .../codecs/isac/main/source/isac.gypi | 87 - .../codecs/isac/main/source/structs.h | 4 +- .../codecs/mock/mock_audio_encoder.h | 41 + .../codecs/opus/audio_encoder_opus.cc | 168 +- .../opus/audio_encoder_opus_unittest.cc | 80 + .../opus/interface/audio_encoder_opus.h | 48 +- .../codecs/opus/interface/opus_interface.h | 67 +- .../audio_coding/codecs/opus/opus.gypi | 40 +- .../audio_coding/codecs/opus/opus_fec_test.cc | 19 +- .../audio_coding/codecs/opus/opus_inst.h | 5 +- .../audio_coding/codecs/opus/opus_interface.c | 301 +- .../codecs/opus/opus_speed_test.cc | 12 +- .../audio_coding/codecs/opus/opus_unittest.cc | 879 +- .../codecs/pcm16b/audio_encoder_pcm16b.cc | 22 + .../pcm16b/include/audio_encoder_pcm16b.h | 37 + .../codecs/pcm16b/include/pcm16b.h | 65 +- .../audio_coding/codecs/pcm16b/pcm16b.c | 96 +- .../audio_coding/codecs/pcm16b/pcm16b.gypi | 6 + .../codecs/red/audio_encoder_copy_red.cc | 107 + .../codecs/red/audio_encoder_copy_red.h | 62 + .../red/audio_encoder_copy_red_unittest.cc | 334 + .../modules/audio_coding/codecs/red/red.gypi | 33 + .../codecs/tools/audio_codec_speed_test.h | 8 +- .../codecs/tools/audio_codec_speed_tests.gypi | 66 - .../modules/audio_coding/main/acm2/acm_amr.cc | 304 - .../modules/audio_coding/main/acm2/acm_amr.h | 67 - .../audio_coding/main/acm2/acm_amrwb.cc | 311 - .../audio_coding/main/acm2/acm_amrwb.h | 68 - .../audio_coding/main/acm2/acm_celt.cc | 184 - .../modules/audio_coding/main/acm2/acm_celt.h | 52 - .../modules/audio_coding/main/acm2/acm_cng.cc | 76 - .../modules/audio_coding/main/acm2/acm_cng.h | 59 - .../main/acm2/acm_codec_database.cc | 461 +- .../main/acm2/acm_codec_database.h | 91 +- .../audio_coding/main/acm2/acm_common_defs.h | 19 - .../main/acm2/acm_dtmf_playout.cc | 81 - .../audio_coding/main/acm2/acm_dtmf_playout.h | 42 - .../audio_coding/main/acm2/acm_g722.cc | 192 - .../modules/audio_coding/main/acm2/acm_g722.h | 64 - .../audio_coding/main/acm2/acm_g7221.cc | 321 - .../audio_coding/main/acm2/acm_g7221.h | 64 - .../audio_coding/main/acm2/acm_g7221c.cc | 327 - .../audio_coding/main/acm2/acm_g7221c.h | 64 - .../audio_coding/main/acm2/acm_g729.cc | 250 - .../modules/audio_coding/main/acm2/acm_g729.h | 56 - .../audio_coding/main/acm2/acm_g7291.cc | 235 - .../audio_coding/main/acm2/acm_g7291.h | 54 - .../main/acm2/acm_generic_codec.cc | 1349 +- .../main/acm2/acm_generic_codec.h | 788 +- .../main/acm2/acm_generic_codec_opus_test.cc | 145 + .../main/acm2/acm_generic_codec_test.cc | 106 + .../audio_coding/main/acm2/acm_gsmfr.cc | 150 - .../audio_coding/main/acm2/acm_gsmfr.h | 52 - .../audio_coding/main/acm2/acm_ilbc.cc | 136 - .../modules/audio_coding/main/acm2/acm_ilbc.h | 54 - .../audio_coding/main/acm2/acm_isac.cc | 828 - .../modules/audio_coding/main/acm2/acm_isac.h | 139 - .../audio_coding/main/acm2/acm_isac_macros.h | 80 - .../audio_coding/main/acm2/acm_opus.cc | 258 - .../modules/audio_coding/main/acm2/acm_opus.h | 63 - .../main/acm2/acm_opus_unittest.cc | 94 - .../audio_coding/main/acm2/acm_pcm16b.cc | 89 - .../audio_coding/main/acm2/acm_pcm16b.h | 47 - .../audio_coding/main/acm2/acm_pcma.cc | 57 - .../modules/audio_coding/main/acm2/acm_pcma.h | 44 - .../audio_coding/main/acm2/acm_pcmu.cc | 59 - .../modules/audio_coding/main/acm2/acm_pcmu.h | 45 - .../main/acm2/acm_receive_test.cc | 9 +- .../audio_coding/main/acm2/acm_receive_test.h | 4 +- .../main/acm2/acm_receive_test_oldapi.cc | 2 +- .../main/acm2/acm_receive_test_oldapi.h | 6 +- .../audio_coding/main/acm2/acm_receiver.cc | 212 +- .../audio_coding/main/acm2/acm_receiver.h | 43 +- .../main/acm2/acm_receiver_unittest.cc | 79 +- .../main/acm2/acm_receiver_unittest_oldapi.cc | 88 +- .../modules/audio_coding/main/acm2/acm_red.cc | 50 - .../modules/audio_coding/main/acm2/acm_red.h | 42 - .../audio_coding/main/acm2/acm_send_test.cc | 6 +- .../audio_coding/main/acm2/acm_send_test.h | 19 +- .../main/acm2/acm_send_test_oldapi.cc | 13 +- .../main/acm2/acm_send_test_oldapi.h | 20 +- .../audio_coding/main/acm2/acm_speex.cc | 324 - .../audio_coding/main/acm2/acm_speex.h | 67 - .../main/acm2/audio_coding_module.gypi | 63 +- .../main/acm2/audio_coding_module_impl.cc | 1550 +- .../main/acm2/audio_coding_module_impl.h | 324 +- .../main/acm2/audio_coding_module_unittest.cc | 186 +- .../audio_coding_module_unittest_oldapi.cc | 407 +- .../audio_coding/main/acm2/codec_manager.cc | 612 + .../audio_coding/main/acm2/codec_manager.h | 101 + .../main/acm2/initial_delay_manager.h | 2 +- .../acm2/initial_delay_manager_unittest.cc | 3 +- .../modules/audio_coding/main/acm2/nack.cc | 4 +- .../modules/audio_coding/main/acm2/nack.h | 10 +- .../audio_coding/main/acm2/nack_unittest.cc | 26 +- .../main/interface/audio_coding_module.h | 164 +- .../interface/audio_coding_module_typedefs.h | 54 +- .../modules/audio_coding/main/test/APITest.cc | 80 +- .../modules/audio_coding/main/test/APITest.h | 6 +- .../modules/audio_coding/main/test/Channel.cc | 61 +- .../modules/audio_coding/main/test/Channel.h | 21 +- .../main/test/EncodeDecodeTest.cc | 17 +- .../audio_coding/main/test/EncodeDecodeTest.h | 17 +- .../audio_coding/main/test/PacketLossTest.cc | 2 +- .../audio_coding/main/test/PacketLossTest.h | 9 +- .../modules/audio_coding/main/test/RTPFile.cc | 91 +- .../modules/audio_coding/main/test/RTPFile.h | 46 +- .../audio_coding/main/test/SpatialAudio.cc | 13 +- .../audio_coding/main/test/SpatialAudio.h | 8 +- .../audio_coding/main/test/TestAllCodecs.cc | 399 +- .../audio_coding/main/test/TestAllCodecs.h | 27 +- .../audio_coding/main/test/TestRedFec.cc | 248 +- .../audio_coding/main/test/TestRedFec.h | 8 +- .../audio_coding/main/test/TestStereo.cc | 103 +- .../audio_coding/main/test/TestStereo.h | 41 +- .../audio_coding/main/test/TestVADDTX.cc | 589 +- .../audio_coding/main/test/TestVADDTX.h | 116 +- .../modules/audio_coding/main/test/Tester.cc | 12 +- .../main/test/TwoWayCommunication.cc | 32 +- .../main/test/TwoWayCommunication.h | 10 +- .../audio_coding/main/test/delay_test.cc | 13 +- .../main/test/dual_stream_unittest.cc | 540 - .../audio_coding/main/test/iSACTest.cc | 6 +- .../modules/audio_coding/main/test/iSACTest.h | 10 +- .../main/test/initial_delay_unittest.cc | 9 +- .../main/test/insert_packet_with_timing.cc | 16 +- .../audio_coding/main/test/opus_test.cc | 13 +- .../audio_coding/main/test/opus_test.h | 5 +- .../main/test/target_delay_unittest.cc | 12 +- .../modules/audio_coding/main/test/utility.cc | 24 +- .../modules/audio_coding/main/test/utility.h | 4 +- .../modules/audio_coding/neteq/accelerate.h | 16 +- .../audio_coding/neteq/audio_classifier.h | 6 +- .../neteq/audio_classifier_unittest.cc | 2 +- .../audio_coding/neteq/audio_decoder.cc | 268 - .../audio_coding/neteq/audio_decoder_impl.cc | 498 +- .../audio_coding/neteq/audio_decoder_impl.h | 232 +- .../neteq/audio_decoder_unittest.cc | 601 +- .../neteq/audio_decoder_unittests.isolate | 6 +- .../audio_coding/neteq/audio_vector.cc | 2 +- .../modules/audio_coding/neteq/audio_vector.h | 4 +- .../audio_coding/neteq/background_noise.cc | 3 +- .../audio_coding/neteq/background_noise.h | 4 +- .../audio_coding/neteq/comfort_noise.cc | 2 +- .../audio_coding/neteq/decision_logic_fax.h | 14 +- .../audio_coding/neteq/decoder_database.cc | 15 +- .../audio_coding/neteq/decoder_database.h | 6 +- .../audio_coding/neteq/delay_manager.h | 2 +- .../modules/audio_coding/neteq/dtmf_buffer.cc | 2 +- .../modules/audio_coding/neteq/dtmf_buffer.h | 2 +- .../modules/audio_coding/neteq/expand.cc | 8 +- .../modules/audio_coding/neteq/expand.h | 4 +- .../audio_coding/neteq/interface/neteq.h | 10 +- .../modules/audio_coding/neteq/merge.cc | 5 +- .../neteq/mock/mock_audio_decoder.h | 8 +- .../neteq/mock/mock_external_decoder_pcm16b.h | 36 +- .../neteq/mock/mock_payload_splitter.h | 8 +- .../modules/audio_coding/neteq/neteq.gypi | 12 +- .../neteq/neteq_external_decoder_unittest.cc | 452 +- .../modules/audio_coding/neteq/neteq_impl.cc | 115 +- .../modules/audio_coding/neteq/neteq_impl.h | 138 +- .../audio_coding/neteq/neteq_impl_unittest.cc | 333 +- .../neteq/neteq_network_stats_unittest.cc | 301 + .../neteq/neteq_stereo_unittest.cc | 4 +- .../audio_coding/neteq/neteq_tests.gypi | 18 +- .../audio_coding/neteq/neteq_unittest.cc | 196 +- .../modules/audio_coding/neteq/normal.cc | 6 +- .../audio_coding/neteq/normal_unittest.cc | 6 +- .../modules/audio_coding/neteq/packet.h | 2 +- .../audio_coding/neteq/packet_buffer.cc | 2 +- .../audio_coding/neteq/payload_splitter.cc | 37 +- .../audio_coding/neteq/payload_splitter.h | 8 +- .../neteq/payload_splitter_unittest.cc | 200 +- .../audio_coding/neteq/post_decode_vad.h | 2 +- .../neteq/statistics_calculator.cc | 24 +- .../neteq/statistics_calculator.h | 6 +- .../neteq/test/NETEQTEST_DummyRTPpacket.h | 6 +- .../neteq/test/NETEQTEST_RTPpacket.cc | 150 +- .../neteq/test/NETEQTEST_RTPpacket.h | 5 +- .../audio_coding/neteq/test/PayloadTypes.h | 1 - .../modules/audio_coding/neteq/test/RTPcat.cc | 75 - .../audio_coding/neteq/test/RTPencode.cc | 251 +- .../neteq/test/audio_classifier_test.cc | 4 +- .../neteq/test/neteq_isac_quality_test.cc | 4 +- ...ity_test.cc => neteq_opus_quality_test.cc} | 86 +- .../audio_coding/neteq/test/rtp_to_text.cc | 2 +- .../audio_coding/neteq/time_stretch.cc | 4 +- .../audio_coding/neteq/timestamp_scaler.cc | 1 + .../audio_coding/neteq/tools/audio_checksum.h | 3 +- .../audio_coding/neteq/tools/audio_loop.h | 4 +- .../audio_coding/neteq/tools/audio_sink.h | 2 +- .../neteq/tools/constant_pcm_packet_source.cc | 15 +- .../neteq/tools/constant_pcm_packet_source.h | 4 +- .../tools/neteq_external_decoder_test.cc | 64 + .../neteq/tools/neteq_external_decoder_test.h | 61 + .../neteq/tools/neteq_performance_test.cc | 5 +- .../neteq/tools/neteq_quality_test.h | 32 +- .../audio_coding/neteq/tools/neteq_rtpplay.cc | 677 +- .../neteq/tools/output_audio_file.h | 2 +- .../neteq/tools/output_wav_file.h | 43 + .../audio_coding/neteq/tools/packet.cc | 4 +- .../modules/audio_coding/neteq/tools/packet.h | 4 +- .../audio_coding/neteq/tools/packet_source.h | 3 +- .../neteq/tools/packet_unittest.cc | 6 +- .../neteq/tools/resample_input_audio_file.cc | 7 +- .../audio_coding/neteq/tools/rtp_analyze.cc | 6 +- .../neteq/tools/rtp_file_source.cc | 12 +- .../neteq/tools/rtp_file_source.h | 8 +- .../audio_coding/neteq/tools/rtp_generator.h | 2 +- .../audio_coding/neteq/tools/rtpcat.cc | 45 + .../modules/audio_conference_mixer/OWNERS | 1 - .../audio_conference_mixer.gypi | 36 + .../interface/audio_conference_mixer.h | 5 +- .../source/audio_conference_mixer.gypi | 46 - .../source/audio_conference_mixer_impl.cc | 9 +- .../source/audio_conference_mixer_impl.h | 44 +- .../source/time_scheduler.cc | 13 +- .../source/time_scheduler.h | 8 +- .../webrtc/modules/audio_device/BUILD.gn | 5 + .../modules/audio_device/android/OWNERS | 1 - .../audio_device/android/audio_common.h | 3 + .../android/audio_device_template.h | 482 +- .../android/audio_device_unittest.cc | 884 + .../android/audio_device_utility_android.cc | 36 +- .../android/audio_device_utility_android.h | 20 +- .../audio_device/android/audio_manager.cc | 204 + .../audio_device/android/audio_manager.h | 141 + .../audio_device/android/audio_manager_jni.cc | 30 +- .../audio_device/android/audio_manager_jni.h | 2 - .../audio_device/android/audio_record_jni.cc | 1389 +- .../audio_device/android/audio_record_jni.h | 233 +- .../audio_device/android/audio_track_jni.cc | 1607 +- .../audio_device/android/audio_track_jni.h | 229 +- .../android/ensure_initialized.cc | 51 + .../android/ensure_initialized.h} | 12 +- .../audio_device/android/fine_audio_buffer.h | 4 +- .../android/fine_audio_buffer_unittest.cc | 4 +- .../voiceengine/WebRtcAudioManager.java | 152 + .../webrtc/voiceengine/WebRtcAudioRecord.java | 380 +- .../webrtc/voiceengine/WebRtcAudioTrack.java | 482 +- .../webrtc/voiceengine/WebRtcAudioUtils.java | 53 + .../android/low_latency_event_unittest.cc | 14 +- .../audio_device/android/opensles_input.cc | 53 +- .../audio_device/android/opensles_input.h | 26 +- .../audio_device/android/opensles_output.cc | 27 +- .../audio_device/android/opensles_output.h | 23 +- .../audio_device/android/single_rw_fifo.cc | 6 + .../audio_device/android/single_rw_fifo.h | 4 +- .../android/single_rw_fifo_unittest.cc | 4 +- .../modules/audio_device/audio_device.gypi | 24 +- .../audio_device/audio_device_buffer.h | 1 - .../audio_device/audio_device_generic.cc | 8 +- .../audio_device/audio_device_generic.h | 7 +- .../modules/audio_device/audio_device_impl.cc | 60 +- .../modules/audio_device/audio_device_impl.h | 206 +- .../audio_device/audio_device_tests.isolate | 8 - .../audio_device/dummy/audio_device_dummy.h | 167 +- .../dummy/audio_device_utility_dummy.h | 2 +- .../audio_device/dummy/file_audio_device.cc | 130 +- .../audio_device/dummy/file_audio_device.h | 173 +- .../dummy/file_audio_device_factory.cc | 6 +- .../dummy/file_audio_device_factory.h | 1 + .../audio_device/gonk/audio_manager.cc | 1 + .../modules/audio_device/gonk/audio_manager.h | 6 + .../audio_device/include/audio_device.h | 17 +- .../audio_device/include/fake_audio_device.h | 3 +- .../audio_device/ios/audio_device_ios.h | 6 +- .../audio_device/ios/audio_device_ios.mm | 27 +- .../linux/audio_device_alsa_linux.cc | 106 +- .../linux/audio_device_alsa_linux.h | 181 +- .../linux/audio_device_pulse_linux.cc | 70 +- .../linux/audio_device_pulse_linux.h | 180 +- .../linux/audio_device_utility_linux.h | 2 +- .../linux/latebindingsymboltable_linux.cc | 7 +- .../audio_device/mac/audio_device_mac.cc | 431 +- .../audio_device/mac/audio_device_mac.h | 30 +- .../mac/portaudio/pa_ringbuffer.c | 66 +- .../mac/portaudio/pa_ringbuffer.h | 48 +- .../audio_device/sndio/audio_device_sndio.cc | 38 +- .../audio_device/sndio/audio_device_sndio.h | 150 +- .../sndio/audio_device_utility_sndio.h | 2 +- .../test/audio_device_test_api.cc | 9 +- .../audio_device/test/func_test_manager.cc | 19 +- .../audio_device/test/func_test_manager.h | 2 +- .../audio_device/win/audio_device_wave_win.cc | 52 +- .../audio_device/win/audio_device_wave_win.h | 5 +- .../webrtc/modules/audio_processing/BUILD.gn | 125 +- .../modules/audio_processing/aec/aec_core.c | 633 +- .../modules/audio_processing/aec/aec_core.h | 48 +- .../audio_processing/aec/aec_core_internal.h | 89 +- .../audio_processing/aec/aec_core_mips.c | 2 +- .../audio_processing/aec/aec_core_neon.c | 3 + .../modules/audio_processing/aec/aec_rdft.c | 20 +- .../modules/audio_processing/aec/aec_rdft.h | 16 +- .../audio_processing/aec/aec_resampler.c | 34 +- .../audio_processing/aec/aec_resampler.h | 10 +- .../audio_processing/aec/echo_cancellation.c | 403 +- .../aec/echo_cancellation_internal.h | 6 +- .../aec/include/echo_cancellation.h | 109 +- .../aec/system_delay_unittest.cc | 29 +- .../modules/audio_processing/aecm/aecm_core.c | 133 +- .../modules/audio_processing/aecm/aecm_core.h | 125 +- .../audio_processing/aecm/aecm_core_c.c | 101 +- .../audio_processing/aecm/aecm_core_mips.c | 43 +- .../audio_processing/aecm/aecm_core_neon.S | 171 - .../audio_processing/aecm/aecm_core_neon.c | 421 +- .../aecm/aecm_core_neon_offsets.c | 26 - .../aecm/echo_control_mobile.c | 242 +- .../aecm/include/echo_control_mobile.h | 89 +- .../modules/audio_processing/agc/agc.cc | 158 + .../webrtc/modules/audio_processing/agc/agc.h | 69 + .../audio_processing/agc/agc_audio_proc.cc | 269 + .../audio_processing/agc/agc_audio_proc.h | 83 + .../agc/agc_audio_proc_internal.h | 81 + .../agc/agc_audio_proc_unittest.cc | 61 + .../agc/agc_manager_direct.cc | 435 + .../audio_processing/agc/agc_manager_direct.h | 98 + .../audio_processing/agc/agc_unittest.cc | 162 + .../audio_processing/agc/circular_buffer.cc | 136 + .../audio_processing/agc/circular_buffer.h | 69 + .../agc/circular_buffer_unittest.cc | 132 + .../modules/audio_processing/agc/common.h | 27 + .../audio_processing/agc/gain_map_internal.h | 275 + .../modules/audio_processing/agc/gmm.cc | 61 + .../webrtc/modules/audio_processing/agc/gmm.h | 45 + .../audio_processing/agc/gmm_unittest.cc | 65 + .../modules/audio_processing/agc/histogram.cc | 228 + .../modules/audio_processing/agc/histogram.h | 91 + .../agc/histogram_unittest.cc | 104 + .../agc/{ => legacy}/analog_agc.c | 444 +- .../agc/{ => legacy}/analog_agc.h | 24 +- .../agc/{ => legacy}/digital_agc.c | 129 +- .../agc/{ => legacy}/digital_agc.h | 36 +- .../agc/{include => legacy}/gain_control.h | 89 +- .../modules/audio_processing/agc/mock_agc.h | 36 + .../audio_processing/agc/noise_gmm_tables.h | 77 + .../audio_processing/agc/pitch_based_vad.cc | 122 + .../audio_processing/agc/pitch_based_vad.h | 56 + .../agc/pitch_based_vad_unittest.cc | 71 + .../audio_processing/agc/pitch_internal.cc | 52 + .../audio_processing/agc/pitch_internal.h | 26 + .../agc/pitch_internal_unittest.cc | 50 + .../audio_processing/agc/pole_zero_filter.cc | 111 + .../audio_processing/agc/pole_zero_filter.h | 50 + .../agc/pole_zero_filter_unittest.cc | 97 + .../audio_processing/agc/standalone_vad.cc | 96 + .../audio_processing/agc/standalone_vad.h | 70 + .../agc/standalone_vad_unittest.cc | 103 + .../modules/audio_processing/agc/utility.cc | 35 + .../modules/audio_processing/agc/utility.h | 23 + .../audio_processing/agc/voice_gmm_tables.h | 77 + .../modules/audio_processing/audio_buffer.cc | 437 +- .../modules/audio_processing/audio_buffer.h | 156 +- .../audio_processing/audio_processing.gypi | 121 +- .../audio_processing/audio_processing_impl.cc | 325 +- .../audio_processing/audio_processing_impl.h | 166 +- .../audio_processing_impl_unittest.cc | 4 +- .../audio_processing_tests.gypi | 56 +- .../audio_processing/beamformer/array_util.h | 49 + .../audio_processing/beamformer/beamformer.h | 41 + .../beamformer/complex_matrix.h | 97 + .../beamformer/complex_matrix_unittest.cc | 102 + .../beamformer/covariance_matrix_generator.cc | 102 + .../beamformer/covariance_matrix_generator.h | 54 + .../covariance_matrix_generator_unittest.cc | 230 + .../audio_processing/beamformer/matrix.h | 366 + .../beamformer/matrix_test_helpers.h | 102 + .../beamformer/matrix_unittest.cc | 326 + .../beamformer/mock_nonlinear_beamformer.cc | 22 + .../beamformer/mock_nonlinear_beamformer.h | 33 + .../beamformer/nonlinear_beamformer.cc | 463 + .../beamformer/nonlinear_beamformer.h | 169 + .../beamformer/nonlinear_beamformer_test.cc | 82 + .../audio_processing/beamformer/pcm_utils.cc | 90 + .../audio_processing/beamformer/pcm_utils.h | 50 + .../webrtc/modules/audio_processing/common.h | 76 - .../echo_cancellation_impl.cc | 65 +- .../audio_processing/echo_cancellation_impl.h | 58 +- .../echo_cancellation_impl_unittest.cc | 6 +- .../echo_control_mobile_impl.cc | 41 +- .../echo_control_mobile_impl.h | 30 +- .../audio_processing/gain_control_impl.cc | 33 +- .../audio_processing/gain_control_impl.h | 46 +- .../gen_core_neon_offsets.gyp | 45 - .../gen_core_neon_offsets_chromium.gyp | 45 - .../audio_processing/high_pass_filter_impl.cc | 24 +- .../audio_processing/high_pass_filter_impl.h | 16 +- .../include/audio_processing.h | 58 +- .../include/mock_audio_processing.h | 18 +- .../audio_processing/level_estimator_impl.cc | 3 +- .../audio_processing/level_estimator_impl.h | 18 +- .../lib_core_neon_offsets.gypi | 51 - .../noise_suppression_impl.cc | 35 +- .../audio_processing/noise_suppression_impl.h | 22 +- .../modules/audio_processing/ns/defines.h | 1 + .../ns/include/noise_suppression.h | 25 +- .../ns/include/noise_suppression_x.h | 20 +- .../audio_processing/ns/noise_suppression.c | 24 +- .../audio_processing/ns/noise_suppression_x.c | 19 +- .../modules/audio_processing/ns/ns_core.c | 131 +- .../modules/audio_processing/ns/ns_core.h | 41 +- .../modules/audio_processing/ns/nsx_core.c | 201 +- .../modules/audio_processing/ns/nsx_core.h | 78 +- .../modules/audio_processing/ns/nsx_core_c.c | 20 +- .../audio_processing/ns/nsx_core_mips.c | 32 +- .../audio_processing/ns/nsx_core_neon.S | 651 - .../audio_processing/ns/nsx_core_neon.c | 141 +- .../ns/nsx_core_neon_offsets.c | 34 - .../modules/audio_processing/ns/nsx_defines.h | 1 + .../audio_processing/splitting_filter.cc | 164 + .../audio_processing/splitting_filter.h | 82 + .../splitting_filter_unittest.cc | 98 + .../test/audio_processing_unittest.cc | 332 +- .../audio_processing/test/audioproc_float.cc | 213 + .../audio_processing/test/process_test.cc | 33 +- .../audio_processing/test/test_utils.h | 15 +- .../audio_processing/test/unittest.proto | 2 + .../modules/audio_processing/test/unpack.cc | 23 +- .../transient/click_annotate.cc | 114 + .../audio_processing/transient/common.h | 27 + .../transient/daubechies_8_wavelet_coeffs.h | 63 + .../transient/dyadic_decimator.h | 70 + .../transient/dyadic_decimator_unittest.cc | 126 + .../audio_processing/transient/file_utils.cc | 257 + .../audio_processing/transient/file_utils.h | 118 + .../transient/file_utils_unittest.cc | 485 + .../transient/moving_moments.cc | 49 + .../transient/moving_moments.h | 52 + .../transient/moving_moments_unittest.cc | 206 + .../transient/test/plotDetection.m | 12 + .../transient/test/readDetection.m | 16 + .../audio_processing/transient/test/readPCM.m | 16 + .../transient/transient_detector.cc | 173 + .../transient/transient_detector.h | 87 + .../transient/transient_detector_unittest.cc | 104 + .../transient/transient_suppression_test.cc | 250 + .../transient/transient_suppressor.cc | 424 + .../transient/transient_suppressor.h | 120 + .../transient_suppressor_unittest.cc | 85 + .../audio_processing/transient/wpd_node.cc | 71 + .../audio_processing/transient/wpd_node.h | 46 + .../transient/wpd_node_unittest.cc | 66 + .../audio_processing/transient/wpd_tree.cc | 119 + .../audio_processing/transient/wpd_tree.h | 91 + .../transient/wpd_tree_unittest.cc | 198 + .../audio_processing/voice_detection_impl.cc | 2 +- .../audio_processing/voice_detection_impl.h | 30 +- .../modules/bitrate_controller/BUILD.gn | 4 + .../bitrate_controller/bitrate_allocator.cc | 210 + .../bitrate_allocator_unittest.cc | 214 + .../bitrate_controller.gypi | 6 +- .../bitrate_controller_impl.cc | 322 +- .../bitrate_controller_impl.h | 105 +- .../bitrate_controller_unittest.cc | 471 +- .../include/bitrate_allocator.h | 106 + .../include/bitrate_controller.h | 61 +- .../send_side_bandwidth_estimation.cc | 105 +- .../send_side_bandwidth_estimation.h | 27 +- ...send_side_bandwidth_estimation_unittest.cc | 47 + .../bitrate_controller/send_time_history.cc | 86 + .../bitrate_controller/send_time_history.h | 42 + .../send_time_history_unittest.cc | 149 + .../webrtc/modules/desktop_capture/BUILD.gn | 17 +- .../desktop_capture/app_capturer_mac.mm | 10 +- .../desktop_capture/app_capturer_null.cc | 10 +- .../desktop_capture/app_capturer_unittest.cc | 14 +- .../desktop_capture/app_capturer_win.cc | 36 +- .../desktop_capture/app_capturer_x11.cc | 34 +- .../desktop_capture/cropped_desktop_frame.cc | 45 + .../desktop_capture/cropped_desktop_frame.h | 25 + .../cropping_window_capturer.cc | 111 + .../cropping_window_capturer.h | 74 + .../cropping_window_capturer_win.cc | 216 + .../desktop_and_cursor_composer.cc | 4 +- .../desktop_and_cursor_composer.h | 24 +- .../desktop_and_cursor_composer_unittest.cc | 30 +- .../desktop_capture/desktop_capture.gypi | 7 +- .../desktop_capture/desktop_device_info.cc | 4 +- .../modules/desktop_capture/desktop_frame.cc | 10 +- .../modules/desktop_capture/desktop_frame.h | 13 +- .../desktop_capture/desktop_frame_win.h | 4 +- .../webrtc/modules/desktop_capture/differ.h | 4 +- .../desktop_capture/differ_unittest.cc | 8 +- .../mac/desktop_configuration_monitor.h | 4 +- .../mac/desktop_device_info_mac.h | 4 +- .../modules/desktop_capture/mouse_cursor.h | 4 +- .../mouse_cursor_monitor_mac.mm | 13 +- .../mouse_cursor_monitor_unittest.cc | 27 +- .../mouse_cursor_monitor_win.cc | 6 +- .../mouse_cursor_monitor_x11.cc | 14 +- .../screen_capture_frame_queue.h | 4 +- .../modules/desktop_capture/screen_capturer.h | 2 +- .../desktop_capture/screen_capturer_helper.h | 4 +- .../screen_capturer_helper_unittest.cc | 2 +- .../desktop_capture/screen_capturer_mac.mm | 18 +- .../screen_capturer_mac_unittest.cc | 12 +- .../screen_capturer_unittest.cc | 4 +- .../desktop_capture/screen_capturer_win.cc | 3 +- .../desktop_capture/screen_capturer_x11.cc | 18 +- .../desktop_capture/shared_desktop_frame.cc | 4 +- .../modules/desktop_capture/win/cursor.cc | 11 +- .../desktop_capture/win/cursor_unittest.cc | 6 +- .../modules/desktop_capture/win/desktop.h | 2 +- .../win/desktop_device_info_win.h | 4 +- .../win/scoped_thread_desktop.cc | 2 +- .../win/scoped_thread_desktop.h | 6 +- .../win/screen_capturer_win_gdi.cc | 4 +- .../win/screen_capturer_win_gdi.h | 12 +- .../win/screen_capturer_win_magnifier.cc | 6 +- .../win/screen_capturer_win_magnifier.h | 18 +- .../modules/desktop_capture/window_capturer.h | 6 +- .../desktop_capture/window_capturer_mac.mm | 10 +- .../desktop_capture/window_capturer_null.cc | 10 +- .../window_capturer_unittest.cc | 19 +- .../desktop_capture/window_capturer_win.cc | 16 +- .../desktop_capture/window_capturer_x11.cc | 14 +- .../x11/desktop_device_info_x11.cc | 2 +- .../x11/desktop_device_info_x11.h | 4 +- .../desktop_capture/x11/shared_x_util.cc | 5 - .../trunk/webrtc/modules/interface/module.h | 59 +- .../modules/interface/module_common_types.h | 283 +- .../trunk/webrtc/modules/media_file/BUILD.gn | 12 +- .../modules/media_file/interface/media_file.h | 55 +- .../media_file/{source => }/media_file.gypi | 28 +- .../modules/media_file/source/avi_file.cc | 1747 - .../modules/media_file/source/avi_file.h | 277 - .../media_file/source/media_file_impl.cc | 310 +- .../media_file/source/media_file_impl.h | 231 +- .../media_file/source/media_file_unittest.cc | 14 +- .../media_file/source/media_file_utility.cc | 885 +- .../media_file/source/media_file_utility.h | 83 +- media/webrtc/trunk/webrtc/modules/modules.gyp | 160 +- .../webrtc/modules/modules_tests.isolate | 12 +- .../webrtc/modules/modules_unittests.isolate | 57 +- .../trunk/webrtc/modules/pacing/BUILD.gn | 2 + .../webrtc/modules/pacing/bitrate_prober.cc | 2 +- .../modules/pacing/bitrate_prober_unittest.cc | 4 +- .../pacing/include/mock/mock_paced_sender.h | 4 +- .../modules/pacing/include/paced_sender.h | 42 +- .../modules/pacing/include/packet_router.h | 59 + .../webrtc/modules/pacing/paced_sender.cc | 85 +- .../modules/pacing/paced_sender_unittest.cc | 79 +- .../trunk/webrtc/modules/pacing/pacing.gypi | 4 +- .../webrtc/modules/pacing/packet_router.cc | 61 + .../modules/pacing/packet_router_unittest.cc | 151 + .../modules/remote_bitrate_estimator/BUILD.gn | 11 + .../aimd_rate_control.cc | 337 + .../aimd_rate_control.h | 90 + .../bwe_simulations.cc | 250 +- .../include/remote_bitrate_estimator.h | 33 +- .../remote_bitrate_estimator/inter_arrival.cc | 121 + .../remote_bitrate_estimator/inter_arrival.h | 85 + .../inter_arrival_unittest.cc | 422 + .../mimd_rate_control.cc | 328 + .../mimd_rate_control.h | 80 + .../overuse_detector.cc | 286 +- .../overuse_detector.h | 86 +- .../overuse_detector_unittest.cc | 605 + .../overuse_estimator.cc | 153 + .../overuse_estimator.h | 70 + .../rate_statistics.cc | 6 +- .../rate_statistics.h | 8 +- .../remote_bitrate_estimator.gypi | 140 +- .../remote_bitrate_estimator_abs_send_time.cc | 559 + ...itrate_estimator_abs_send_time_unittest.cc | 240 + .../remote_bitrate_estimator_single_stream.cc | 268 +- ...itrate_estimator_single_stream_unittest.cc | 38 +- ...emote_bitrate_estimator_unittest_helper.cc | 166 +- ...remote_bitrate_estimator_unittest_helper.h | 23 +- .../remote_bitrate_estimators_test.cc | 236 +- .../remote_rate_control.cc | 315 +- .../remote_rate_control.h | 69 +- .../remote_bitrate_estimator/test/bwe.cc | 86 + .../remote_bitrate_estimator/test/bwe.h | 72 + .../remote_bitrate_estimator/test/bwe_test.cc | 367 +- .../remote_bitrate_estimator/test/bwe_test.h | 127 +- .../test/bwe_test_baselinefile.cc | 12 +- .../test/bwe_test_fileutils.cc | 2 +- .../test/bwe_test_framework.cc | 425 +- .../test/bwe_test_framework.h | 236 +- .../test/bwe_test_framework_unittest.cc | 271 +- .../test/bwe_test_logging.h | 4 +- .../test/estimators/nada.cc | 128 + .../test/estimators/nada.h | 65 + .../test/estimators/remb.cc | 160 + .../test/estimators/remb.h | 82 + .../test/estimators/send_side.cc | 125 + .../test/estimators/send_side.h | 67 + .../remote_bitrate_estimator/test/packet.h | 144 + .../test/packet_receiver.cc | 90 + .../test/packet_receiver.h | 54 + .../test/packet_sender.cc | 268 + .../test/packet_sender.h | 101 + .../tools/bwe_rtp_play.cc | 79 +- .../tools/rtp_to_text.cc | 16 +- .../trunk/webrtc/modules/rtp_rtcp/BUILD.gn | 3 + .../modules/rtp_rtcp/interface/fec_receiver.h | 15 +- .../rtp_rtcp/interface/receive_statistics.h | 41 +- .../interface/remote_ntp_time_estimator.h | 6 +- .../modules/rtp_rtcp/interface/rtp_cvo.h | 54 + .../rtp_rtcp/interface/rtp_payload_registry.h | 10 +- .../modules/rtp_rtcp/interface/rtp_receiver.h | 2 +- .../modules/rtp_rtcp/interface/rtp_rtcp.h | 249 +- .../rtp_rtcp/interface/rtp_rtcp_defines.h | 89 +- .../modules/rtp_rtcp/mocks/mock_rtp_rtcp.h | 88 +- .../webrtc/modules/rtp_rtcp/rtp_rtcp.gypi | 107 + .../webrtc/modules/rtp_rtcp/source/bitrate.cc | 2 +- .../webrtc/modules/rtp_rtcp/source/bitrate.h | 8 +- .../webrtc/modules/rtp_rtcp/source/byte_io.h | 24 +- .../rtp_rtcp/source/byte_io_unittest.cc | 2 +- .../modules/rtp_rtcp/source/dtmf_queue.cc | 15 +- .../rtp_rtcp/source/fec_receiver_impl.cc | 19 +- .../rtp_rtcp/source/fec_receiver_impl.h | 17 +- .../rtp_rtcp/source/fec_receiver_unittest.cc | 24 +- .../rtp_rtcp/source/fec_test_helper.cc | 13 +- .../modules/rtp_rtcp/source/fec_test_helper.h | 14 +- .../source/forward_error_correction.cc | 28 +- .../source/forward_error_correction.h | 4 +- .../rtp_rtcp/source/nack_rtx_unittest.cc | 61 +- .../modules/rtp_rtcp/source/producer_fec.cc | 24 +- .../modules/rtp_rtcp/source/producer_fec.h | 22 +- .../rtp_rtcp/source/producer_fec_unittest.cc | 4 +- .../source/receive_statistics_impl.cc | 110 +- .../rtp_rtcp/source/receive_statistics_impl.h | 71 +- .../source/receive_statistics_unittest.cc | 134 +- .../source/remote_ntp_time_estimator.cc | 2 +- .../remote_ntp_time_estimator_unittest.cc | 6 +- .../source/rtcp_format_remb_unittest.cc | 47 +- .../modules/rtp_rtcp/source/rtcp_packet.cc | 8 +- .../modules/rtp_rtcp/source/rtcp_packet.h | 80 +- .../rtp_rtcp/source/rtcp_packet_unittest.cc | 2 - .../modules/rtp_rtcp/source/rtcp_receiver.cc | 729 +- .../modules/rtp_rtcp/source/rtcp_receiver.h | 128 +- .../rtp_rtcp/source/rtcp_receiver_help.h | 14 +- .../rtp_rtcp/source/rtcp_receiver_unittest.cc | 190 +- .../modules/rtp_rtcp/source/rtcp_sender.cc | 550 +- .../modules/rtp_rtcp/source/rtcp_sender.h | 179 +- .../rtp_rtcp/source/rtcp_sender_unittest.cc | 93 +- .../rtp_rtcp/source/rtp_fec_unittest.cc | 18 +- .../rtp_rtcp/source/rtp_format_h264.cc | 4 +- .../modules/rtp_rtcp/source/rtp_format_h264.h | 25 +- .../source/rtp_format_h264_unittest.cc | 20 +- .../source/rtp_format_video_generic.cc | 2 +- .../source/rtp_format_video_generic.h | 27 +- .../modules/rtp_rtcp/source/rtp_format_vp8.cc | 164 +- .../modules/rtp_rtcp/source/rtp_format_vp8.h | 79 +- .../source/rtp_format_vp8_test_helper.cc | 26 +- .../source/rtp_format_vp8_test_helper.h | 18 +- .../source/rtp_format_vp8_unittest.cc | 139 +- .../rtp_rtcp/source/rtp_header_extension.cc | 76 +- .../rtp_rtcp/source/rtp_header_extension.h | 41 +- .../source/rtp_header_extension_unittest.cc | 25 +- .../rtp_rtcp/source/rtp_header_parser.cc | 15 +- .../rtp_rtcp/source/rtp_packet_history.cc | 115 +- .../rtp_rtcp/source/rtp_packet_history.h | 52 +- .../source/rtp_packet_history_unittest.cc | 98 +- .../rtp_rtcp/source/rtp_payload_registry.cc | 80 +- .../source/rtp_payload_registry_unittest.cc | 37 +- .../rtp_rtcp/source/rtp_receiver_audio.cc | 18 +- .../rtp_rtcp/source/rtp_receiver_audio.h | 27 +- .../rtp_rtcp/source/rtp_receiver_impl.cc | 11 +- .../rtp_rtcp/source/rtp_receiver_impl.h | 48 +- .../rtp_rtcp/source/rtp_receiver_strategy.h | 6 +- .../rtp_rtcp/source/rtp_receiver_video.cc | 57 +- .../rtp_rtcp/source/rtp_receiver_video.h | 35 +- .../modules/rtp_rtcp/source/rtp_rtcp.gypi | 107 - .../modules/rtp_rtcp/source/rtp_rtcp_config.h | 5 - .../modules/rtp_rtcp/source/rtp_rtcp_impl.cc | 781 +- .../modules/rtp_rtcp/source/rtp_rtcp_impl.h | 364 +- .../rtp_rtcp/source/rtp_rtcp_impl_unittest.cc | 460 +- .../modules/rtp_rtcp/source/rtp_sender.cc | 863 +- .../modules/rtp_rtcp/source/rtp_sender.h | 271 +- .../rtp_rtcp/source/rtp_sender_audio.cc | 467 +- .../rtp_rtcp/source/rtp_sender_audio.h | 84 +- .../rtp_rtcp/source/rtp_sender_unittest.cc | 553 +- .../rtp_rtcp/source/rtp_sender_video.cc | 113 +- .../rtp_rtcp/source/rtp_sender_video.h | 15 +- .../modules/rtp_rtcp/source/rtp_utility.cc | 184 +- .../modules/rtp_rtcp/source/rtp_utility.h | 26 +- .../source/vp8_partition_aggregator.cc | 93 +- .../source/vp8_partition_aggregator.h | 48 +- .../vp8_partition_aggregator_unittest.cc | 92 +- .../test/BWEStandAlone/BWEStandAlone.cc | 24 +- .../rtp_rtcp/test/BWEStandAlone/MatlabPlot.cc | 27 +- .../rtp_rtcp/test/BWEStandAlone/MatlabPlot.h | 4 +- .../test/BWEStandAlone/TestLoadGenerator.cc | 58 +- .../test/BWEStandAlone/TestLoadGenerator.h | 25 +- .../test/BWEStandAlone/TestSenderReceiver.cc | 49 +- .../test/BWEStandAlone/TestSenderReceiver.h | 57 +- .../modules/rtp_rtcp/test/bwe_standalone.gypi | 4 +- .../modules/rtp_rtcp/test/testAPI/test_api.cc | 192 +- .../modules/rtp_rtcp/test/testAPI/test_api.h | 103 +- .../rtp_rtcp/test/testAPI/test_api_audio.cc | 48 +- .../rtp_rtcp/test/testAPI/test_api_rtcp.cc | 90 +- .../rtp_rtcp/test/testAPI/test_api_video.cc | 66 +- .../modules/rtp_rtcp/test/testFec/test_fec.cc | 21 +- .../test/testFec/test_packet_masks_metrics.cc | 8 +- .../trunk/webrtc/modules/utility/BUILD.gn | 10 +- .../trunk/webrtc/modules/utility/OWNERS | 1 - .../modules/utility/interface/file_player.h | 3 +- .../modules/utility/interface/file_recorder.h | 3 +- .../utility/interface/helpers_android.h | 45 + .../interface/mock/mock_process_thread.h | 17 +- .../utility/interface/process_thread.h | 56 +- .../modules/utility/interface/rtp_dump.h | 2 +- .../webrtc/modules/utility/source/coder.cc | 11 +- .../webrtc/modules/utility/source/coder.h | 23 +- .../utility/source/file_player_impl.cc | 278 +- .../modules/utility/source/file_player_impl.h | 43 - .../utility/source/file_player_unittests.cc | 4 +- .../utility/source/file_recorder_impl.cc | 483 +- .../utility/source/file_recorder_impl.h | 93 +- .../modules/utility/source/frame_scaler.cc | 51 - .../modules/utility/source/frame_scaler.h | 48 - .../modules/utility/source/helpers_android.cc | 78 +- .../utility/source/process_thread_impl.cc | 322 +- .../utility/source/process_thread_impl.h | 72 +- .../source/process_thread_impl_unittest.cc | 304 + .../modules/utility/source/rtp_dump_impl.cc | 35 +- .../modules/utility/source/rtp_dump_impl.h | 10 +- .../modules/utility/source/utility.gypi | 54 - .../modules/utility/source/video_coder.cc | 133 - .../modules/utility/source/video_coder.h | 66 - .../utility/source/video_frames_queue.cc | 112 - .../utility/source/video_frames_queue.h | 63 - .../trunk/webrtc/modules/utility/utility.gypi | 42 + .../webrtc/modules/video_capture/BUILD.gn | 227 +- .../trunk/webrtc/modules/video_capture/OWNERS | 1 - .../android/device_info_android.cc | 5 +- .../android/device_info_android.h | 2 +- .../android/video_capture_android.cc | 19 +- .../android/video_capture_android.h | 6 +- .../modules/video_capture/device_info_impl.cc | 5 +- .../modules/video_capture/device_info_impl.h | 5 +- .../include/mock/mock_video_capture.h | 6 +- .../video_capture/include/video_capture.h | 19 +- .../include/video_capture_defines.h | 16 +- .../video_capture/ios/device_info_ios.h | 52 +- .../video_capture/ios/device_info_ios.mm | 6 +- .../ios/rtc_video_capture_ios_objc.h | 2 +- .../ios/rtc_video_capture_ios_objc.mm | 11 +- .../video_capture/ios/video_capture_ios.h | 9 +- .../video_capture/ios/video_capture_ios.mm | 2 + .../linux/video_capture_linux.cc | 32 +- .../video_capture/linux/video_capture_linux.h | 4 +- .../mac/qtkit/video_capture_qtkit.mm | 8 +- .../mac/qtkit/video_capture_qtkit_objc.h | 2 +- .../mac/qtkit/video_capture_qtkit_objc.mm | 17 +- .../test/video_capture_unittest.cc | 156 +- .../modules/video_capture/video_capture.gypi | 244 +- .../video_capture/video_capture_config.h | 1 - .../video_capture/video_capture_impl.cc | 142 +- .../video_capture/video_capture_impl.h | 41 +- .../video_capture/video_capture_tests.isolate | 8 - .../webrtc/modules/video_coding/BUILD.gn | 51 +- .../trunk/webrtc/modules/video_coding/OWNERS | 1 - .../webrtc/modules/video_coding/codecs/OWNERS | 1 - .../codecs/i420/main/interface/i420.h | 54 +- .../codecs/i420/main/source/i420.cc | 29 +- .../codecs/i420/main/source/i420.gypi | 2 +- .../mock/mock_video_codec_interface.h | 6 +- .../codecs/interface/video_codec_interface.h | 1 - .../codecs/test/packet_manipulator.cc | 5 +- .../codecs/test/packet_manipulator.h | 9 +- .../test/packet_manipulator_unittest.cc | 8 +- .../test/predictive_packet_manipulator.h | 2 +- .../modules/video_coding/codecs/test/stats.cc | 29 +- .../modules/video_coding/codecs/test/stats.h | 4 +- .../codecs/test/videoprocessor.cc | 74 +- .../video_coding/codecs/test/videoprocessor.h | 30 +- .../test/videoprocessor_integrationtest.cc | 53 +- .../video_coding/codecs/test_framework/OWNERS | 5 - .../codecs/test_framework/benchmark.cc | 304 - .../codecs/test_framework/benchmark.h | 39 - .../codecs/test_framework/exportfig.m | 500 - .../test_framework/normal_async_test.cc | 593 - .../codecs/test_framework/normal_async_test.h | 186 - .../codecs/test_framework/normal_test.cc | 264 - .../codecs/test_framework/normal_test.h | 45 - .../codecs/test_framework/packet_loss_test.cc | 259 - .../codecs/test_framework/packet_loss_test.h | 60 - .../codecs/test_framework/plotBenchmark.m | 427 - .../codecs/test_framework/test.cc | 169 - .../video_coding/codecs/test_framework/test.h | 77 - .../codecs/test_framework/test_framework.gypi | 43 - .../codecs/test_framework/unit_test.cc | 820 - .../codecs/test_framework/unit_test.h | 106 - .../codecs/test_framework/video_source.cc | 425 - .../codecs/test_framework/video_source.h | 108 - .../codecs/tools/video_codecs_tools.gypi | 3 +- .../codecs/tools/video_quality_measurement.cc | 28 +- .../codecs/vp8/default_temporal_layers.cc | 3 + .../codecs/vp8/reference_picture_selection.cc | 9 +- .../codecs/vp8/reference_picture_selection.h | 8 +- .../codecs/vp8/screenshare_layers.cc | 177 + .../codecs/vp8/screenshare_layers.h | 68 + .../codecs/vp8/screenshare_layers_unittest.cc | 290 + .../codecs/vp8/simulcast_encoder_adapter.cc | 497 + .../codecs/vp8/simulcast_encoder_adapter.h | 107 + .../vp8/simulcast_encoder_adapter_unittest.cc | 301 + .../codecs/vp8/simulcast_unittest.cc | 95 + .../codecs/vp8/simulcast_unittest.h | 1004 + .../video_coding/codecs/vp8/temporal_layers.h | 5 +- .../codecs/vp8/test/vp8_impl_unittest.cc | 203 +- .../modules/video_coding/codecs/vp8/vp8.gyp | 28 +- .../video_coding/codecs/vp8/vp8_factory.cc | 21 +- .../video_coding/codecs/vp8/vp8_factory.h | 35 + .../video_coding/codecs/vp8/vp8_impl.cc | 1269 +- .../video_coding/codecs/vp8/vp8_impl.h | 107 +- .../codecs/vp8/vp8_sequence_coder.cc | 26 +- .../modules/video_coding/codecs/vp9/vp9.gyp | 20 +- .../video_coding/codecs/vp9/vp9_dummy_impl.cc | 19 + .../video_coding/codecs/vp9/vp9_impl.cc | 65 +- .../video_coding/codecs/vp9/vp9_impl.h | 54 +- .../main/interface/video_coding.h | 110 +- .../main/interface/video_coding_defines.h | 28 +- .../main/source/codec_database.cc | 135 +- .../video_coding/main/source/codec_database.h | 28 +- .../main/source/decoding_state.cc | 2 +- .../video_coding/main/source/encoded_frame.cc | 53 +- .../video_coding/main/source/encoded_frame.h | 12 +- .../video_coding/main/source/er_tables_xor.h | 38742 ---------------- .../video_coding/main/source/frame_buffer.cc | 33 +- .../video_coding/main/source/frame_buffer.h | 5 - .../main/source/generic_decoder.cc | 5 +- .../main/source/generic_decoder.h | 1 + .../main/source/generic_encoder.cc | 244 +- .../main/source/generic_encoder.h | 36 +- .../video_coding/main/source/jitter_buffer.cc | 424 +- .../video_coding/main/source/jitter_buffer.h | 100 +- .../main/source/jitter_buffer_unittest.cc | 140 +- .../main/source/jitter_estimator.cc | 2 +- .../main/source/jitter_estimator.h | 2 +- .../main/source/media_opt_util.cc | 261 +- .../video_coding/main/source/media_opt_util.h | 53 +- .../main/source/media_optimization.cc | 40 +- .../main/source/media_optimization.h | 33 +- .../source/media_optimization_unittest.cc | 18 +- .../main/source/nack_fec_tables.h | 5 +- .../video_coding/main/source/packet.cc | 12 +- .../modules/video_coding/main/source/packet.h | 6 +- .../video_coding/main/source/qm_select.cc | 7 +- .../video_coding/main/source/qm_select.h | 7 +- .../main/source/qm_select_unittest.cc | 20 +- .../video_coding/main/source/receiver.cc | 111 +- .../video_coding/main/source/receiver.h | 26 +- .../main/source/receiver_unittest.cc | 8 +- .../video_coding/main/source/rtt_filter.cc | 12 +- .../video_coding/main/source/rtt_filter.h | 16 +- .../video_coding/main/source/session_info.cc | 59 +- .../video_coding/main/source/session_info.h | 20 +- .../main/source/session_info_unittest.cc | 553 +- .../video_coding/main/source/timing.cc | 43 +- .../modules/video_coding/main/source/timing.h | 11 +- .../main/source/timing_unittest.cc | 5 +- .../main/source/video_coding.gypi | 85 - .../main/source/video_coding_impl.cc | 267 +- .../main/source/video_coding_impl.h | 65 +- .../video_coding_robustness_unittest.cc | 96 +- .../main/source/video_coding_test.gypi | 62 - .../main/source/video_receiver.cc | 191 +- .../main/source/video_receiver_unittest.cc | 23 +- .../video_coding/main/source/video_sender.cc | 207 +- .../main/source/video_sender_unittest.cc | 57 +- .../main/test/codec_database_test.cc | 411 - .../main/test/codec_database_test.h | 51 - .../main/test/generic_codec_test.cc | 558 - .../main/test/generic_codec_test.h | 110 - .../main/test/jitter_estimate_test.h | 106 - .../video_coding/main/test/media_opt_test.cc | 557 - .../video_coding/main/test/media_opt_test.h | 99 - .../video_coding/main/test/mt_rx_tx_test.cc | 381 - .../video_coding/main/test/mt_test_common.cc | 148 - .../video_coding/main/test/mt_test_common.h | 87 - .../video_coding/main/test/normal_test.cc | 407 - .../video_coding/main/test/normal_test.h | 149 - .../main/test/quality_modes_test.cc | 580 - .../main/test/quality_modes_test.h | 111 - .../video_coding/main/test/receiver_tests.h | 16 +- .../video_coding/main/test/rtp_player.cc | 94 +- .../video_coding/main/test/rtp_player.h | 2 +- .../video_coding/main/test/test_callbacks.cc | 484 - .../video_coding/main/test/test_callbacks.h | 262 - .../video_coding/main/test/test_macros.h | 45 - .../video_coding/main/test/test_util.cc | 20 +- .../video_coding/main/test/test_util.h | 44 +- .../video_coding/main/test/tester_main.cc | 62 +- .../main/test/vcm_payload_sink_factory.cc | 39 +- .../main/test/vcm_payload_sink_factory.h | 10 +- .../video_coding/main/test/video_rtp_play.cc | 7 +- .../main/test/video_rtp_play_mt.cc | 143 - .../video_coding/main/test/video_source.cc | 202 - .../video_coding/main/test/video_source.h | 2 +- .../video_coding/utility/frame_dropper.cc | 2 +- .../utility/include/frame_dropper.h | 4 +- .../utility/include/mock/mock_frame_dropper.h | 2 +- .../utility/video_coding_utility.gyp | 2 +- .../modules/video_coding/video_coding.gypi | 85 + .../video_coding/video_coding_test.gypi | 35 + .../webrtc/modules/video_processing/BUILD.gn | 2 +- .../webrtc/modules/video_processing/OWNERS | 1 - .../main/interface/video_processing.h | 4 +- .../main/source/brightness_detection.cc | 8 +- .../main/source/brightness_detection.h | 3 - .../main/source/content_analysis.h | 4 +- .../main/source/deflickering.cc | 8 +- .../main/source/deflickering.h | 4 - .../main/source/frame_preprocessor.cc | 8 +- .../main/source/frame_preprocessor.h | 3 - .../main/source/video_processing_impl.cc | 20 +- .../main/source/video_processing_impl.h | 42 +- .../unit_test/brightness_detection_test.cc | 17 +- .../test/unit_test/color_enhancement_test.cc | 27 +- .../test/unit_test/content_metrics_test.cc | 7 +- .../main/test/unit_test/deflickering_test.cc | 8 +- .../unit_test/video_processing_unittest.cc | 324 +- .../unit_test/video_processing_unittest.h | 2 +- .../{main/source => }/video_processing.gypi | 46 +- .../webrtc/modules/video_render/BUILD.gn | 224 +- .../trunk/webrtc/modules/video_render/OWNERS | 1 - .../android/video_render_android_impl.cc | 37 +- .../android/video_render_android_impl.h | 6 +- .../video_render_android_native_opengl2.cc | 4 +- .../video_render_android_native_opengl2.h | 2 +- .../video_render_android_surface_view.cc | 4 +- .../video_render_android_surface_view.h | 2 +- .../external/video_render_external_impl.cc | 16 +- .../external/video_render_external_impl.h | 5 +- .../modules/video_render/i_video_render.h | 6 +- .../video_render/include/video_render.h | 23 +- .../include/video_render_defines.h | 10 +- .../video_render/incoming_video_stream.cc | 108 +- .../video_render/incoming_video_stream.h | 22 +- .../modules/video_render/ios/open_gles20.mm | 1 + .../ios/video_render_ios_channel.h | 4 +- .../ios/video_render_ios_channel.mm | 5 +- .../ios/video_render_ios_gles20.h | 10 +- .../ios/video_render_ios_gles20.mm | 32 +- .../video_render/ios/video_render_ios_impl.h | 35 +- .../video_render/ios/video_render_ios_impl.mm | 7 - .../video_render/ios/video_render_ios_view.mm | 2 +- .../linux/video_render_linux_impl.cc | 8 - .../linux/video_render_linux_impl.h | 2 - .../video_render/linux/video_x11_channel.cc | 2 +- .../video_render/linux/video_x11_channel.h | 2 +- .../video_render/mac/video_render_agl.cc | 67 +- .../video_render/mac/video_render_agl.h | 11 +- .../mac/video_render_mac_carbon_impl.cc | 17 - .../mac/video_render_mac_carbon_impl.h | 2 - .../mac/video_render_mac_cocoa_impl.h | 2 - .../mac/video_render_mac_cocoa_impl.mm | 15 - .../video_render/mac/video_render_nsopengl.h | 20 +- .../video_render/mac/video_render_nsopengl.mm | 41 +- .../video_render/test/testAPI/testAPI.cc | 2 +- .../modules/video_render/video_render.gypi | 223 +- .../video_render/video_render_frames.cc | 117 +- .../video_render/video_render_frames.h | 16 +- .../modules/video_render/video_render_impl.cc | 72 +- .../modules/video_render/video_render_impl.h | 15 +- .../video_render_internal_impl.cc | 72 +- .../video_render/video_render_tests.isolate | 8 - .../windows/video_render_direct3d9.cc | 35 +- .../windows/video_render_direct3d9.h | 7 +- .../windows/video_render_windows_impl.cc | 10 +- .../windows/video_render_windows_impl.h | 3 - media/webrtc/trunk/webrtc/overrides/OWNERS | 1 - .../webrtc/overrides/webrtc/base/arraysize.h | 20 + .../webrtc/overrides/webrtc/base/basictypes.h | 13 +- .../webrtc/base/diagnostic_logging.h | 156 + .../webrtc/overrides/webrtc/base/logging.cc | 30 +- .../webrtc/overrides/webrtc/base/logging.h | 142 +- media/webrtc/trunk/webrtc/p2p/OWNERS | 12 + .../webrtc/p2p/base/asyncstuntcpsocket.cc | 153 + .../webrtc/p2p/base/asyncstuntcpsocket.h | 50 + .../p2p/base/asyncstuntcpsocket_unittest.cc | 263 + .../p2p/base/basicpacketsocketfactory.cc | 205 + .../p2p/base/basicpacketsocketfactory.h | 58 + .../webrtc/trunk/webrtc/p2p/base/candidate.h | 244 + media/webrtc/trunk/webrtc/p2p/base/common.h | 20 + .../webrtc/trunk/webrtc/p2p/base/constants.cc | 65 + .../webrtc/trunk/webrtc/p2p/base/constants.h | 67 + .../trunk/webrtc/p2p/base/dtlstransport.h | 239 + .../webrtc/p2p/base/dtlstransportchannel.cc | 631 + .../webrtc/p2p/base/dtlstransportchannel.h | 253 + .../p2p/base/dtlstransportchannel_unittest.cc | 841 + .../trunk/webrtc/p2p/base/fakesession.h | 508 + .../trunk/webrtc/p2p/base/p2ptransport.cc | 44 + .../trunk/webrtc/p2p/base/p2ptransport.h | 39 + .../webrtc/p2p/base/p2ptransportchannel.cc | 1335 + .../webrtc/p2p/base/p2ptransportchannel.h | 250 + .../p2p/base/p2ptransportchannel_unittest.cc | 1804 + .../webrtc/p2p/base/packetsocketfactory.h | 58 + media/webrtc/trunk/webrtc/p2p/base/port.cc | 1494 + media/webrtc/trunk/webrtc/p2p/base/port.h | 626 + .../trunk/webrtc/p2p/base/port_unittest.cc | 2505 + .../trunk/webrtc/p2p/base/portallocator.cc | 95 + .../trunk/webrtc/p2p/base/portallocator.h | 198 + .../p2p/base/portallocatorsessionproxy.cc | 222 + .../p2p/base/portallocatorsessionproxy.h | 106 + .../portallocatorsessionproxy_unittest.cc | 146 + .../trunk/webrtc/p2p/base/portinterface.h | 126 + .../webrtc/trunk/webrtc/p2p/base/portproxy.cc | 163 + .../webrtc/trunk/webrtc/p2p/base/portproxy.h | 87 + .../webrtc/trunk/webrtc/p2p/base/pseudotcp.cc | 1278 + .../webrtc/trunk/webrtc/p2p/base/pseudotcp.h | 241 + .../webrtc/p2p/base/pseudotcp_unittest.cc | 841 + .../trunk/webrtc/p2p/base/rawtransport.cc | 43 + .../trunk/webrtc/p2p/base/rawtransport.h | 46 + .../webrtc/p2p/base/rawtransportchannel.cc | 260 + .../webrtc/p2p/base/rawtransportchannel.h | 198 + .../webrtc/trunk/webrtc/p2p/base/relayport.cc | 822 + .../webrtc/trunk/webrtc/p2p/base/relayport.h | 109 + .../webrtc/p2p/base/relayport_unittest.cc | 272 + .../trunk/webrtc/p2p/base/relayserver.cc | 746 + .../trunk/webrtc/p2p/base/relayserver.h | 235 + .../webrtc/p2p/base/relayserver_unittest.cc | 529 + media/webrtc/trunk/webrtc/p2p/base/session.cc | 849 + media/webrtc/trunk/webrtc/p2p/base/session.h | 459 + .../webrtc/p2p/base/sessiondescription.cc | 220 + .../webrtc/p2p/base/sessiondescription.h | 185 + .../stringdigest.h => p2p/base/sessionid.h} | 13 +- media/webrtc/trunk/webrtc/p2p/base/stun.cc | 916 + media/webrtc/trunk/webrtc/p2p/base/stun.h | 633 + .../trunk/webrtc/p2p/base/stun_unittest.cc | 1446 + .../webrtc/trunk/webrtc/p2p/base/stunport.cc | 459 + media/webrtc/trunk/webrtc/p2p/base/stunport.h | 257 + .../webrtc/p2p/base/stunport_unittest.cc | 284 + .../trunk/webrtc/p2p/base/stunrequest.cc | 203 + .../trunk/webrtc/p2p/base/stunrequest.h | 125 + .../webrtc/p2p/base/stunrequest_unittest.cc | 203 + .../trunk/webrtc/p2p/base/stunserver.cc | 99 + .../webrtc/trunk/webrtc/p2p/base/stunserver.h | 66 + .../webrtc/p2p/base/stunserver_unittest.cc | 112 + media/webrtc/trunk/webrtc/p2p/base/tcpport.cc | 330 + media/webrtc/trunk/webrtc/p2p/base/tcpport.h | 141 + .../trunk/webrtc/p2p/base/testrelayserver.h | 101 + .../trunk/webrtc/p2p/base/teststunserver.h | 58 + .../trunk/webrtc/p2p/base/testturnserver.h | 116 + .../webrtc/trunk/webrtc/p2p/base/transport.cc | 950 + .../webrtc/trunk/webrtc/p2p/base/transport.h | 452 + .../webrtc/p2p/base/transport_unittest.cc | 323 + .../trunk/webrtc/p2p/base/transportchannel.cc | 43 + .../trunk/webrtc/p2p/base/transportchannel.h | 158 + .../webrtc/p2p/base/transportchannelimpl.h | 110 + .../webrtc/p2p/base/transportchannelproxy.cc | 276 + .../webrtc/p2p/base/transportchannelproxy.h | 96 + .../webrtc/p2p/base/transportdescription.cc | 55 + .../webrtc/p2p/base/transportdescription.h | 171 + .../p2p/base/transportdescriptionfactory.cc | 160 + .../p2p/base/transportdescriptionfactory.h | 66 + .../transportdescriptionfactory_unittest.cc | 365 + .../trunk/webrtc/p2p/base/transportinfo.h | 43 + .../webrtc/trunk/webrtc/p2p/base/turnport.cc | 1263 + media/webrtc/trunk/webrtc/p2p/base/turnport.h | 245 + .../webrtc/p2p/base/turnport_unittest.cc | 804 + .../trunk/webrtc/p2p/base/turnserver.cc | 945 + .../webrtc/trunk/webrtc/p2p/base/turnserver.h | 272 + media/webrtc/trunk/webrtc/p2p/base/udpport.h | 17 + .../webrtc/p2p/client/autoportallocator.h | 50 + .../webrtc/p2p/client/basicportallocator.cc | 1220 + .../webrtc/p2p/client/basicportallocator.h | 241 + .../webrtc/p2p/client/connectivitychecker.cc | 532 + .../webrtc/p2p/client/connectivitychecker.h | 281 + .../client/connectivitychecker_unittest.cc | 367 + .../webrtc/p2p/client/fakeportallocator.h | 118 + .../webrtc/p2p/client/httpportallocator.cc | 326 + .../webrtc/p2p/client/httpportallocator.h | 173 + .../p2p/client/portallocator_unittest.cc | 1129 + .../trunk/webrtc/p2p/client/socketmonitor.cc | 96 + .../trunk/webrtc/p2p/client/socketmonitor.h | 62 + media/webrtc/trunk/webrtc/p2p/p2p.gyp | 117 + media/webrtc/trunk/webrtc/p2p/p2p_tests.gypi | 43 + media/webrtc/trunk/webrtc/sound/OWNERS | 13 + .../trunk/webrtc/sound/alsasoundsystem.cc | 745 + .../trunk/webrtc/sound/alsasoundsystem.h | 103 + .../trunk/webrtc/sound/alsasymboltable.cc | 20 + .../trunk/webrtc/sound/alsasymboltable.h | 49 + .../sound/automaticallychosensoundsystem.h | 88 + ...automaticallychosensoundsystem_unittest.cc | 197 + .../trunk/webrtc/sound/linuxsoundsystem.cc | 25 + .../trunk/webrtc/sound/linuxsoundsystem.h | 41 + .../trunk/webrtc/sound/nullsoundsystem.cc | 157 + .../trunk/webrtc/sound/nullsoundsystem.h | 53 + .../webrtc/sound/nullsoundsystemfactory.cc | 32 + .../webrtc/sound/nullsoundsystemfactory.h | 33 + .../trunk/webrtc/sound/platformsoundsystem.cc | 31 + .../trunk/webrtc/sound/platformsoundsystem.h | 23 + .../sound/platformsoundsystemfactory.cc | 40 + .../webrtc/sound/platformsoundsystemfactory.h | 35 + .../webrtc/sound/pulseaudiosoundsystem.cc | 1541 + .../webrtc/sound/pulseaudiosoundsystem.h | 177 + .../webrtc/sound/pulseaudiosymboltable.cc | 24 + .../webrtc/sound/pulseaudiosymboltable.h | 87 + media/webrtc/trunk/webrtc/sound/sound.gyp | 55 + .../trunk/webrtc/sound/sound_tests.gypi | 23 + .../trunk/webrtc/sound/sounddevicelocator.h | 54 + .../webrtc/sound/soundinputstreaminterface.h | 68 + .../webrtc/sound/soundoutputstreaminterface.h | 72 + .../trunk/webrtc/sound/soundsystemfactory.h | 27 + .../webrtc/sound/soundsysteminterface.cc | 29 + .../trunk/webrtc/sound/soundsysteminterface.h | 112 + .../trunk/webrtc/sound/soundsystemproxy.cc | 47 + .../trunk/webrtc/sound/soundsystemproxy.h | 47 + media/webrtc/trunk/webrtc/supplement.gypi | 11 +- .../trunk/webrtc/system_wrappers/BUILD.gn | 41 +- .../trunk/webrtc/system_wrappers/OWNERS | 1 - .../system_wrappers/cpu_features_chromium.gyp | 26 + .../system_wrappers/cpu_features_webrtc.gyp | 38 + .../system_wrappers/interface/asm_defines.h | 4 + .../webrtc/system_wrappers/interface/clock.h | 15 +- .../interface/compile_assert.h | 90 - .../interface/compile_assert_c.h | 6 +- .../system_wrappers/interface/data_log_impl.h | 8 +- .../system_wrappers/interface/event_tracer.h | 46 +- .../system_wrappers/interface/event_wrapper.h | 3 - .../system_wrappers/interface/field_trial.h | 2 +- .../interface/field_trial_default.h | 26 + .../system_wrappers/interface/file_wrapper.h | 13 +- .../system_wrappers/interface/metrics.h | 8 +- .../system_wrappers/interface/scoped_ptr.h | 615 - .../system_wrappers/interface/scoped_vector.h | 2 +- .../system_wrappers/interface/template_util.h | 114 - .../interface/thread_wrapper.h | 65 +- .../webrtc/system_wrappers/interface/trace.h | 10 +- .../system_wrappers/interface/trace_event.h | 905 +- .../system_wrappers/interface/utf_util_win.h | 6 +- .../source/aligned_malloc_unittest.cc | 6 +- .../system_wrappers/source/atomic32_win.cc | 5 +- .../webrtc/system_wrappers/source/clock.cc | 225 +- .../system_wrappers/source/clock_unittest.cc | 3 +- .../source/condition_variable_posix.h | 12 +- .../source/condition_variable_unittest.cc | 14 +- .../source/cpu_features_android.c | 2 +- .../source/critical_section_posix.h | 6 +- .../source/critical_section_unittest.cc | 17 +- .../webrtc/system_wrappers/source/data_log.cc | 23 +- .../source/droid-cpu-features.c | 2 +- .../system_wrappers/source/event_posix.cc | 160 +- .../system_wrappers/source/event_posix.h | 20 +- .../system_wrappers/source/event_tracer.cc | 52 +- .../source/event_tracer_unittest.cc | 74 +- .../system_wrappers/source/event_win.cc | 4 - .../webrtc/system_wrappers/source/event_win.h | 13 - .../source/field_trial_default.cc | 44 +- .../system_wrappers/source/file_impl.cc | 20 +- .../webrtc/system_wrappers/source/file_impl.h | 41 +- .../source/logging_unittest.cc | 6 +- .../webrtc/system_wrappers/source/move.h | 237 - .../system_wrappers/source/rw_lock_generic.h | 10 +- .../system_wrappers/source/rw_lock_posix.h | 10 +- .../source/scoped_vector_unittest.cc | 8 +- .../source/set_thread_name_win.h | 108 - .../source/system_wrappers.gyp | 274 - .../webrtc/system_wrappers/source/thread.cc | 28 +- .../system_wrappers/source/thread_posix.cc | 392 +- .../system_wrappers/source/thread_posix.h | 56 +- .../system_wrappers/source/thread_unittest.cc | 17 +- .../system_wrappers/source/thread_win.cc | 346 +- .../system_wrappers/source/thread_win.h | 61 +- .../system_wrappers/source/trace_impl.cc | 383 +- .../system_wrappers/source/trace_impl.h | 42 +- .../system_wrappers/source/trace_posix.cc | 1 - .../system_wrappers/source/trace_posix.h | 7 +- .../system_wrappers/source/trace_win.cc | 1 - .../system_wrappers/system_wrappers.gyp | 237 + .../{source => }/system_wrappers_tests.gyp | 48 +- .../system_wrappers_unittests.isolate | 8 - media/webrtc/trunk/webrtc/test/BUILD.gn | 36 +- media/webrtc/trunk/webrtc/test/call_test.cc | 7 +- media/webrtc/trunk/webrtc/test/call_test.h | 10 +- .../webrtc/test/channel_transport/OWNERS | 2 - .../channel_transport/channel_transport.cc | 8 +- .../include/channel_transport.h | 28 +- .../channel_transport/traffic_control_win.cc | 11 +- .../channel_transport/traffic_control_win.h | 3 - .../udp_socket2_manager_win.cc | 46 +- .../udp_socket2_manager_win.h | 8 +- .../test/channel_transport/udp_socket2_win.cc | 32 +- .../test/channel_transport/udp_socket2_win.h | 46 +- .../udp_socket_manager_posix.cc | 24 +- .../udp_socket_manager_posix.h | 15 +- .../udp_socket_manager_wrapper.h | 2 - .../channel_transport/udp_socket_posix.cc | 11 +- .../test/channel_transport/udp_socket_posix.h | 42 +- .../channel_transport/udp_socket_wrapper.h | 7 +- .../udp_socket_wrapper_unittest.cc | 1 - .../test/channel_transport/udp_transport.h | 14 +- .../channel_transport/udp_transport_impl.cc | 28 +- .../channel_transport/udp_transport_impl.h | 165 +- .../udp_transport_unittest.cc | 4 +- .../test/configurable_frame_size_encoder.cc | 8 +- .../test/configurable_frame_size_encoder.h | 39 +- .../trunk/webrtc/test/direct_transport.cc | 17 +- .../trunk/webrtc/test/direct_transport.h | 12 +- .../trunk/webrtc/test/fake_audio_device.cc | 8 +- .../trunk/webrtc/test/fake_audio_device.h | 22 +- media/webrtc/trunk/webrtc/test/fake_common.h | 20 +- media/webrtc/trunk/webrtc/test/fake_decoder.h | 45 +- .../webrtc/trunk/webrtc/test/fake_encoder.cc | 56 +- media/webrtc/trunk/webrtc/test/fake_encoder.h | 50 +- .../trunk/webrtc/test/fake_network_pipe.cc | 8 +- .../trunk/webrtc/test/fake_network_pipe.h | 6 +- .../webrtc/test/fake_network_pipe_unittest.cc | 18 +- .../trunk/webrtc/test/frame_generator.cc | 119 +- .../trunk/webrtc/test/frame_generator.h | 16 +- .../webrtc/test/frame_generator_capturer.cc | 27 +- .../webrtc/test/frame_generator_capturer.h | 21 +- .../webrtc/test/frame_generator_unittest.cc | 152 + .../webrtc/trunk/webrtc/test/gl/gl_renderer.h | 4 +- media/webrtc/trunk/webrtc/test/histogram.cc | 49 + media/webrtc/trunk/webrtc/test/histogram.h | 27 + .../trunk/webrtc/test/linux/glx_renderer.h | 5 +- .../webrtc/test/mac/video_renderer_mac.h | 3 +- media/webrtc/trunk/webrtc/test/manual/README | 8 - .../trunk/webrtc/test/manual/adapter.js | 51 - .../webrtc/test/manual/audio-and-video.html | 47 - .../webrtc/test/manual/iframe-apprtc.html | 20 - .../webrtc/test/manual/iframe-video.html | 19 - .../webrtc/test/manual/multiple-audio.html | 56 - .../webrtc/test/manual/multiple-video.html | 72 - .../webrtc/test/manual/single-audio.html | 44 - .../webrtc/test/manual/single-video.html | 45 - .../webrtc/test/manual/two-video-devices.html | 51 - media/webrtc/trunk/webrtc/test/metrics.gyp | 2 +- .../webrtc/trunk/webrtc/test/mock_transport.h | 4 +- .../webrtc/trunk/webrtc/test/null_transport.h | 4 +- .../trunk/webrtc/test/rtcp_packet_parser.cc | 5 +- .../trunk/webrtc/test/rtcp_packet_parser.h | 2 +- .../trunk/webrtc/test/rtp_file_reader.cc | 129 +- .../trunk/webrtc/test/rtp_file_reader.h | 34 +- .../webrtc/test/rtp_file_reader_unittest.cc | 12 +- .../trunk/webrtc/test/rtp_file_writer.cc | 109 + .../trunk/webrtc/test/rtp_file_writer.h | 33 + .../webrtc/test/rtp_file_writer_unittest.cc | 75 + .../trunk/webrtc/test/rtp_rtcp_observer.h | 11 +- media/webrtc/trunk/webrtc/test/test.gyp | 30 +- media/webrtc/trunk/webrtc/test/test_suite.h | 4 +- .../test/test_support_unittests.isolate | 8 - .../webrtc/test/testsupport/fileutils.cc | 4 +- .../webrtc/test/testsupport/frame_reader.h | 12 +- .../webrtc/test/testsupport/frame_writer.h | 10 +- .../test/testsupport/metrics/video_metrics.cc | 8 +- .../webrtc/test/testsupport/packet_reader.cc | 19 +- .../webrtc/test/testsupport/packet_reader.h | 13 +- .../testsupport/packet_reader_unittest.cc | 9 +- .../webrtc/test/testsupport/trace_to_stderr.h | 6 +- .../webrtc/test/testsupport/unittest_utils.h | 4 +- .../webrtc/trunk/webrtc/test/vcm_capturer.cc | 4 +- media/webrtc/trunk/webrtc/test/vcm_capturer.h | 11 +- .../trunk/webrtc/test/video_renderer.cc | 5 +- .../trunk/webrtc/test/webrtc_test_common.gyp | 7 +- .../trunk/webrtc/test/win/d3d_renderer.h | 5 +- .../trunk/webrtc/tools/agc/activity_metric.cc | 384 + .../trunk/webrtc/tools/agc/agc_harness.cc | 283 + .../trunk/webrtc/tools/agc/agc_manager.cc | 252 + .../trunk/webrtc/tools/agc/agc_manager.h | 81 + .../tools/agc/agc_manager_integrationtest.cc | 123 + .../webrtc/tools/agc/agc_manager_unittest.cc | 736 + .../webrtc/trunk/webrtc/tools/agc/agc_test.cc | 155 + .../webrtc/trunk/webrtc/tools/agc/fake_agc.h | 46 + .../trunk/webrtc/tools/agc/test_utils.cc | 63 + .../trunk/webrtc/tools/agc/test_utils.h | 28 + .../trunk/webrtc/tools/converter/converter.h | 4 +- .../e2e_quality/audio/audio_e2e_harness.cc | 4 +- .../tools/e2e_quality/audio/perf/__init__.py | 0 .../e2e_quality/audio/perf/perf_utils.py | 31 + .../force_mic_volume_max.cc | 2 +- .../frame_analyzer/video_quality_analysis.cc | 2 +- .../frame_analyzer/video_quality_analysis.h | 4 +- .../tools/frame_editing/frame_editing_lib.cc | 8 +- .../frame_editing/frame_editing_unittest.cc | 17 +- .../simple_command_line_parser_unittest.cc | 4 +- media/webrtc/trunk/webrtc/tools/tools.gyp | 74 +- .../webrtc/tools/tools_unittests.isolate | 6 +- media/webrtc/trunk/webrtc/typedefs.h | 42 +- media/webrtc/trunk/webrtc/video/BUILD.gn | 5 +- .../webrtc/video/bitrate_estimator_tests.cc | 33 +- media/webrtc/trunk/webrtc/video/call.cc | 184 +- .../trunk/webrtc/video/call_perf_tests.cc | 153 +- .../video/encoded_frame_callback_adapter.cc | 5 +- .../video/encoded_frame_callback_adapter.h | 2 +- .../trunk/webrtc/video/end_to_end_tests.cc | 1013 +- media/webrtc/trunk/webrtc/video/full_stack.cc | 464 +- media/webrtc/trunk/webrtc/video/loopback.cc | 182 +- media/webrtc/trunk/webrtc/video/loopback.h | 57 + .../webrtc/trunk/webrtc/video/rampup_tests.cc | 56 +- .../webrtc/trunk/webrtc/video/rampup_tests.h | 47 +- .../webrtc/video/receive_statistics_proxy.cc | 92 +- .../webrtc/video/receive_statistics_proxy.h | 67 +- media/webrtc/trunk/webrtc/video/replay.cc | 87 +- .../webrtc/video/screenshare_loopback.cc | 177 + .../webrtc/video/send_statistics_proxy.cc | 139 +- .../webrtc/video/send_statistics_proxy.h | 92 +- .../video/send_statistics_proxy_unittest.cc | 178 +- .../trunk/webrtc/video/transport_adapter.cc | 12 +- .../trunk/webrtc/video/transport_adapter.h | 10 +- .../trunk/webrtc/video/video_loopback.cc | 135 + .../webrtc/video/video_receive_stream.cc | 210 +- .../trunk/webrtc/video/video_receive_stream.h | 29 +- .../trunk/webrtc/video/video_send_stream.cc | 231 +- .../trunk/webrtc/video/video_send_stream.h | 24 +- .../webrtc/video/video_send_stream_tests.cc | 990 +- media/webrtc/trunk/webrtc/video_encoder.h | 12 +- .../webrtc/trunk/webrtc/video_engine/BUILD.gn | 11 +- media/webrtc/trunk/webrtc/video_engine/OWNERS | 1 - .../video_engine/browser_capture_impl.h | 2 +- .../trunk/webrtc/video_engine/call_stats.cc | 104 +- .../trunk/webrtc/video_engine/call_stats.h | 29 +- .../video_engine/call_stats_unittest.cc | 86 +- .../video_engine/desktop_capture_impl.cc | 98 +- .../video_engine/desktop_capture_impl.h | 70 +- .../video_engine/encoder_state_feedback.h | 6 +- .../encoder_state_feedback_unittest.cc | 30 +- .../webrtc/video_engine/include/vie_base.h | 33 +- .../webrtc/video_engine/include/vie_capture.h | 55 +- .../webrtc/video_engine/include/vie_codec.h | 2 + .../video_engine/include/vie_external_codec.h | 2 +- .../video_engine/include/vie_image_process.h | 2 +- .../webrtc/video_engine/include/vie_network.h | 18 +- .../webrtc/video_engine/include/vie_render.h | 19 +- .../video_engine/include/vie_rtp_rtcp.h | 106 +- .../mock/mock_vie_frame_provider_base.h | 5 +- .../video_engine/overuse_frame_detector.cc | 67 +- .../video_engine/overuse_frame_detector.h | 104 +- .../overuse_frame_detector_unittest.cc | 76 +- .../webrtc/video_engine/payload_router.cc | 101 + .../webrtc/video_engine/payload_router.h | 85 + .../video_engine/payload_router_unittest.cc | 209 + .../webrtc/video_engine/report_block_stats.cc | 111 + .../webrtc/video_engine/report_block_stats.h | 62 + .../report_block_stats_unittest.cc | 146 + .../vie_extended_integration_test.cc | 5 - .../auto_test/automated/vie_network_test.cc | 22 +- .../test/auto_test/interface/vie_autotest.h | 8 +- .../interface/vie_autotest_windows.h | 4 +- .../primitives/framedrop_primitives.cc | 24 +- .../primitives/framedrop_primitives.h | 14 +- .../primitives/general_primitives.cc | 6 + .../auto_test/primitives/general_primitives.h | 8 +- .../test/auto_test/source/vie_autotest.cc | 11 +- .../auto_test/source/vie_autotest_android.cc | 5 +- .../auto_test/source/vie_autotest_base.cc | 1 + .../auto_test/source/vie_autotest_capture.cc | 26 +- .../auto_test/source/vie_autotest_codec.cc | 21 +- .../source/vie_autotest_custom_call.cc | 20 +- .../source/vie_autotest_image_process.cc | 15 +- .../auto_test/source/vie_autotest_linux.cc | 1 - .../auto_test/source/vie_autotest_loopback.cc | 16 +- .../auto_test/source/vie_autotest_record.cc | 5 +- .../auto_test/source/vie_autotest_render.cc | 41 +- .../auto_test/source/vie_autotest_rtp_rtcp.cc | 151 +- .../test/auto_test/source/vie_autotest_win.cc | 20 +- .../test/auto_test/vie_auto_test.gypi | 5 +- .../test/auto_test/vie_auto_test.isolate | 8 - .../libvietest/helpers/vie_fake_camera.cc | 10 +- .../helpers/vie_file_capture_device.cc | 11 +- .../helpers/vie_to_file_renderer.cc | 85 +- .../test/libvietest/include/tb_I420_codec.h | 49 +- .../include/tb_external_transport.h | 10 +- .../libvietest/include/tb_video_channel.h | 4 +- .../include/vie_external_render_filter.h | 2 +- .../test/libvietest/include/vie_fake_camera.h | 4 +- .../libvietest/include/vie_to_file_renderer.h | 24 +- .../test/libvietest/libvietest.gypi | 3 +- .../test/libvietest/testbed/tb_I420_codec.cc | 22 +- .../testbed/tb_external_transport.cc | 48 +- .../video_engine/video_engine_core.gypi | 9 +- .../video_engine_core_unittests.isolate | 8 - .../webrtc/video_engine/vie_base_impl.cc | 69 +- .../trunk/webrtc/video_engine/vie_base_impl.h | 18 +- .../webrtc/video_engine/vie_capture_impl.cc | 42 +- .../webrtc/video_engine/vie_capture_impl.h | 6 +- .../trunk/webrtc/video_engine/vie_capturer.cc | 380 +- .../trunk/webrtc/video_engine/vie_capturer.h | 67 +- .../video_engine/vie_capturer_unittest.cc | 113 +- .../trunk/webrtc/video_engine/vie_channel.cc | 1062 +- .../trunk/webrtc/video_engine/vie_channel.h | 167 +- .../webrtc/video_engine/vie_channel_group.cc | 375 +- .../webrtc/video_engine/vie_channel_group.h | 97 +- .../video_engine/vie_channel_manager.cc | 319 +- .../webrtc/video_engine/vie_channel_manager.h | 42 +- .../webrtc/video_engine/vie_codec_impl.cc | 40 +- .../webrtc/video_engine/vie_codec_impl.h | 1 + .../trunk/webrtc/video_engine/vie_encoder.cc | 548 +- .../trunk/webrtc/video_engine/vie_encoder.h | 135 +- .../video_engine/vie_external_codec_impl.cc | 8 +- .../video_engine/vie_external_codec_impl.h | 2 +- .../webrtc/video_engine/vie_file_image.cc | 5 +- .../video_engine/vie_frame_provider_base.cc | 128 +- .../video_engine/vie_frame_provider_base.h | 38 +- .../video_engine/vie_image_process_impl.h | 28 +- .../trunk/webrtc/video_engine/vie_impl.h | 4 +- .../webrtc/video_engine/vie_input_manager.cc | 29 +- .../webrtc/video_engine/vie_input_manager.h | 9 +- .../webrtc/video_engine/vie_network_impl.cc | 41 +- .../webrtc/video_engine/vie_network_impl.h | 44 +- .../trunk/webrtc/video_engine/vie_receiver.cc | 120 +- .../trunk/webrtc/video_engine/vie_receiver.h | 50 +- .../trunk/webrtc/video_engine/vie_ref_count.h | 4 +- .../trunk/webrtc/video_engine/vie_remb.cc | 3 +- .../trunk/webrtc/video_engine/vie_remb.h | 4 +- .../webrtc/video_engine/vie_remb_unittest.cc | 40 +- .../webrtc/video_engine/vie_render_impl.cc | 42 - .../webrtc/video_engine/vie_render_impl.h | 5 - .../webrtc/video_engine/vie_render_manager.h | 4 +- .../trunk/webrtc/video_engine/vie_renderer.cc | 78 +- .../trunk/webrtc/video_engine/vie_renderer.h | 22 +- .../webrtc/video_engine/vie_rtp_rtcp_impl.cc | 186 +- .../webrtc/video_engine/vie_rtp_rtcp_impl.h | 44 +- .../trunk/webrtc/video_engine/vie_sender.cc | 10 +- .../trunk/webrtc/video_engine/vie_sender.h | 8 +- .../webrtc/video_engine/vie_shared_data.cc | 7 +- .../webrtc/video_engine/vie_shared_data.h | 10 +- .../webrtc/video_engine/vie_sync_module.cc | 8 +- .../webrtc/video_engine/vie_sync_module.h | 10 +- .../trunk/webrtc/video_engine_tests.isolate | 6 +- media/webrtc/trunk/webrtc/video_frame.h | 234 +- .../trunk/webrtc/video_receive_stream.h | 42 +- media/webrtc/trunk/webrtc/video_renderer.h | 2 + media/webrtc/trunk/webrtc/video_send_stream.h | 34 +- .../webrtc/trunk/webrtc/voice_engine/BUILD.gn | 9 +- .../trunk/webrtc/voice_engine/channel.cc | 485 +- .../trunk/webrtc/voice_engine/channel.h | 153 +- .../webrtc/voice_engine/channel_manager.cc | 7 +- .../webrtc/voice_engine/channel_manager.h | 9 +- .../include/mock/fake_voe_external_media.h | 4 +- .../include/voe_audio_processing.h | 8 +- .../webrtc/voice_engine/include/voe_base.h | 1 - .../webrtc/voice_engine/include/voe_codec.h | 21 +- .../voice_engine/include/voe_hardware.h | 7 +- .../webrtc/voice_engine/include/voe_network.h | 9 +- .../voice_engine/include/voe_rtp_rtcp.h | 22 +- .../webrtc/voice_engine/monitor_module.cc | 21 +- .../webrtc/voice_engine/monitor_module.h | 8 +- .../webrtc/voice_engine/network_predictor.cc | 11 +- .../webrtc/voice_engine/network_predictor.h | 2 +- .../network_predictor_unittest.cc | 2 +- .../trunk/webrtc/voice_engine/shared_data.cc | 4 +- .../trunk/webrtc/voice_engine/shared_data.h | 8 +- .../android/android_test/jni/android_test.cc | 30 +- .../auto_test/extended/ec_metrics_test.cc | 19 +- .../fakes/fake_external_transport.cc | 32 +- .../auto_test/fakes/fake_external_transport.h | 10 +- .../fixtures/after_initialization_fixture.h | 57 +- .../fixtures/before_streaming_fixture.cc | 4 + .../fixtures/before_streaming_fixture.h | 3 + .../standard/codec_before_streaming_test.cc | 1 + .../test/auto_test/standard/codec_test.cc | 37 +- .../auto_test/standard/neteq_stats_test.cc | 30 +- .../auto_test/standard/rtp_rtcp_extensions.cc | 56 +- .../test/auto_test/standard/rtp_rtcp_test.cc | 39 +- .../test/auto_test/voe_cpu_test.cc | 4 +- .../test/auto_test/voe_stress_test.cc | 12 +- .../test/auto_test/voe_stress_test.h | 9 +- .../test/cmd_test/voe_cmd_test.cc | 40 +- .../voice_engine/test/win_test/WinTestDlg.cc | 23 +- .../webrtc/voice_engine/transmit_mixer.cc | 13 +- .../webrtc/voice_engine/transmit_mixer.h | 4 +- .../voice_engine/voe_audio_processing_impl.cc | 14 +- .../voice_engine/voe_audio_processing_impl.h | 3 +- .../webrtc/voice_engine/voe_auto_test.isolate | 8 - .../webrtc/voice_engine/voe_base_impl.cc | 30 +- .../webrtc/voice_engine/voe_base_unittest.cc | 6 +- .../webrtc/voice_engine/voe_codec_impl.cc | 122 +- .../webrtc/voice_engine/voe_codec_impl.h | 8 +- .../webrtc/voice_engine/voe_codec_unittest.cc | 72 +- .../webrtc/voice_engine/voe_hardware_impl.cc | 8 + .../webrtc/voice_engine/voe_hardware_impl.h | 16 +- .../webrtc/voice_engine/voe_network_impl.cc | 13 +- .../webrtc/voice_engine/voe_network_impl.h | 21 +- .../webrtc/voice_engine/voe_rtp_rtcp_impl.cc | 3 +- .../webrtc/voice_engine/voice_engine.gyp | 18 +- .../webrtc/voice_engine/voice_engine_impl.cc | 12 +- .../webrtc/voice_engine/voice_engine_impl.h | 2 +- .../voice_engine_unittests.isolate | 8 - media/webrtc/trunk/webrtc/webrtc.gyp | 20 +- media/webrtc/trunk/webrtc/webrtc_examples.gyp | 22 +- .../trunk/webrtc/webrtc_perf_tests.isolate | 14 +- media/webrtc/trunk/webrtc/webrtc_tests.gypi | 96 +- modules/libpref/init/all.js | 6 + testing/cppunittest.ini | 3 + .../self-doesnt-match-blob.sub.html.ini | 6 + .../star-doesnt-match-blob.sub.html.ini | 2 + .../child-src-worker-blocked.sub.html.ini | 9 + .../opt-in-blocks.https.html.ini | 2 + .../no-redirect/opt-in-blocks.https.html.ini | 2 + .../opt-in-blocks.https.html.ini | 2 + .../opt-in-blocks.https.html.ini | 2 + .../no-redirect/opt-in-blocks.https.html.ini | 2 + .../opt-in-blocks.https.html.ini | 2 + .../no-redirect/opt-in-blocks.https.html.ini | 2 + .../no-redirect/opt-in-blocks.https.html.ini | 2 + .../no-opt-in-blocks.https.html.ini | 2 + .../no-opt-in-blocks.https.html.ini | 2 + .../no-opt-in-blocks.https.html.ini | 2 + .../no-opt-in-blocks.https.html.ini | 2 + .../no-opt-in-blocks.https.html.ini | 2 + .../no-opt-in-blocks.https.html.ini | 2 + .../Worker_cross_origin_security_err.htm.ini | 4 + .../SharedWorker/same-origin.html.ini | 18 + .../constructors/Worker/same-origin.html.ini | 17 + .../WorkerUtils/importScripts/006.html.ini | 6 - toolkit/components/thumbnails/PageThumbs.jsm | 9 +- .../content/backgroundPageThumbsContent.js | 5 +- toolkit/devtools/server/actors/device.js | 2 +- toolkit/devtools/server/actors/webapps.js | 5 +- toolkit/devtools/webconsole/test/common.js | 2 +- toolkit/modules/CharsetMenu.jsm | 4 +- toolkit/modules/DeferredTask.jsm | 2 +- toolkit/modules/FileUtils.jsm | 5 +- toolkit/modules/Log.jsm | 2 +- toolkit/modules/Promise-backend.js | 3 +- toolkit/modules/PromiseUtils.jsm | 2 +- toolkit/modules/PropertyListUtils.jsm | 7 +- toolkit/modules/RemotePageManager.jsm | 2 +- toolkit/modules/Services.jsm | 6 +- toolkit/modules/Sqlite.jsm | 16 +- toolkit/modules/Task.jsm | 25 +- toolkit/modules/ZipUtils.jsm | 10 +- toolkit/modules/addons/MatchPattern.jsm | 2 +- toolkit/modules/addons/WebRequestContent.js | 6 +- .../tests/xpcshell/test_DeferredTask.js | 8 +- toolkit/modules/tests/xpcshell/test_Log.js | 14 +- .../tests/xpcshell/test_NewTabUtils.js | 12 +- .../tests/xpcshell/test_PromiseUtils.js | 2 +- .../modules/tests/xpcshell/test_ZipUtils.js | 2 +- toolkit/modules/tests/xpcshell/test_sqlite.js | 10 +- .../tests/xpcshell/test_sqlite_shutdown.js | 4 +- .../extensions/content/selectAddons.js | 2 +- toolkit/mozapps/extensions/content/update.js | 22 +- .../extensions/internal/AddonRepository.jsm | 42 +- .../AddonRepository_SQLiteMigrator.jsm | 2 +- .../internal/AddonUpdateChecker.jsm | 4 +- .../extensions/internal/GMPProvider.jsm | 10 +- .../extensions/internal/PluginProvider.jsm | 7 +- .../extensions/internal/XPIProvider.jsm | 21 +- .../extensions/internal/XPIProviderUtils.js | 10 +- .../mozapps/extensions/nsBlocklistService.js | 6 +- .../test/browser/browser_bug580298.js | 2 +- .../test/browser/browser_bug596336.js | 108 +- .../test/browser/browser_cancelCompatCheck.js | 10 +- .../test/browser/browser_experiments.js | 6 +- .../extensions/test/xpcshell/head_addons.js | 7 +- .../test/xpcshell/test_DeferredSave.js | 24 +- .../test/xpcshell/test_asyncBlocklistLoad.js | 2 +- .../extensions/test/xpcshell/test_locked2.js | 2 +- .../test/xpcshell/test_mapURIToAddonID.js | 9 +- .../test/xpcshell/test_no_addons.js | 6 +- .../test/xpcshell/test_updateCancel.js | 4 +- .../test/xpcshell/test_update_strictcompat.js | 2 +- xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp | 3 - 2203 files changed, 124894 insertions(+), 112212 deletions(-) delete mode 100644 dom/base/FileIOObject.cpp delete mode 100644 dom/base/FileIOObject.h rename dom/base/{nsDOMFileReader.cpp => FileReader.cpp} (50%) rename dom/base/{nsDOMFileReader.h => FileReader.h} (57%) delete mode 100644 dom/base/nsIDOMFileReader.idl create mode 100644 dom/base/test/file_bug1198095.js create mode 100644 dom/base/test/test_bug1198095.html create mode 100644 dom/security/test/csp/file_child-src_iframe.html create mode 100644 dom/security/test/csp/file_child-src_inner_frame.html create mode 100644 dom/security/test/csp/file_child-src_service_worker.html create mode 100644 dom/security/test/csp/file_child-src_service_worker.js create mode 100644 dom/security/test/csp/file_child-src_shared_worker-redirect.html create mode 100644 dom/security/test/csp/file_child-src_shared_worker.html create mode 100644 dom/security/test/csp/file_child-src_shared_worker.js create mode 100644 dom/security/test/csp/file_child-src_shared_worker_data.html create mode 100644 dom/security/test/csp/file_child-src_worker-redirect.html create mode 100644 dom/security/test/csp/file_child-src_worker.html create mode 100644 dom/security/test/csp/file_child-src_worker.js create mode 100644 dom/security/test/csp/file_child-src_worker_data.html create mode 100644 dom/security/test/csp/file_main_worker.js create mode 100644 dom/security/test/csp/file_redirect_worker.sjs create mode 100644 dom/security/test/csp/file_service_worker.html create mode 100644 dom/security/test/csp/file_service_worker.js delete mode 100644 dom/security/test/csp/file_worker_redirect.html delete mode 100644 dom/security/test/csp/file_worker_redirect.sjs create mode 100644 dom/security/test/csp/test_child-src_iframe.html create mode 100644 dom/security/test/csp/test_child-src_worker-redirect.html create mode 100644 dom/security/test/csp/test_child-src_worker.html create mode 100644 dom/security/test/csp/test_child-src_worker_data.html create mode 100644 dom/security/test/csp/test_service_worker.html delete mode 100644 dom/security/test/csp/test_worker_redirect.html rename dom/workers/test/serviceworkers/{test_eval_not_allowed.html^headers^ => test_eval_allowed.html^headers^} (100%) delete mode 100644 dom/workers/test/serviceworkers/test_eval_not_allowed.html create mode 100644 js/xpconnect/tests/unit/test_fileReader.js create mode 100644 media/webrtc/signaling/src/common/EncodingConstraints.h create mode 100644 media/webrtc/signaling/src/jsep/JsepTrack.cpp create mode 100644 media/webrtc/signaling/src/jsep/JsepTrackEncoding.h delete mode 100644 media/webrtc/signaling/src/jsep/JsepTrackImpl.h create mode 100644 media/webrtc/signaling/src/sdp/SdpMediaSection.cpp create mode 100644 media/webrtc/signaling/test/jsep_track_unittest.cpp create mode 100644 media/webrtc/signaling/test/sdp_file_parser.cpp create mode 100644 media/webrtc/trunk/AUTHORS create mode 100644 media/webrtc/trunk/build/android/cpufeatures.gypi create mode 100644 media/webrtc/trunk/webrtc/base/arraysize.h create mode 100644 media/webrtc/trunk/webrtc/base/asyncpacketsocket.cc create mode 100644 media/webrtc/trunk/webrtc/base/asyncresolverinterface.cc create mode 100644 media/webrtc/trunk/webrtc/base/buffer.cc delete mode 100644 media/webrtc/trunk/webrtc/base/compile_assert.h create mode 100644 media/webrtc/trunk/webrtc/base/criticalsection.cc create mode 100644 media/webrtc/trunk/webrtc/base/cryptstring.cc create mode 100644 media/webrtc/trunk/webrtc/base/event_tracer.cc create mode 100644 media/webrtc/trunk/webrtc/base/event_tracer.h create mode 100644 media/webrtc/trunk/webrtc/base/event_tracer_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/base/format_macros.h create mode 100644 media/webrtc/trunk/webrtc/base/md5digest.cc create mode 100644 media/webrtc/trunk/webrtc/base/sha1digest.cc create mode 100644 media/webrtc/trunk/webrtc/base/sigslot.cc create mode 100644 media/webrtc/trunk/webrtc/base/trace_event.h create mode 100644 media/webrtc/trunk/webrtc/build/android/test_runner.py create mode 100644 media/webrtc/trunk/webrtc/build/find_directx_sdk.py delete mode 100644 media/webrtc/trunk/webrtc/build/ios-webrtc.sh create mode 100644 media/webrtc/trunk/webrtc/build/sanitizers/OWNERS create mode 100644 media/webrtc/trunk/webrtc/build/sanitizers/README create mode 100644 media/webrtc/trunk/webrtc/build/sanitizers/lsan_suppressions_webrtc.cc rename media/webrtc/trunk/webrtc/build/{ => sanitizers}/tsan_suppressions_webrtc.cc (89%) delete mode 100644 media/webrtc/trunk/webrtc/build/version.py delete mode 100644 media/webrtc/trunk/webrtc/build/vie-webrtc.sh create mode 100644 media/webrtc/trunk/webrtc/build/whitespace.txt create mode 100644 media/webrtc/trunk/webrtc/codereview.settings create mode 100644 media/webrtc/trunk/webrtc/common_audio/audio_ring_buffer.cc create mode 100644 media/webrtc/trunk/webrtc/common_audio/audio_ring_buffer.h create mode 100644 media/webrtc/trunk/webrtc/common_audio/audio_ring_buffer_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/common_audio/channel_buffer.cc create mode 100644 media/webrtc/trunk/webrtc/common_audio/channel_buffer.h rename media/webrtc/trunk/webrtc/{modules/audio_processing/utility => common_audio}/fft4g.c (100%) create mode 100644 media/webrtc/trunk/webrtc/common_audio/fft4g.h create mode 100644 media/webrtc/trunk/webrtc/common_audio/real_fourier_ooura.cc create mode 100644 media/webrtc/trunk/webrtc/common_audio/real_fourier_ooura.h create mode 100644 media/webrtc/trunk/webrtc/common_audio/real_fourier_openmax.cc create mode 100644 media/webrtc/trunk/webrtc/common_audio/real_fourier_openmax.h rename media/webrtc/trunk/webrtc/{modules/audio_processing/utility => common_audio}/ring_buffer.c (97%) rename media/webrtc/trunk/webrtc/{modules/audio_processing/utility => common_audio}/ring_buffer.h (88%) rename media/webrtc/trunk/webrtc/{modules/audio_processing/utility => common_audio}/ring_buffer_unittest.cc (91%) delete mode 100644 media/webrtc/trunk/webrtc/common_audio/signal_processing/cross_correlation_neon.S create mode 100644 media/webrtc/trunk/webrtc/common_audio/signal_processing/cross_correlation_neon.c delete mode 100644 media/webrtc/trunk/webrtc/common_audio/signal_processing/downsample_fast_neon.S create mode 100644 media/webrtc/trunk/webrtc/common_audio/signal_processing/downsample_fast_neon.c delete mode 100644 media/webrtc/trunk/webrtc/common_audio/signal_processing/min_max_operations_neon.S create mode 100644 media/webrtc/trunk/webrtc/common_audio/signal_processing/min_max_operations_neon.c delete mode 100644 media/webrtc/trunk/webrtc/common_audio/signal_processing/vector_scaling_operations_neon.S create mode 100644 media/webrtc/trunk/webrtc/common_types.cc create mode 100644 media/webrtc/trunk/webrtc/common_video/i420_buffer_pool.cc create mode 100644 media/webrtc/trunk/webrtc/common_video/i420_buffer_pool_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/common_video/interface/i420_buffer_pool.h delete mode 100644 media/webrtc/trunk/webrtc/common_video/interface/texture_video_frame.h create mode 100644 media/webrtc/trunk/webrtc/common_video/interface/video_frame_buffer.h delete mode 100644 media/webrtc/trunk/webrtc/common_video/plane_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/common_video/rotation.h delete mode 100644 media/webrtc/trunk/webrtc/common_video/texture_video_frame.cc delete mode 100644 media/webrtc/trunk/webrtc/common_video/texture_video_frame_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/common_video/video_frame_buffer.cc rename media/webrtc/trunk/webrtc/modules/audio_coding/{codecs/tools => }/audio_codec_speed_tests.isolate (92%) create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/audio_coding.gypi create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/audio_coding_tests.gypi create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/audio_decoder.cc rename media/webrtc/trunk/webrtc/modules/audio_coding/{neteq/interface => codecs}/audio_decoder.h (65%) create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/audio_encoder.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h rename media/webrtc/trunk/webrtc/modules/{remote_bitrate_estimator/remote_bitrate_estimator_components.gyp => audio_coding/codecs/interfaces.gypi} (55%) create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/filterbanks_neon.c create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/filters_neon.c delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/isacfix.gypi create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/lattice_neon.c create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/transform_neon.c create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/isac.gypi create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/isacfix.gypi create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/main/source/isac.gypi create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/red/red.gypi delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_tests.gypi delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_amr.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_amr.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_amrwb.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_amrwb.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_celt.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_celt.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_cng.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_cng.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_dtmf_playout.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_dtmf_playout.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_g722.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_g722.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_g7221.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_g7221.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_g7221c.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_g7221c.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_g729.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_g729.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_g7291.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_g7291.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_opus_test.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_test.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_gsmfr.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_gsmfr.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_ilbc.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_ilbc.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_isac.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_isac.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_isac_macros.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_opus.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_opus.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_opus_unittest.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_pcm16b.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_pcm16b.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_pcma.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_pcma.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_pcmu.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_pcmu.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_red.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_red.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_speex.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/acm_speex.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/codec_manager.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/acm2/codec_manager.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/main/test/dual_stream_unittest.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/neteq/audio_decoder.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/neteq/test/RTPcat.cc rename media/webrtc/trunk/webrtc/modules/audio_coding/neteq/test/{neteq_opus_fec_quality_test.cc => neteq_opus_quality_test.cc} (64%) create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/neteq/tools/output_wav_file.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_coding/neteq/tools/rtpcat.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_conference_mixer/audio_conference_mixer.gypi delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_conference_mixer/source/audio_conference_mixer.gypi delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_device/android/OWNERS create mode 100644 media/webrtc/trunk/webrtc/modules/audio_device/android/audio_device_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_device/android/audio_manager.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_device/android/audio_manager.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_device/android/ensure_initialized.cc rename media/webrtc/trunk/webrtc/modules/{audio_processing/utility/fft4g.h => audio_device/android/ensure_initialized.h} (54%) create mode 100644 media/webrtc/trunk/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioManager.java create mode 100644 media/webrtc/trunk/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioUtils.java create mode 100644 media/webrtc/trunk/webrtc/modules/audio_device/gonk/audio_manager.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_device/gonk/audio_manager.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/aecm/aecm_core_neon.S delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/aecm/aecm_core_neon_offsets.c create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/agc.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/agc.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/agc_audio_proc.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/agc_audio_proc.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/agc_audio_proc_internal.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/agc_audio_proc_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/agc_manager_direct.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/agc_manager_direct.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/agc_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/circular_buffer.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/circular_buffer.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/circular_buffer_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/common.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/gain_map_internal.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/gmm.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/gmm.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/gmm_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/histogram.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/histogram.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/histogram_unittest.cc rename media/webrtc/trunk/webrtc/modules/audio_processing/agc/{ => legacy}/analog_agc.c (80%) rename media/webrtc/trunk/webrtc/modules/audio_processing/agc/{ => legacy}/analog_agc.h (92%) rename media/webrtc/trunk/webrtc/modules/audio_processing/agc/{ => legacy}/digital_agc.c (86%) rename media/webrtc/trunk/webrtc/modules/audio_processing/agc/{ => legacy}/digital_agc.h (65%) rename media/webrtc/trunk/webrtc/modules/audio_processing/agc/{include => legacy}/gain_control.h (68%) create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/mock_agc.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/noise_gmm_tables.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/pitch_based_vad.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/pitch_based_vad.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/pitch_based_vad_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/pitch_internal.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/pitch_internal.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/pitch_internal_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/pole_zero_filter.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/pole_zero_filter.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/pole_zero_filter_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/standalone_vad.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/standalone_vad.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/standalone_vad_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/utility.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/utility.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/agc/voice_gmm_tables.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/array_util.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/beamformer.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/complex_matrix.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/complex_matrix_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/covariance_matrix_generator.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/covariance_matrix_generator.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/covariance_matrix_generator_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/matrix.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/matrix_test_helpers.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/matrix_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/mock_nonlinear_beamformer.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/mock_nonlinear_beamformer.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/nonlinear_beamformer_test.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/pcm_utils.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/beamformer/pcm_utils.h delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/gen_core_neon_offsets.gyp delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/gen_core_neon_offsets_chromium.gyp delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/lib_core_neon_offsets.gypi delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/ns/nsx_core_neon.S delete mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/ns/nsx_core_neon_offsets.c create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/splitting_filter.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/splitting_filter.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/splitting_filter_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/test/audioproc_float.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/click_annotate.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/common.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/daubechies_8_wavelet_coeffs.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/dyadic_decimator.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/dyadic_decimator_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/file_utils.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/file_utils.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/file_utils_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/moving_moments.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/moving_moments.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/moving_moments_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/test/plotDetection.m create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/test/readDetection.m create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/test/readPCM.m create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/transient_detector.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/transient_detector.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/transient_detector_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/transient_suppression_test.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/transient_suppressor.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/transient_suppressor.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/transient_suppressor_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/wpd_node.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/wpd_node.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/wpd_node_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/wpd_tree.cc create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/wpd_tree.h create mode 100644 media/webrtc/trunk/webrtc/modules/audio_processing/transient/wpd_tree_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/bitrate_controller/bitrate_allocator.cc create mode 100644 media/webrtc/trunk/webrtc/modules/bitrate_controller/bitrate_allocator_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/bitrate_controller/include/bitrate_allocator.h create mode 100644 media/webrtc/trunk/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/bitrate_controller/send_time_history.cc create mode 100644 media/webrtc/trunk/webrtc/modules/bitrate_controller/send_time_history.h create mode 100644 media/webrtc/trunk/webrtc/modules/bitrate_controller/send_time_history_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/desktop_capture/cropped_desktop_frame.cc create mode 100644 media/webrtc/trunk/webrtc/modules/desktop_capture/cropped_desktop_frame.h create mode 100644 media/webrtc/trunk/webrtc/modules/desktop_capture/cropping_window_capturer.cc create mode 100644 media/webrtc/trunk/webrtc/modules/desktop_capture/cropping_window_capturer.h create mode 100644 media/webrtc/trunk/webrtc/modules/desktop_capture/cropping_window_capturer_win.cc rename media/webrtc/trunk/webrtc/modules/media_file/{source => }/media_file.gypi (55%) delete mode 100644 media/webrtc/trunk/webrtc/modules/media_file/source/avi_file.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/media_file/source/avi_file.h create mode 100644 media/webrtc/trunk/webrtc/modules/pacing/include/packet_router.h create mode 100644 media/webrtc/trunk/webrtc/modules/pacing/packet_router.cc create mode 100644 media/webrtc/trunk/webrtc/modules/pacing/packet_router_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/aimd_rate_control.h create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/inter_arrival.cc create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/inter_arrival.h create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/inter_arrival_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/mimd_rate_control.cc create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/mimd_rate_control.h create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/overuse_detector_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/overuse_estimator.cc create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/overuse_estimator.h create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/test/bwe.cc create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/test/bwe.h create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.cc create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.cc create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.h create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.cc create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/test/packet.h create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/test/packet_receiver.cc create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/test/packet_receiver.h create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/test/packet_sender.cc create mode 100644 media/webrtc/trunk/webrtc/modules/remote_bitrate_estimator/test/packet_sender.h create mode 100644 media/webrtc/trunk/webrtc/modules/rtp_rtcp/interface/rtp_cvo.h create mode 100644 media/webrtc/trunk/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi delete mode 100644 media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_rtcp.gypi delete mode 100644 media/webrtc/trunk/webrtc/modules/utility/source/frame_scaler.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/utility/source/frame_scaler.h create mode 100644 media/webrtc/trunk/webrtc/modules/utility/source/process_thread_impl_unittest.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/utility/source/utility.gypi delete mode 100644 media/webrtc/trunk/webrtc/modules/utility/source/video_coder.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/utility/source/video_coder.h delete mode 100644 media/webrtc/trunk/webrtc/modules/utility/source/video_frames_queue.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/utility/source/video_frames_queue.h create mode 100644 media/webrtc/trunk/webrtc/modules/utility/utility.gypi delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/OWNERS delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/benchmark.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/benchmark.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/exportfig.m delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/normal_async_test.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/normal_async_test.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/normal_test.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/normal_test.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/packet_loss_test.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/packet_loss_test.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/plotBenchmark.m delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/test.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/test.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/test_framework.gypi delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/unit_test.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/unit_test.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/video_source.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/test_framework/video_source.h create mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc create mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h create mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/screenshare_layers_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc create mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h create mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h create mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/vp8_factory.h create mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp9/vp9_dummy_impl.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/source/er_tables_xor.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/source/video_coding.gypi delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/source/video_coding_test.gypi delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/codec_database_test.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/codec_database_test.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/generic_codec_test.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/generic_codec_test.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/jitter_estimate_test.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/media_opt_test.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/media_opt_test.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/mt_rx_tx_test.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/mt_test_common.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/mt_test_common.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/normal_test.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/normal_test.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/quality_modes_test.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/quality_modes_test.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/test_callbacks.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/test_callbacks.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/test_macros.h delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/video_rtp_play_mt.cc delete mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/main/test/video_source.cc create mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/video_coding.gypi create mode 100644 media/webrtc/trunk/webrtc/modules/video_coding/video_coding_test.gypi rename media/webrtc/trunk/webrtc/modules/video_processing/{main/source => }/video_processing.gypi (58%) create mode 100644 media/webrtc/trunk/webrtc/overrides/webrtc/base/arraysize.h create mode 100644 media/webrtc/trunk/webrtc/overrides/webrtc/base/diagnostic_logging.h create mode 100644 media/webrtc/trunk/webrtc/p2p/OWNERS create mode 100644 media/webrtc/trunk/webrtc/p2p/base/asyncstuntcpsocket.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/asyncstuntcpsocket.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/asyncstuntcpsocket_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/basicpacketsocketfactory.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/basicpacketsocketfactory.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/candidate.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/common.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/constants.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/constants.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/dtlstransport.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/dtlstransportchannel.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/dtlstransportchannel.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/dtlstransportchannel_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/fakesession.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/p2ptransport.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/p2ptransport.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/p2ptransportchannel.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/p2ptransportchannel.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/p2ptransportchannel_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/packetsocketfactory.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/port.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/port.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/port_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/portallocator.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/portallocator.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/portallocatorsessionproxy.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/portallocatorsessionproxy.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/portallocatorsessionproxy_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/portinterface.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/portproxy.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/portproxy.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/pseudotcp.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/pseudotcp.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/pseudotcp_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/rawtransport.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/rawtransport.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/rawtransportchannel.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/rawtransportchannel.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/relayport.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/relayport.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/relayport_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/relayserver.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/relayserver.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/relayserver_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/session.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/session.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/sessiondescription.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/sessiondescription.h rename media/webrtc/trunk/webrtc/{base/stringdigest.h => p2p/base/sessionid.h} (65%) create mode 100644 media/webrtc/trunk/webrtc/p2p/base/stun.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/stun.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/stun_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/stunport.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/stunport.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/stunport_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/stunrequest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/stunrequest.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/stunrequest_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/stunserver.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/stunserver.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/stunserver_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/tcpport.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/tcpport.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/testrelayserver.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/teststunserver.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/testturnserver.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/transport.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/transport.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/transport_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/transportchannel.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/transportchannel.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/transportchannelimpl.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/transportchannelproxy.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/transportchannelproxy.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/transportdescription.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/transportdescription.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/transportdescriptionfactory.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/transportdescriptionfactory.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/transportdescriptionfactory_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/transportinfo.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/turnport.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/turnport.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/turnport_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/turnserver.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/base/turnserver.h create mode 100644 media/webrtc/trunk/webrtc/p2p/base/udpport.h create mode 100644 media/webrtc/trunk/webrtc/p2p/client/autoportallocator.h create mode 100644 media/webrtc/trunk/webrtc/p2p/client/basicportallocator.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/client/basicportallocator.h create mode 100644 media/webrtc/trunk/webrtc/p2p/client/connectivitychecker.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/client/connectivitychecker.h create mode 100644 media/webrtc/trunk/webrtc/p2p/client/connectivitychecker_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/client/fakeportallocator.h create mode 100644 media/webrtc/trunk/webrtc/p2p/client/httpportallocator.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/client/httpportallocator.h create mode 100644 media/webrtc/trunk/webrtc/p2p/client/portallocator_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/client/socketmonitor.cc create mode 100644 media/webrtc/trunk/webrtc/p2p/client/socketmonitor.h create mode 100644 media/webrtc/trunk/webrtc/p2p/p2p.gyp create mode 100644 media/webrtc/trunk/webrtc/p2p/p2p_tests.gypi create mode 100644 media/webrtc/trunk/webrtc/sound/OWNERS create mode 100644 media/webrtc/trunk/webrtc/sound/alsasoundsystem.cc create mode 100644 media/webrtc/trunk/webrtc/sound/alsasoundsystem.h create mode 100644 media/webrtc/trunk/webrtc/sound/alsasymboltable.cc create mode 100644 media/webrtc/trunk/webrtc/sound/alsasymboltable.h create mode 100644 media/webrtc/trunk/webrtc/sound/automaticallychosensoundsystem.h create mode 100644 media/webrtc/trunk/webrtc/sound/automaticallychosensoundsystem_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/sound/linuxsoundsystem.cc create mode 100644 media/webrtc/trunk/webrtc/sound/linuxsoundsystem.h create mode 100644 media/webrtc/trunk/webrtc/sound/nullsoundsystem.cc create mode 100644 media/webrtc/trunk/webrtc/sound/nullsoundsystem.h create mode 100644 media/webrtc/trunk/webrtc/sound/nullsoundsystemfactory.cc create mode 100644 media/webrtc/trunk/webrtc/sound/nullsoundsystemfactory.h create mode 100644 media/webrtc/trunk/webrtc/sound/platformsoundsystem.cc create mode 100644 media/webrtc/trunk/webrtc/sound/platformsoundsystem.h create mode 100644 media/webrtc/trunk/webrtc/sound/platformsoundsystemfactory.cc create mode 100644 media/webrtc/trunk/webrtc/sound/platformsoundsystemfactory.h create mode 100644 media/webrtc/trunk/webrtc/sound/pulseaudiosoundsystem.cc create mode 100644 media/webrtc/trunk/webrtc/sound/pulseaudiosoundsystem.h create mode 100644 media/webrtc/trunk/webrtc/sound/pulseaudiosymboltable.cc create mode 100644 media/webrtc/trunk/webrtc/sound/pulseaudiosymboltable.h create mode 100644 media/webrtc/trunk/webrtc/sound/sound.gyp create mode 100644 media/webrtc/trunk/webrtc/sound/sound_tests.gypi create mode 100644 media/webrtc/trunk/webrtc/sound/sounddevicelocator.h create mode 100644 media/webrtc/trunk/webrtc/sound/soundinputstreaminterface.h create mode 100644 media/webrtc/trunk/webrtc/sound/soundoutputstreaminterface.h create mode 100644 media/webrtc/trunk/webrtc/sound/soundsystemfactory.h create mode 100644 media/webrtc/trunk/webrtc/sound/soundsysteminterface.cc create mode 100644 media/webrtc/trunk/webrtc/sound/soundsysteminterface.h create mode 100644 media/webrtc/trunk/webrtc/sound/soundsystemproxy.cc create mode 100644 media/webrtc/trunk/webrtc/sound/soundsystemproxy.h create mode 100644 media/webrtc/trunk/webrtc/system_wrappers/cpu_features_chromium.gyp create mode 100644 media/webrtc/trunk/webrtc/system_wrappers/cpu_features_webrtc.gyp delete mode 100644 media/webrtc/trunk/webrtc/system_wrappers/interface/compile_assert.h create mode 100644 media/webrtc/trunk/webrtc/system_wrappers/interface/field_trial_default.h delete mode 100644 media/webrtc/trunk/webrtc/system_wrappers/interface/scoped_ptr.h delete mode 100644 media/webrtc/trunk/webrtc/system_wrappers/interface/template_util.h delete mode 100644 media/webrtc/trunk/webrtc/system_wrappers/source/move.h delete mode 100644 media/webrtc/trunk/webrtc/system_wrappers/source/set_thread_name_win.h delete mode 100644 media/webrtc/trunk/webrtc/system_wrappers/source/system_wrappers.gyp create mode 100644 media/webrtc/trunk/webrtc/system_wrappers/system_wrappers.gyp rename media/webrtc/trunk/webrtc/system_wrappers/{source => }/system_wrappers_tests.gyp (61%) rename media/webrtc/trunk/webrtc/system_wrappers/{source => }/system_wrappers_unittests.isolate (83%) create mode 100644 media/webrtc/trunk/webrtc/test/frame_generator_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/test/histogram.cc create mode 100644 media/webrtc/trunk/webrtc/test/histogram.h delete mode 100644 media/webrtc/trunk/webrtc/test/manual/README delete mode 100644 media/webrtc/trunk/webrtc/test/manual/adapter.js delete mode 100644 media/webrtc/trunk/webrtc/test/manual/audio-and-video.html delete mode 100644 media/webrtc/trunk/webrtc/test/manual/iframe-apprtc.html delete mode 100644 media/webrtc/trunk/webrtc/test/manual/iframe-video.html delete mode 100644 media/webrtc/trunk/webrtc/test/manual/multiple-audio.html delete mode 100644 media/webrtc/trunk/webrtc/test/manual/multiple-video.html delete mode 100644 media/webrtc/trunk/webrtc/test/manual/single-audio.html delete mode 100644 media/webrtc/trunk/webrtc/test/manual/single-video.html delete mode 100644 media/webrtc/trunk/webrtc/test/manual/two-video-devices.html create mode 100644 media/webrtc/trunk/webrtc/test/rtp_file_writer.cc create mode 100644 media/webrtc/trunk/webrtc/test/rtp_file_writer.h create mode 100644 media/webrtc/trunk/webrtc/test/rtp_file_writer_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/tools/agc/activity_metric.cc create mode 100644 media/webrtc/trunk/webrtc/tools/agc/agc_harness.cc create mode 100644 media/webrtc/trunk/webrtc/tools/agc/agc_manager.cc create mode 100644 media/webrtc/trunk/webrtc/tools/agc/agc_manager.h create mode 100644 media/webrtc/trunk/webrtc/tools/agc/agc_manager_integrationtest.cc create mode 100644 media/webrtc/trunk/webrtc/tools/agc/agc_manager_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/tools/agc/agc_test.cc create mode 100644 media/webrtc/trunk/webrtc/tools/agc/fake_agc.h create mode 100644 media/webrtc/trunk/webrtc/tools/agc/test_utils.cc create mode 100644 media/webrtc/trunk/webrtc/tools/agc/test_utils.h create mode 100644 media/webrtc/trunk/webrtc/tools/e2e_quality/audio/perf/__init__.py create mode 100644 media/webrtc/trunk/webrtc/tools/e2e_quality/audio/perf/perf_utils.py create mode 100644 media/webrtc/trunk/webrtc/video/loopback.h create mode 100644 media/webrtc/trunk/webrtc/video/screenshare_loopback.cc create mode 100644 media/webrtc/trunk/webrtc/video/video_loopback.cc create mode 100644 media/webrtc/trunk/webrtc/video_engine/payload_router.cc create mode 100644 media/webrtc/trunk/webrtc/video_engine/payload_router.h create mode 100644 media/webrtc/trunk/webrtc/video_engine/payload_router_unittest.cc create mode 100644 media/webrtc/trunk/webrtc/video_engine/report_block_stats.cc create mode 100644 media/webrtc/trunk/webrtc/video_engine/report_block_stats.h create mode 100644 media/webrtc/trunk/webrtc/video_engine/report_block_stats_unittest.cc create mode 100644 testing/web-platform/meta/content-security-policy/blink-contrib/self-doesnt-match-blob.sub.html.ini create mode 100644 testing/web-platform/meta/content-security-policy/blink-contrib/star-doesnt-match-blob.sub.html.ini create mode 100644 testing/web-platform/meta/content-security-policy/child-src/child-src-worker-blocked.sub.html.ini create mode 100644 testing/web-platform/meta/mixed-content/blockable/http-csp/cross-origin-http/worker-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html.ini create mode 100644 testing/web-platform/meta/mixed-content/blockable/http-csp/cross-origin-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html.ini create mode 100644 testing/web-platform/meta/mixed-content/blockable/http-csp/cross-origin-http/worker-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html.ini create mode 100644 testing/web-platform/meta/mixed-content/blockable/http-csp/same-host-http/worker-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html.ini create mode 100644 testing/web-platform/meta/mixed-content/blockable/http-csp/same-host-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html.ini create mode 100644 testing/web-platform/meta/mixed-content/blockable/http-csp/same-host-http/worker-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html.ini create mode 100644 testing/web-platform/meta/mixed-content/blockable/meta-csp/cross-origin-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html.ini create mode 100644 testing/web-platform/meta/mixed-content/blockable/meta-csp/same-host-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html.ini create mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/worker-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini create mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/worker-request/top-level/no-redirect/no-opt-in-blocks.https.html.ini create mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/cross-origin-http/worker-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini create mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/worker-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html.ini create mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/worker-request/top-level/no-redirect/no-opt-in-blocks.https.html.ini create mode 100644 testing/web-platform/meta/mixed-content/blockable/no-opt-in/same-host-http/worker-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html.ini create mode 100644 testing/web-platform/meta/workers/Worker_cross_origin_security_err.htm.ini delete mode 100644 testing/web-platform/meta/workers/interfaces/WorkerUtils/importScripts/006.html.ini diff --git a/b2g/components/LogCapture.jsm b/b2g/components/LogCapture.jsm index 2170d1f597..803028d574 100644 --- a/b2g/components/LogCapture.jsm +++ b/b2g/components/LogCapture.jsm @@ -10,6 +10,7 @@ const Cu = Components.utils; const Ci = Components.interfaces; const Cc = Components.classes; +Cu.importGlobalProperties(['FileReader']); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm"); @@ -198,9 +199,7 @@ var LogCapture = { try { this.ensureLoaded(); - let fr = Cc["@mozilla.org/files/filereader;1"] - .createInstance(Ci.nsIDOMFileReader); - + let fr = new FileReader(); fr.onload = function(evt) { deferred.resolve(new Uint8Array(evt.target.result)); }; diff --git a/build/clang-plugin/clang-plugin.cpp b/build/clang-plugin/clang-plugin.cpp index 8cab4b4458..bc2ce02e0e 100644 --- a/build/clang-plugin/clang-plugin.cpp +++ b/build/clang-plugin/clang-plugin.cpp @@ -164,6 +164,7 @@ bool isInIgnoredNamespaceForImplicitCtor(const Decl *decl) { name == "__gnu_cxx" || // gnu C++ lib name == "boost" || // boost name == "webrtc" || // upstream webrtc + name == "rtc" || // upstream webrtc 'base' package name.substr(0, 4) == "icu_" || // icu name == "google" || // protobuf name == "google_breakpad" || // breakpad diff --git a/build/gyp.mozbuild b/build/gyp.mozbuild index be53d0defc..55be1cea12 100644 --- a/build/gyp.mozbuild +++ b/build/gyp.mozbuild @@ -5,6 +5,8 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. gyp_vars = { + 'lsan': 0, + 'asan': 0, 'build_with_mozilla': 1, 'build_with_chromium': 0, 'use_official_google_api_keys': 0, @@ -27,14 +29,14 @@ gyp_vars = { 'build_libyuv': 0, 'build_libvpx': 0, 'build_ssl': 0, + 'build_json': 0, + 'build_icu': 0, + 'build_opus': 0, 'libyuv_dir': '/media/libyuv', 'yuv_disable_avx2': 0 if CONFIG['HAVE_X86_AVX2'] else 1, # don't use openssl 'use_openssl': 0, - # saves 4MB when webrtc_trace is off - 'enable_lazy_trace_alloc': 1 if CONFIG['RELEASE_BUILD'] else 0, - 'use_x11': 1 if CONFIG['MOZ_X11'] else 0, 'use_glib': 1 if CONFIG['GLIB_LIBS'] else 0, @@ -60,7 +62,9 @@ gyp_vars = { 'include_opus': 1, 'include_g722': 1, 'include_ilbc': 0, - 'include_isac': 0, + # We turn on ISAC because the AGC uses parts of it, and depend on the + # linker to throw away uneeded bits. + 'include_isac': 1, 'include_pcm16b': 1, } diff --git a/dom/apps/ImportExport.jsm b/dom/apps/ImportExport.jsm index 8cfbd160ae..e2797084eb 100644 --- a/dom/apps/ImportExport.jsm +++ b/dom/apps/ImportExport.jsm @@ -15,7 +15,7 @@ Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Webapps.jsm"); Cu.import("resource://gre/modules/MessageBroadcaster.jsm"); -Cu.importGlobalProperties(['File']); +Cu.importGlobalProperties(['File', 'FileReader']); XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", "resource://gre/modules/FileUtils.jsm"); @@ -255,8 +255,7 @@ this.ImportExport = { debug("_writeBlobToTempFile"); let path; return new Promise((aResolve, aReject) => { - let reader = Cc['@mozilla.org/files/filereader;1'] - .createInstance(Ci.nsIDOMFileReader); + let reader = new FileReader(); reader.onloadend = () => { path = OS.Path.join(OS.Constants.Path.tmpDir, "app-blob.zip"); debug("onloadend path=" + path); diff --git a/dom/base/BlobSet.h b/dom/base/BlobSet.h index 3a0596282d..8ca8f4aa43 100644 --- a/dom/base/BlobSet.h +++ b/dom/base/BlobSet.h @@ -32,7 +32,8 @@ public: nsTArray>& GetBlobImpls() { Flush(); return mBlobImpls; } already_AddRefed GetBlobInternal(nsISupports* aParent, - const nsACString& aContentType); + const nsACString& aContentType, + ErrorResult& aRv); protected: bool ExpandBufferSize(uint64_t aSize) diff --git a/dom/base/ChildIterator.cpp b/dom/base/ChildIterator.cpp index fef7f582d4..13dd9fc66f 100644 --- a/dom/base/ChildIterator.cpp +++ b/dom/base/ChildIterator.cpp @@ -190,6 +190,30 @@ FlattenedChildIterator::Init(bool aIgnoreXBL) } } +void +ExplicitChildIterator::Seek(nsIContent* aChildToFind) +{ + if (aChildToFind->GetParent() == mParent && + !aChildToFind->IsRootOfAnonymousSubtree()) { + // Fast path: just point ourselves to aChildToFind, which is a + // normal DOM child of ours. + MOZ_ASSERT(!ShadowRoot::IsShadowInsertionPoint(aChildToFind)); + MOZ_ASSERT(!nsContentUtils::IsContentInsertionPoint(aChildToFind)); + mChild = aChildToFind; + mIndexInInserted = 0; + mShadowIterator = nullptr; + mDefaultChild = nullptr; + mIsFirst = false; + return; + } + + // Can we add more fast paths here based on whether the parent of aChildToFind + // is a shadow insertion point or content insertion point? + + // Slow path: just walk all our kids. + Seek(aChildToFind, nullptr); +} + nsIContent* ExplicitChildIterator::Get() { diff --git a/dom/base/ChildIterator.h b/dom/base/ChildIterator.h index def339e038..dbe6def3cf 100644 --- a/dom/base/ChildIterator.h +++ b/dom/base/ChildIterator.h @@ -60,16 +60,24 @@ public: nsIContent* GetNextChild(); - // Looks for aChildToFind respecting insertion points until aChildToFind + // Looks for aChildToFind respecting insertion points until aChildToFind is + // found. This version can take shortcuts that the two-argument version + // can't, so can be faster (and in fact can be O(1) instead of O(N) in many + // cases). + void Seek(nsIContent* aChildToFind); + + // Looks for aChildToFind respecting insertion points until aChildToFind is found. // or aBound is found. If aBound is nullptr then the seek is unbounded. Returns // whether aChildToFind was found as an explicit child prior to encountering // aBound. - bool Seek(nsIContent* aChildToFind, nsIContent* aBound = nullptr) + bool Seek(nsIContent* aChildToFind, nsIContent* aBound) { // It would be nice to assert that we find aChildToFind, but bz thinks that // we might not find aChildToFind when called from ContentInserted // if first-letter frames are about. + // We can't easily take shortcuts here because we'd have to have a way to + // compare aChildToFind to aBound. nsIContent* child; do { child = GetNextChild(); diff --git a/dom/base/Console.cpp b/dom/base/Console.cpp index 38e580459f..e1b35a9728 100644 --- a/dom/base/Console.cpp +++ b/dom/base/Console.cpp @@ -18,6 +18,7 @@ #include "nsDOMNavigationTiming.h" #include "nsGlobalWindow.h" #include "nsJSUtils.h" +#include "nsNetUtil.h" #include "nsPerformance.h" #include "ScriptSettings.h" #include "WorkerPrivate.h" @@ -34,15 +35,12 @@ #include "nsIInterfaceRequestorUtils.h" #include "nsILoadContext.h" #include "nsIProgrammingLanguage.h" +#include "nsISensitiveInfoHiddenURI.h" #include "nsIServiceManager.h" #include "nsISupportsPrimitives.h" #include "nsIWebNavigation.h" #include "nsIXPConnect.h" -#ifdef MOZ_ENABLE_PROFILER_SPS -#include "nsIProfiler.h" -#endif - // The maximum allowed number of concurrent timers per page. #define MAX_PAGE_TIMERS 10000 @@ -240,7 +238,7 @@ public: } private: - NS_IMETHOD Run() + NS_IMETHOD Run() override { AssertIsOnMainThread(); @@ -311,7 +309,9 @@ private: MOZ_ASSERT(aWindow->IsInnerWindow()); nsPIDOMWindow* outerWindow = aWindow->GetOuterWindow(); - MOZ_ASSERT(outerWindow); + if (NS_WARN_IF(!outerWindow)) { + return; + } RunConsole(jsapi.cx(), outerWindow, aWindow); } @@ -697,9 +697,13 @@ Console::Console(nsPIDOMWindow* aWindow) MOZ_ASSERT(mWindow->IsInnerWindow()); mInnerID = mWindow->WindowID(); + // Without outerwindow any console message coming from this object will not + // shown in the devtools webconsole. But this should be fine because + // probably we are shutting down, or the window is CCed/GCed. nsPIDOMWindow* outerWindow = mWindow->GetOuterWindow(); - MOZ_ASSERT(outerWindow); - mOuterID = outerWindow->WindowID(); + if (outerWindow) { + mOuterID = outerWindow->WindowID(); + } } if (NS_IsMainThread()) { @@ -829,23 +833,6 @@ Console::TimeStamp(JSContext* aCx, const JS::Handle aData) return; } -#ifdef MOZ_ENABLE_PROFILER_SPS - if (aData.isString() && NS_IsMainThread()) { - if (!mProfiler) { - mProfiler = do_GetService("@mozilla.org/tools/profiler;1"); - } - if (mProfiler) { - bool active = false; - if (NS_SUCCEEDED(mProfiler->IsActive(&active)) && active) { - nsAutoJSString stringValue; - if (stringValue.init(aCx, aData)) { - mProfiler->AddMarker(NS_ConvertUTF16toUTF8(stringValue).get()); - } - } - } - } -#endif - Method(aCx, MethodTimeStamp, NS_LITERAL_STRING("timeStamp"), data); } @@ -1222,6 +1209,19 @@ Console::ProcessCallData(ConsoleCallData* aData) event.mLevel = aData->mMethodString; event.mFilename = frame.mFilename; + + nsCOMPtr filenameURI; + nsAutoCString pass; + if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(filenameURI), frame.mFilename)) && + NS_SUCCEEDED(filenameURI->GetPassword(pass)) && !pass.IsEmpty()) { + nsCOMPtr safeURI = do_QueryInterface(filenameURI); + nsAutoCString spec; + if (safeURI && + NS_SUCCEEDED(safeURI->GetSensitiveInfoHiddenSpec(spec))) { + CopyUTF8toUTF16(spec, event.mFilename); + } + } + event.mLineNumber = frame.mLineNumber; event.mColumnNumber = frame.mColumnNumber; event.mFunctionName = frame.mFunctionName; @@ -1389,7 +1389,7 @@ FlushOutput(JSContext* aCx, Sequence& aSequence, nsString &aOutput) return true; } -} // anonymous namespace +} // namespace bool Console::ProcessArguments(JSContext* aCx, @@ -1519,6 +1519,12 @@ Console::ProcessArguments(JSContext* aCx, case 'c': { + // If there isn't any output but there's already a style, then + // discard the previous style and use the next one instead. + if (output.IsEmpty() && !aStyles.IsEmpty()) { + aStyles.TruncateLength(aStyles.Length() - 1); + } + if (!FlushOutput(aCx, aSequence, output)) { return false; } diff --git a/dom/base/Console.h b/dom/base/Console.h index 506a2c3dac..394278b063 100644 --- a/dom/base/Console.h +++ b/dom/base/Console.h @@ -20,7 +20,6 @@ class nsIConsoleAPIStorage; class nsIPrincipal; -class nsIProfiler; namespace mozilla { namespace dom { @@ -205,9 +204,6 @@ private: nsCOMPtr mWindow; nsCOMPtr mStorage; RefPtr mSandbox; -#ifdef MOZ_ENABLE_PROFILER_SPS - nsCOMPtr mProfiler; -#endif nsDataHashtable mTimerRegistry; nsDataHashtable mCounterRegistry; diff --git a/dom/base/File.cpp b/dom/base/File.cpp index e3df761998..5cc20a76e4 100644 --- a/dom/base/File.cpp +++ b/dom/base/File.cpp @@ -257,7 +257,7 @@ Blob::ToFile() } already_AddRefed -Blob::ToFile(const nsAString& aName) const +Blob::ToFile(const nsAString& aName, ErrorResult& aRv) const { nsAutoTArray, 1> blobImpls; blobImpls.AppendElement(mImpl); @@ -266,7 +266,10 @@ Blob::ToFile(const nsAString& aName) const mImpl->GetType(contentType); RefPtr impl = - new MultipartBlobImpl(blobImpls, aName, contentType); + MultipartBlobImpl::Create(blobImpls, aName, contentType, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } RefPtr file = new File(mParent, impl); return file.forget(); @@ -347,7 +350,11 @@ Blob::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv) { RefPtr impl = new MultipartBlobImpl(); - impl->InitializeBlob(); + impl->InitializeBlob(aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + MOZ_ASSERT(!impl->IsFile()); RefPtr blob = Blob::Create(aGlobal.GetAsSupports(), impl); @@ -851,7 +858,7 @@ BlobImplFile::GetMozFullPathInternal(nsAString& aFilename, ErrorResult& aRv) con uint64_t BlobImplFile::GetSize(ErrorResult& aRv) { - if (IsSizeUnknown()) { + if (BlobImplBase::IsSizeUnknown()) { NS_ASSERTION(mWholeFile, "Should only use lazy size when using the whole file"); int64_t fileSize; @@ -902,7 +909,7 @@ int64_t BlobImplFile::GetLastModified(ErrorResult& aRv) { NS_ASSERTION(mIsFile, "Should only be called on files"); - if (IsDateUnknown()) { + if (BlobImplBase::IsDateUnknown()) { PRTime msecs; aRv = mFile->GetLastModifiedTime(&msecs); if (NS_WARN_IF(aRv.Failed())) { @@ -1121,11 +1128,19 @@ BlobImplTemporaryBlob::GetInternalStream(nsIInputStream** aStream, // BlobSet implementation already_AddRefed -BlobSet::GetBlobInternal(nsISupports* aParent, const nsACString& aContentType) +BlobSet::GetBlobInternal(nsISupports* aParent, + const nsACString& aContentType, + ErrorResult& aRv) { - RefPtr blob = Blob::Create(aParent, - new MultipartBlobImpl(GetBlobImpls(), - NS_ConvertASCIItoUTF16(aContentType))); + RefPtr blobImpl = + MultipartBlobImpl::Create(GetBlobImpls(), + NS_ConvertASCIItoUTF16(aContentType), + aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + RefPtr blob = Blob::Create(aParent, blobImpl); return blob.forget(); } diff --git a/dom/base/File.h b/dom/base/File.h index bb1a2cb5c9..25550faab4 100644 --- a/dom/base/File.h +++ b/dom/base/File.h @@ -118,7 +118,8 @@ public: // This method creates a new File object with the given name and the same // BlobImpl. - already_AddRefed ToFile(const nsAString& aName) const; + already_AddRefed ToFile(const nsAString& aName, + ErrorResult& aRv) const; already_AddRefed CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType, @@ -798,6 +799,10 @@ public: virtual void LookupAndCacheIsDirectory() override; + // We always have size and date for this kind of blob. + virtual bool IsSizeUnknown() const override { return false; } + virtual bool IsDateUnknown() const override { return false; } + protected: virtual ~BlobImplFile() { if (mFile && mIsTemporary) { diff --git a/dom/base/FileIOObject.cpp b/dom/base/FileIOObject.cpp deleted file mode 100644 index 8c0c097b55..0000000000 --- a/dom/base/FileIOObject.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "FileIOObject.h" -#include "mozilla/dom/File.h" -#include "mozilla/dom/ProgressEvent.h" -#include "mozilla/EventDispatcher.h" -#include "nsComponentManagerUtils.h" -#include "nsError.h" -#include "nsIDOMEvent.h" - -#define ERROR_STR "error" -#define ABORT_STR "abort" -#define PROGRESS_STR "progress" - -namespace mozilla { -namespace dom { - -const uint64_t kUnknownSize = uint64_t(-1); - -NS_IMPL_ADDREF_INHERITED(FileIOObject, DOMEventTargetHelper) -NS_IMPL_RELEASE_INHERITED(FileIOObject, DOMEventTargetHelper) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FileIOObject) - NS_INTERFACE_MAP_ENTRY(nsITimerCallback) - NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback) -NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) - -NS_IMPL_CYCLE_COLLECTION_CLASS(FileIOObject) - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FileIOObject, - DOMEventTargetHelper) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mProgressNotifier) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FileIOObject, - DOMEventTargetHelper) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mProgressNotifier) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mError) -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMPL_EVENT_HANDLER(FileIOObject, abort) -NS_IMPL_EVENT_HANDLER(FileIOObject, error) -NS_IMPL_EVENT_HANDLER(FileIOObject, progress) - -FileIOObject::FileIOObject() - : mProgressEventWasDelayed(false), - mTimerIsActive(false), - mReadyState(0), - mTotal(0), mTransferred(0) -{} - -FileIOObject::~FileIOObject() -{} - -void -FileIOObject::StartProgressEventTimer() -{ - if (!mProgressNotifier) { - mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID); - } - if (mProgressNotifier) { - mProgressEventWasDelayed = false; - mTimerIsActive = true; - mProgressNotifier->Cancel(); - mProgressNotifier->InitWithCallback(this, NS_PROGRESS_EVENT_INTERVAL, - nsITimer::TYPE_ONE_SHOT); - } -} - -void -FileIOObject::ClearProgressEventTimer() -{ - mProgressEventWasDelayed = false; - mTimerIsActive = false; - if (mProgressNotifier) { - mProgressNotifier->Cancel(); - } -} - -void -FileIOObject::DispatchError(nsresult rv, nsAString& finalEvent) -{ - // Set the status attribute, and dispatch the error event - switch (rv) { - case NS_ERROR_FILE_NOT_FOUND: - mError = new DOMError(GetOwner(), NS_LITERAL_STRING("NotFoundError")); - break; - case NS_ERROR_FILE_ACCESS_DENIED: - mError = new DOMError(GetOwner(), NS_LITERAL_STRING("SecurityError")); - break; - default: - mError = new DOMError(GetOwner(), NS_LITERAL_STRING("NotReadableError")); - break; - } - - // Dispatch error event to signify load failure - DispatchProgressEvent(NS_LITERAL_STRING(ERROR_STR)); - DispatchProgressEvent(finalEvent); -} - -nsresult -FileIOObject::DispatchProgressEvent(const nsAString& aType) -{ - ProgressEventInit init; - init.mBubbles = false; - init.mCancelable = false; - init.mLoaded = mTransferred; - - if (mTotal != kUnknownSize) { - init.mLengthComputable = true; - init.mTotal = mTotal; - } else { - init.mLengthComputable = false; - init.mTotal = 0; - } - RefPtr event = - ProgressEvent::Constructor(this, aType, init); - event->SetTrusted(true); - - return DispatchDOMEvent(nullptr, event, nullptr, nullptr); -} - -// nsITimerCallback -NS_IMETHODIMP -FileIOObject::Notify(nsITimer* aTimer) -{ - nsresult rv; - mTimerIsActive = false; - - if (mProgressEventWasDelayed) { - rv = DispatchProgressEvent(NS_LITERAL_STRING("progress")); - NS_ENSURE_SUCCESS(rv, rv); - - StartProgressEventTimer(); - } - - return NS_OK; -} - -// InputStreamCallback -NS_IMETHODIMP -FileIOObject::OnInputStreamReady(nsIAsyncInputStream* aStream) -{ - if (mReadyState != 1 || aStream != mAsyncStream) { - return NS_OK; - } - - uint64_t aCount; - nsresult rv = aStream->Available(&aCount); - - if (NS_SUCCEEDED(rv) && aCount) { - rv = DoReadData(aStream, aCount); - } - - if (NS_SUCCEEDED(rv)) { - rv = DoAsyncWait(aStream); - } - - if (NS_FAILED(rv) || !aCount) { - if (rv == NS_BASE_STREAM_CLOSED) { - rv = NS_OK; - } - return OnLoadEnd(rv); - } - - mTransferred += aCount; - - //Notify the timer is the appropriate timeframe has passed - if (mTimerIsActive) { - mProgressEventWasDelayed = true; - } else { - rv = DispatchProgressEvent(NS_LITERAL_STRING(PROGRESS_STR)); - NS_ENSURE_SUCCESS(rv, rv); - - StartProgressEventTimer(); - } - - return NS_OK; -} - -nsresult -FileIOObject::OnLoadEnd(nsresult aStatus) -{ - // Cancel the progress event timer - ClearProgressEventTimer(); - - // FileIOObject must be in DONE stage after an operation - mReadyState = 2; - - nsString successEvent, termEvent; - nsresult rv = DoOnLoadEnd(aStatus, successEvent, termEvent); - NS_ENSURE_SUCCESS(rv, rv); - - // Set the status field as appropriate - if (NS_FAILED(aStatus)) { - DispatchError(aStatus, termEvent); - return NS_OK; - } - - // Dispatch event to signify end of a successful operation - DispatchProgressEvent(successEvent); - DispatchProgressEvent(termEvent); - - return NS_OK; -} - -nsresult -FileIOObject::DoAsyncWait(nsIAsyncInputStream* aStream) -{ - return aStream->AsyncWait(this, - /* aFlags*/ 0, - /* aRequestedCount */ 0, - NS_GetCurrentThread()); -} - -void -FileIOObject::Abort(ErrorResult& aRv) -{ - if (mReadyState != 1) { - // XXX The spec doesn't say this - aRv.Throw(NS_ERROR_DOM_FILE_ABORT_ERR); - return; - } - - ClearProgressEventTimer(); - - mReadyState = 2; // There are DONE constants on multiple interfaces, - // but they all have value 2. - // XXX The spec doesn't say this - mError = new DOMError(GetOwner(), NS_LITERAL_STRING("AbortError")); - - nsString finalEvent; - DoAbort(finalEvent); - - // Dispatch the events - DispatchProgressEvent(NS_LITERAL_STRING(ABORT_STR)); - DispatchProgressEvent(finalEvent); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/base/FileIOObject.h b/dom/base/FileIOObject.h deleted file mode 100644 index 769f09b041..0000000000 --- a/dom/base/FileIOObject.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef FileIOObject_h__ -#define FileIOObject_h__ - -#include "mozilla/DOMEventTargetHelper.h" -#include "nsIFile.h" -#include "nsITimer.h" -#include "nsCOMPtr.h" -#include "nsIAsyncInputStream.h" - -#include "mozilla/dom/DOMError.h" - -#define NS_PROGRESS_EVENT_INTERVAL 50 - -namespace mozilla { - -class ErrorResult; - -namespace dom { - -extern const uint64_t kUnknownSize; - -// A common base class for FileReader and FileSaver - -class FileIOObject : public DOMEventTargetHelper, - public nsIInputStreamCallback, - public nsITimerCallback -{ -public: - FileIOObject(); - - NS_DECL_ISUPPORTS_INHERITED - - // Common methods - void Abort(ErrorResult& aRv); - uint16_t ReadyState() const - { - return mReadyState; - } - DOMError* GetError() const - { - return mError; - } - - NS_METHOD GetOnabort(JSContext* aCx, JS::MutableHandle aValue); - NS_METHOD SetOnabort(JSContext* aCx, JS::Handle aValue); - NS_METHOD GetOnerror(JSContext* aCx, JS::MutableHandle aValue); - NS_METHOD SetOnerror(JSContext* aCx, JS::Handle aValue); - NS_METHOD GetOnprogress(JSContext* aCx, JS::MutableHandle aValue); - NS_METHOD SetOnprogress(JSContext* aCx, JS::Handle aValue); - - IMPL_EVENT_HANDLER(abort) - IMPL_EVENT_HANDLER(error) - IMPL_EVENT_HANDLER(progress) - - NS_DECL_NSITIMERCALLBACK - - NS_DECL_NSIINPUTSTREAMCALLBACK - - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FileIOObject, DOMEventTargetHelper) - -protected: - virtual ~FileIOObject(); - - // Implemented by the derived class to do whatever it needs to do for abort - virtual void DoAbort(nsAString& aEvent) = 0; - - virtual nsresult DoReadData(nsIAsyncInputStream* aStream, uint64_t aCount) = 0; - - virtual nsresult DoOnLoadEnd(nsresult aStatus, nsAString& aSuccessEvent, - nsAString& aTerminationEvent) = 0; - - nsresult OnLoadEnd(nsresult aStatus); - nsresult DoAsyncWait(nsIAsyncInputStream* aStream); - - void StartProgressEventTimer(); - void ClearProgressEventTimer(); - void DispatchError(nsresult rv, nsAString& finalEvent); - nsresult DispatchProgressEvent(const nsAString& aType); - - nsCOMPtr mProgressNotifier; - bool mProgressEventWasDelayed; - bool mTimerIsActive; - - nsCOMPtr mAsyncStream; - - RefPtr mError; - - uint16_t mReadyState; - - uint64_t mTotal; - uint64_t mTransferred; -}; - -} // namespace dom -} // namespace mozilla - -#endif diff --git a/dom/base/nsDOMFileReader.cpp b/dom/base/FileReader.cpp similarity index 50% rename from dom/base/nsDOMFileReader.cpp rename to dom/base/FileReader.cpp index a5b1b82776..0ad85b8e70 100644 --- a/dom/base/nsDOMFileReader.cpp +++ b/dom/base/FileReader.cpp @@ -4,7 +4,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "nsDOMFileReader.h" +#include "FileReader.h" #include "nsContentCID.h" #include "nsContentUtils.h" @@ -22,6 +22,7 @@ #include "mozilla/dom/EncodingUtils.h" #include "mozilla/dom/File.h" #include "mozilla/dom/FileReaderBinding.h" +#include "mozilla/dom/ProgressEvent.h" #include "xpcpublic.h" #include "nsDOMJSUtils.h" @@ -30,226 +31,137 @@ #include "nsITransport.h" #include "nsIStreamTransportService.h" -using namespace mozilla; -using namespace mozilla::dom; +namespace mozilla { +namespace dom { +#define ABORT_STR "abort" #define LOAD_STR "load" #define LOADSTART_STR "loadstart" #define LOADEND_STR "loadend" +#define ERROR_STR "error" +#define PROGRESS_STR "progress" + +const uint64_t kUnknownSize = uint64_t(-1); static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID); -NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileReader) +NS_IMPL_CYCLE_COLLECTION_CLASS(FileReader) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMFileReader, - FileIOObject) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FileReader, + DOMEventTargetHelper) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBlob) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mProgressNotifier) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMFileReader, - FileIOObject) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FileReader, + DOMEventTargetHelper) tmp->mResultArrayBuffer = nullptr; NS_IMPL_CYCLE_COLLECTION_UNLINK(mBlob) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mProgressNotifier) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mError) NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsDOMFileReader, +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(FileReader, DOMEventTargetHelper) NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mResultArrayBuffer) NS_IMPL_CYCLE_COLLECTION_TRACE_END -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMFileReader) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsIDOMFileReader) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FileReader) + NS_INTERFACE_MAP_ENTRY(nsITimerCallback) + NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) -NS_INTERFACE_MAP_END_INHERITING(FileIOObject) +NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) -NS_IMPL_ADDREF_INHERITED(nsDOMFileReader, FileIOObject) -NS_IMPL_RELEASE_INHERITED(nsDOMFileReader, FileIOObject) - -NS_IMPL_EVENT_HANDLER(nsDOMFileReader, load) -NS_IMPL_EVENT_HANDLER(nsDOMFileReader, loadend) -NS_IMPL_EVENT_HANDLER(nsDOMFileReader, loadstart) -NS_IMPL_FORWARD_EVENT_HANDLER(nsDOMFileReader, abort, FileIOObject) -NS_IMPL_FORWARD_EVENT_HANDLER(nsDOMFileReader, progress, FileIOObject) -NS_IMPL_FORWARD_EVENT_HANDLER(nsDOMFileReader, error, FileIOObject) +NS_IMPL_ADDREF_INHERITED(FileReader, DOMEventTargetHelper) +NS_IMPL_RELEASE_INHERITED(FileReader, DOMEventTargetHelper) void -nsDOMFileReader::RootResultArrayBuffer() +FileReader::RootResultArrayBuffer() { mozilla::HoldJSObjects(this); } -//nsDOMFileReader constructors/initializers +//FileReader constructors/initializers -nsDOMFileReader::nsDOMFileReader() - : mFileData(nullptr), - mDataLen(0), mDataFormat(FILE_AS_BINARY), - mResultArrayBuffer(nullptr) +FileReader::FileReader(nsPIDOMWindow* aWindow) + : DOMEventTargetHelper(aWindow) + , mFileData(nullptr) + , mDataLen(0) + , mDataFormat(FILE_AS_BINARY) + , mResultArrayBuffer(nullptr) + , mProgressEventWasDelayed(false) + , mTimerIsActive(false) + , mReadyState(EMPTY) + , mTotal(0) + , mTransferred(0) { SetDOMStringToNull(mResult); } -nsDOMFileReader::~nsDOMFileReader() +FileReader::~FileReader() { FreeFileData(); mResultArrayBuffer = nullptr; - mozilla::DropJSObjects(this); + DropJSObjects(this); } - -/** - * This Init method is called from the factory constructor. - */ -nsresult -nsDOMFileReader::Init() +/* static */ already_AddRefed +FileReader::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv) { - // Instead of grabbing some random global from the context stack, - // let's use the default one (junk scope) for now. - // We should move away from this Init... - BindToOwner(xpc::NativeGlobal(xpc::PrivilegedJunkScope())); - return NS_OK; -} - -/* static */ already_AddRefed -nsDOMFileReader::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv) -{ - RefPtr fileReader = new nsDOMFileReader(); - + // The owner can be null when this object is used by chrome code. nsCOMPtr owner = do_QueryInterface(aGlobal.GetAsSupports()); - if (!owner) { - NS_WARNING("Unexpected owner"); - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; + RefPtr fileReader = new FileReader(owner); + + if (!owner && nsContentUtils::IsCallerChrome()) { + // Instead of grabbing some random global from the context stack, + // let's use the default one (junk scope) for now. + // We should move away from this Init... + fileReader->BindToOwner(xpc::NativeGlobal(xpc::PrivilegedJunkScope())); } - fileReader->BindToOwner(owner); return fileReader.forget(); } // nsIInterfaceRequestor NS_IMETHODIMP -nsDOMFileReader::GetInterface(const nsIID & aIID, void **aResult) +FileReader::GetInterface(const nsIID & aIID, void **aResult) { return QueryInterface(aIID, aResult); } -// nsIDOMFileReader - -NS_IMETHODIMP -nsDOMFileReader::GetReadyState(uint16_t *aReadyState) -{ - *aReadyState = ReadyState(); - return NS_OK; -} - void -nsDOMFileReader::GetResult(JSContext* aCx, JS::MutableHandle aResult, - ErrorResult& aRv) -{ - aRv = GetResult(aCx, aResult); -} - -NS_IMETHODIMP -nsDOMFileReader::GetResult(JSContext* aCx, JS::MutableHandle aResult) +FileReader::GetResult(JSContext* aCx, + JS::MutableHandle aResult, + ErrorResult& aRv) { JS::Rooted result(aCx); + if (mDataFormat == FILE_AS_ARRAYBUFFER) { - if (mReadyState == nsIDOMFileReader::DONE && mResultArrayBuffer) { + if (mReadyState == DONE && mResultArrayBuffer) { result.setObject(*mResultArrayBuffer); } else { result.setNull(); } + if (!JS_WrapValue(aCx, &result)) { - return NS_ERROR_FAILURE; + aRv.Throw(NS_ERROR_FAILURE); + return; } + aResult.set(result); - return NS_OK; + return; } nsString tmpResult = mResult; if (!xpc::StringToJsval(aCx, tmpResult, aResult)) { - return NS_ERROR_FAILURE; + aRv.Throw(NS_ERROR_FAILURE); + return; } - return NS_OK; } -NS_IMETHODIMP -nsDOMFileReader::GetError(nsISupports** aError) -{ - NS_IF_ADDREF(*aError = GetError()); - return NS_OK; -} - -NS_IMETHODIMP -nsDOMFileReader::ReadAsArrayBuffer(nsIDOMBlob* aBlob, JSContext* aCx) -{ - NS_ENSURE_TRUE(aBlob, NS_ERROR_NULL_POINTER); - ErrorResult rv; - RefPtr blob = static_cast(aBlob); - ReadAsArrayBuffer(aCx, *blob, rv); - return rv.StealNSResult(); -} - -NS_IMETHODIMP -nsDOMFileReader::ReadAsBinaryString(nsIDOMBlob* aBlob) -{ - NS_ENSURE_TRUE(aBlob, NS_ERROR_NULL_POINTER); - ErrorResult rv; - RefPtr blob = static_cast(aBlob); - ReadAsBinaryString(*blob, rv); - return rv.StealNSResult(); -} - -NS_IMETHODIMP -nsDOMFileReader::ReadAsText(nsIDOMBlob* aBlob, - const nsAString &aCharset) -{ - NS_ENSURE_TRUE(aBlob, NS_ERROR_NULL_POINTER); - ErrorResult rv; - RefPtr blob = static_cast(aBlob); - ReadAsText(*blob, aCharset, rv); - return rv.StealNSResult(); -} - -NS_IMETHODIMP -nsDOMFileReader::ReadAsDataURL(nsIDOMBlob* aBlob) -{ - NS_ENSURE_TRUE(aBlob, NS_ERROR_NULL_POINTER); - ErrorResult rv; - RefPtr blob = static_cast(aBlob); - ReadAsDataURL(*blob, rv); - return rv.StealNSResult(); -} - -NS_IMETHODIMP -nsDOMFileReader::Abort() -{ - ErrorResult rv; - FileIOObject::Abort(rv); - return rv.StealNSResult(); -} - -/* virtual */ void -nsDOMFileReader::DoAbort(nsAString& aEvent) -{ - // Revert status and result attributes - SetDOMStringToNull(mResult); - mResultArrayBuffer = nullptr; - - mAsyncStream = nullptr; - mBlob = nullptr; - - //Clean up memory buffer - FreeFileData(); - - // Tell the base class which event to dispatch - aEvent = NS_LITERAL_STRING(LOADEND_STR); -} - -static -NS_METHOD +static NS_IMETHODIMP ReadFuncBinaryString(nsIInputStream* in, void* closure, const char* fromRawSegment, @@ -271,11 +183,10 @@ ReadFuncBinaryString(nsIInputStream* in, } nsresult -nsDOMFileReader::DoOnLoadEnd(nsresult aStatus, - nsAString& aSuccessEvent, - nsAString& aTerminationEvent) +FileReader::DoOnLoadEnd(nsresult aStatus, + nsAString& aSuccessEvent, + nsAString& aTerminationEvent) { - // Make sure we drop all the objects that could hold files open now. nsCOMPtr stream; mAsyncStream.swap(stream); @@ -283,25 +194,34 @@ nsDOMFileReader::DoOnLoadEnd(nsresult aStatus, RefPtr blob; mBlob.swap(blob); - aSuccessEvent = NS_LITERAL_STRING(LOAD_STR); - aTerminationEvent = NS_LITERAL_STRING(LOADEND_STR); - // Clear out the data if necessary if (NS_FAILED(aStatus)) { FreeFileData(); return NS_OK; } + // In case we read a different number of bytes, we can assume that the + // underlying storage has changed. We should not continue. + if (mDataLen != mTotal) { + DispatchError(NS_ERROR_FAILURE, aTerminationEvent); + FreeFileData(); + return NS_ERROR_FAILURE; + } + + aSuccessEvent = NS_LITERAL_STRING(LOAD_STR); + aTerminationEvent = NS_LITERAL_STRING(LOADEND_STR); + nsresult rv = NS_OK; switch (mDataFormat) { case FILE_AS_ARRAYBUFFER: { AutoJSAPI jsapi; - if (NS_WARN_IF(!jsapi.Init(mozilla::DOMEventTargetHelper::GetParentObject()))) { + if (NS_WARN_IF(!jsapi.Init(DOMEventTargetHelper::GetParentObject()))) { + FreeFileData(); return NS_ERROR_FAILURE; } RootResultArrayBuffer(); - mResultArrayBuffer = JS_NewArrayBufferWithContents(jsapi.cx(), mTotal, mFileData); + mResultArrayBuffer = JS_NewArrayBufferWithContents(jsapi.cx(), mDataLen, mFileData); if (!mResultArrayBuffer) { JS_ClearPendingException(jsapi.cx()); rv = NS_ERROR_OUT_OF_MEMORY; @@ -336,15 +256,14 @@ nsDOMFileReader::DoOnLoadEnd(nsresult aStatus, } nsresult -nsDOMFileReader::DoReadData(nsIAsyncInputStream* aStream, uint64_t aCount) +FileReader::DoReadData(nsIAsyncInputStream* aStream, uint64_t aCount) { MOZ_ASSERT(aStream); if (mDataFormat == FILE_AS_BINARY) { //Continuously update our binary string as data comes in uint32_t oldLen = mResult.Length(); - NS_ASSERTION(mResult.Length() == mDataLen, - "unexpected mResult length"); + NS_ASSERTION(mResult.Length() == mDataLen, "unexpected mResult length"); if (uint64_t(oldLen) + aCount > UINT32_MAX) return NS_ERROR_OUT_OF_MEMORY; char16_t *buf = nullptr; @@ -379,18 +298,21 @@ nsDOMFileReader::DoReadData(nsIAsyncInputStream* aStream, uint64_t aCount) // Helper methods void -nsDOMFileReader::ReadFileContent(Blob& aBlob, - const nsAString &aCharset, - eDataFormat aDataFormat, - ErrorResult& aRv) +FileReader::ReadFileContent(Blob& aBlob, + const nsAString &aCharset, + eDataFormat aDataFormat, + ErrorResult& aRv) { //Implicit abort to clear any other activity going on - Abort(); + ErrorResult error; + Abort(error); + error.SuppressException(); + mError = nullptr; SetDOMStringToNull(mResult); mTransferred = 0; mTotal = 0; - mReadyState = nsIDOMFileReader::EMPTY; + mReadyState = EMPTY; FreeFileData(); mBlob = &aBlob; @@ -398,7 +320,6 @@ nsDOMFileReader::ReadFileContent(Blob& aBlob, CopyUTF16toUTF8(aCharset, mCharset); nsresult rv; - nsCOMPtr sts = do_GetService(kStreamTransportServiceCID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -413,23 +334,21 @@ nsDOMFileReader::ReadFileContent(Blob& aBlob, } nsCOMPtr transport; - rv = sts->CreateInputTransport(stream, - /* aStartOffset */ 0, - /* aReadLimit */ -1, - /* aCloseWhenDone */ true, - getter_AddRefs(transport)); - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(rv); + aRv = sts->CreateInputTransport(stream, + /* aStartOffset */ 0, + /* aReadLimit */ -1, + /* aCloseWhenDone */ true, + getter_AddRefs(transport)); + if (NS_WARN_IF(aRv.Failed())) { return; } nsCOMPtr wrapper; - rv = transport->OpenInputStream(/* aFlags */ 0, - /* aSegmentSize */ 0, - /* aSegmentCount */ 0, - getter_AddRefs(wrapper)); - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(rv); + aRv = transport->OpenInputStream(/* aFlags */ 0, + /* aSegmentSize */ 0, + /* aSegmentCount */ 0, + getter_AddRefs(wrapper)); + if (NS_WARN_IF(aRv.Failed())) { return; } @@ -442,14 +361,16 @@ nsDOMFileReader::ReadFileContent(Blob& aBlob, return; } - rv = DoAsyncWait(mAsyncStream); - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(rv); + aRv = mAsyncStream->AsyncWait(this, + /* aFlags*/ 0, + /* aRequestedCount */ 0, + NS_GetCurrentThread()); + if (NS_WARN_IF(aRv.Failed())) { return; } //FileReader should be in loading state here - mReadyState = nsIDOMFileReader::LOADING; + mReadyState = LOADING; DispatchProgressEvent(NS_LITERAL_STRING(LOADSTART_STR)); if (mDataFormat == FILE_AS_ARRAYBUFFER) { @@ -462,11 +383,11 @@ nsDOMFileReader::ReadFileContent(Blob& aBlob, } nsresult -nsDOMFileReader::GetAsText(Blob *aBlob, - const nsACString &aCharset, - const char *aFileData, - uint32_t aDataLen, - nsAString& aResult) +FileReader::GetAsText(Blob *aBlob, + const nsACString &aCharset, + const char *aFileData, + uint32_t aDataLen, + nsAString& aResult) { // The BOM sniffing is baked into the "decode" part of the Encoding // Standard, which the File API references. @@ -502,14 +423,14 @@ nsDOMFileReader::GetAsText(Blob *aBlob, } nsresult -nsDOMFileReader::GetAsDataURL(Blob *aBlob, - const char *aFileData, - uint32_t aDataLen, - nsAString& aResult) +FileReader::GetAsDataURL(Blob *aBlob, + const char *aFileData, + uint32_t aDataLen, + nsAString& aResult) { aResult.AssignLiteral("data:"); - nsString contentType; + nsAutoString contentType; aBlob->GetType(contentType); if (!contentType.IsEmpty()) { aResult.Append(contentType); @@ -530,7 +451,197 @@ nsDOMFileReader::GetAsDataURL(Blob *aBlob, } /* virtual */ JSObject* -nsDOMFileReader::WrapObject(JSContext* aCx, JS::Handle aGivenProto) +FileReader::WrapObject(JSContext* aCx, JS::Handle aGivenProto) { return FileReaderBinding::Wrap(aCx, this, aGivenProto); } + +void +FileReader::StartProgressEventTimer() +{ + if (!mProgressNotifier) { + mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID); + } + + if (mProgressNotifier) { + mProgressEventWasDelayed = false; + mTimerIsActive = true; + mProgressNotifier->Cancel(); + mProgressNotifier->InitWithCallback(this, NS_PROGRESS_EVENT_INTERVAL, + nsITimer::TYPE_ONE_SHOT); + } +} + +void +FileReader::ClearProgressEventTimer() +{ + mProgressEventWasDelayed = false; + mTimerIsActive = false; + if (mProgressNotifier) { + mProgressNotifier->Cancel(); + } +} + +void +FileReader::DispatchError(nsresult rv, nsAString& finalEvent) +{ + // Set the status attribute, and dispatch the error event + switch (rv) { + case NS_ERROR_FILE_NOT_FOUND: + mError = new DOMError(GetOwner(), NS_LITERAL_STRING("NotFoundError")); + break; + case NS_ERROR_FILE_ACCESS_DENIED: + mError = new DOMError(GetOwner(), NS_LITERAL_STRING("SecurityError")); + break; + default: + mError = new DOMError(GetOwner(), NS_LITERAL_STRING("NotReadableError")); + break; + } + + // Dispatch error event to signify load failure + DispatchProgressEvent(NS_LITERAL_STRING(ERROR_STR)); + DispatchProgressEvent(finalEvent); +} + +nsresult +FileReader::DispatchProgressEvent(const nsAString& aType) +{ + ProgressEventInit init; + init.mBubbles = false; + init.mCancelable = false; + init.mLoaded = mTransferred; + + if (mTotal != kUnknownSize) { + init.mLengthComputable = true; + init.mTotal = mTotal; + } else { + init.mLengthComputable = false; + init.mTotal = 0; + } + RefPtr event = + ProgressEvent::Constructor(this, aType, init); + event->SetTrusted(true); + + return DispatchDOMEvent(nullptr, event, nullptr, nullptr); +} + +// nsITimerCallback +NS_IMETHODIMP +FileReader::Notify(nsITimer* aTimer) +{ + nsresult rv; + mTimerIsActive = false; + + if (mProgressEventWasDelayed) { + rv = DispatchProgressEvent(NS_LITERAL_STRING("progress")); + NS_ENSURE_SUCCESS(rv, rv); + + StartProgressEventTimer(); + } + + return NS_OK; +} + +// InputStreamCallback +NS_IMETHODIMP +FileReader::OnInputStreamReady(nsIAsyncInputStream* aStream) +{ + if (mReadyState != LOADING || aStream != mAsyncStream) { + return NS_OK; + } + + uint64_t aCount; + nsresult rv = aStream->Available(&aCount); + + if (NS_SUCCEEDED(rv) && aCount) { + rv = DoReadData(aStream, aCount); + } + + if (NS_SUCCEEDED(rv)) { + rv = aStream->AsyncWait(this, + /* aFlags*/ 0, + /* aRequestedCount */ 0, + NS_GetCurrentThread()); + } + + if (NS_FAILED(rv) || !aCount) { + if (rv == NS_BASE_STREAM_CLOSED) { + rv = NS_OK; + } + return OnLoadEnd(rv); + } + + mTransferred += aCount; + + //Notify the timer is the appropriate timeframe has passed + if (mTimerIsActive) { + mProgressEventWasDelayed = true; + } else { + rv = DispatchProgressEvent(NS_LITERAL_STRING(PROGRESS_STR)); + NS_ENSURE_SUCCESS(rv, rv); + + StartProgressEventTimer(); + } + + return NS_OK; +} + +nsresult +FileReader::OnLoadEnd(nsresult aStatus) +{ + // Cancel the progress event timer + ClearProgressEventTimer(); + + // FileReader must be in DONE stage after an operation + mReadyState = DONE; + + nsAutoString successEvent, termEvent; + nsresult rv = DoOnLoadEnd(aStatus, successEvent, termEvent); + NS_ENSURE_SUCCESS(rv, rv); + + // Set the status field as appropriate + if (NS_FAILED(aStatus)) { + DispatchError(aStatus, termEvent); + return NS_OK; + } + + // Dispatch event to signify end of a successful operation + DispatchProgressEvent(successEvent); + DispatchProgressEvent(termEvent); + + return NS_OK; +} + +void +FileReader::Abort(ErrorResult& aRv) +{ + if (mReadyState != LOADING) { + // XXX The spec doesn't say this + aRv.Throw(NS_ERROR_DOM_FILE_ABORT_ERR); + return; + } + + ClearProgressEventTimer(); + + mReadyState = DONE; + + // XXX The spec doesn't say this + mError = new DOMError(GetOwner(), NS_LITERAL_STRING("AbortError")); + + // Revert status and result attributes + SetDOMStringToNull(mResult); + mResultArrayBuffer = nullptr; + + mAsyncStream = nullptr; + mBlob = nullptr; + + //Clean up memory buffer + FreeFileData(); + + // Dispatch the events + DispatchProgressEvent(NS_LITERAL_STRING(ABORT_STR)); + DispatchProgressEvent(NS_LITERAL_STRING(LOADEND_STR)); +} + +} // dom namespace +} // mozilla namespace diff --git a/dom/base/nsDOMFileReader.h b/dom/base/FileReader.h similarity index 57% rename from dom/base/nsDOMFileReader.h rename to dom/base/FileReader.h index 0fa7080a67..418ef5c833 100644 --- a/dom/base/nsDOMFileReader.h +++ b/dom/base/FileReader.h @@ -4,70 +4,55 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef nsDOMFileReader_h__ -#define nsDOMFileReader_h__ +#ifndef mozilla_dom_FileReader_h +#define mozilla_dom_FileReader_h #include "mozilla/Attributes.h" -#include "nsISupportsUtils.h" -#include "nsString.h" -#include "nsWeakReference.h" -#include "nsIStreamListener.h" -#include "nsIInterfaceRequestor.h" -#include "nsJSUtils.h" -#include "nsTArray.h" -#include "prtime.h" -#include "nsITimer.h" -#include "nsIAsyncInputStream.h" +#include "mozilla/DOMEventTargetHelper.h" +#include "mozilla/dom/DOMError.h" -#include "nsIDOMFileReader.h" -#include "nsIDOMFileList.h" #include "nsCOMPtr.h" +#include "nsIAsyncInputStream.h" +#include "nsIStreamListener.h" +#include "nsISupportsUtils.h" +#include "nsIInterfaceRequestor.h" +#include "nsITimer.h" +#include "nsJSUtils.h" +#include "nsString.h" +#include "nsTArray.h" +#include "nsWeakReference.h" +#include "prtime.h" -#include "FileIOObject.h" +#define NS_PROGRESS_EVENT_INTERVAL 50 namespace mozilla { namespace dom { + class Blob; -} // namespace dom -} // namespace mozilla -class nsDOMFileReader final : public mozilla::dom::FileIOObject, - public nsIDOMFileReader, - public nsIInterfaceRequestor, - public nsSupportsWeakReference +extern const uint64_t kUnknownSize; + +class FileReader final : public DOMEventTargetHelper, + public nsIInterfaceRequestor, + public nsSupportsWeakReference, + public nsIInputStreamCallback, + public nsITimerCallback { - typedef mozilla::ErrorResult ErrorResult; - typedef mozilla::dom::GlobalObject GlobalObject; - typedef mozilla::dom::Blob Blob; - public: - nsDOMFileReader(); + explicit FileReader(nsPIDOMWindow* aWindow); NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIDOMFILEREADER - - NS_REALLY_FORWARD_NSIDOMEVENTTARGET(mozilla::DOMEventTargetHelper) - - // nsIInterfaceRequestor + NS_DECL_NSITIMERCALLBACK + NS_DECL_NSIINPUTSTREAMCALLBACK NS_DECL_NSIINTERFACEREQUESTOR - // FileIOObject overrides - virtual void DoAbort(nsAString& aEvent) override; + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(FileReader, DOMEventTargetHelper) - virtual nsresult DoReadData(nsIAsyncInputStream* aStream, uint64_t aCount) override; - - virtual nsresult DoOnLoadEnd(nsresult aStatus, nsAString& aSuccessEvent, - nsAString& aTerminationEvent) override; - - nsPIDOMWindow* GetParentObject() const - { - return GetOwner(); - } virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; // WebIDL - static already_AddRefed + static already_AddRefed Constructor(const GlobalObject& aGlobal, ErrorResult& aRv); void ReadAsArrayBuffer(JSContext* aCx, Blob& aBlob, ErrorResult& aRv) { @@ -84,23 +69,26 @@ public: ReadFileContent(aBlob, EmptyString(), FILE_AS_DATAURL, aRv); } - using FileIOObject::Abort; + void Abort(ErrorResult& aRv); - // Inherited ReadyState(). + uint16_t ReadyState() const + { + return static_cast(mReadyState); + } + + DOMError* GetError() const + { + return mError; + } void GetResult(JSContext* aCx, JS::MutableHandle aResult, ErrorResult& aRv); - using FileIOObject::GetError; - IMPL_EVENT_HANDLER(loadstart) - using FileIOObject::GetOnprogress; - using FileIOObject::SetOnprogress; + IMPL_EVENT_HANDLER(progress) IMPL_EVENT_HANDLER(load) - using FileIOObject::GetOnabort; - using FileIOObject::SetOnabort; - using FileIOObject::GetOnerror; - using FileIOObject::SetOnerror; + IMPL_EVENT_HANDLER(abort) + IMPL_EVENT_HANDLER(error) IMPL_EVENT_HANDLER(loadend) void ReadAsBinaryString(Blob& aBlob, ErrorResult& aRv) @@ -108,15 +96,15 @@ public: ReadFileContent(aBlob, EmptyString(), FILE_AS_BINARY, aRv); } +private: + virtual ~FileReader(); - nsresult Init(); - - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsDOMFileReader, - FileIOObject) - void RootResultArrayBuffer(); - -protected: - virtual ~nsDOMFileReader(); + // This must be in sync with dom/webidl/FileReader.webidl + enum eReadyState { + EMPTY = 0, + LOADING = 1, + DONE = 2 + }; enum eDataFormat { FILE_AS_ARRAYBUFFER, @@ -125,6 +113,8 @@ protected: FILE_AS_DATAURL }; + void RootResultArrayBuffer(); + void ReadFileContent(Blob& aBlob, const nsAString &aCharset, eDataFormat aDataFormat, ErrorResult& aRv); @@ -134,7 +124,20 @@ protected: nsresult GetAsDataURL(Blob *aBlob, const char *aFileData, uint32_t aDataLen, nsAString &aResult); - void FreeFileData() { + nsresult OnLoadEnd(nsresult aStatus); + + void StartProgressEventTimer(); + void ClearProgressEventTimer(); + void DispatchError(nsresult rv, nsAString& finalEvent); + nsresult DispatchProgressEvent(const nsAString& aType); + + nsresult DoReadData(nsIAsyncInputStream* aStream, uint64_t aCount); + + nsresult DoOnLoadEnd(nsresult aStatus, nsAString& aSuccessEvent, + nsAString& aTerminationEvent); + + void FreeFileData() + { moz_free(mFileData); mFileData = nullptr; mDataLen = 0; @@ -150,6 +153,22 @@ protected: nsString mResult; JS::Heap mResultArrayBuffer; + + nsCOMPtr mProgressNotifier; + bool mProgressEventWasDelayed; + bool mTimerIsActive; + + nsCOMPtr mAsyncStream; + + RefPtr mError; + + eReadyState mReadyState; + + uint64_t mTotal; + uint64_t mTransferred; }; -#endif +} // dom namespace +} // mozilla namespace + +#endif // mozilla_dom_FileReader_h diff --git a/dom/base/MultipartBlobImpl.cpp b/dom/base/MultipartBlobImpl.cpp index 4d2c309c2f..98671429ed 100644 --- a/dom/base/MultipartBlobImpl.cpp +++ b/dom/base/MultipartBlobImpl.cpp @@ -25,6 +25,37 @@ using namespace mozilla::dom; NS_IMPL_ISUPPORTS_INHERITED0(MultipartBlobImpl, BlobImpl) +/* static */ already_AddRefed +MultipartBlobImpl::Create(const nsTArray>& aBlobImpls, + const nsAString& aName, + const nsAString& aContentType, + ErrorResult& aRv) +{ + RefPtr blobImpl = + new MultipartBlobImpl(aBlobImpls, aName, aContentType); + blobImpl->SetLengthAndModifiedDate(aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + return blobImpl.forget(); +} + +/* static */ already_AddRefed +MultipartBlobImpl::Create(const nsTArray>& aBlobImpls, + const nsAString& aContentType, + ErrorResult& aRv) +{ + RefPtr blobImpl = + new MultipartBlobImpl(aBlobImpls, aContentType); + blobImpl->SetLengthAndModifiedDate(aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + return blobImpl.forget(); +} + void MultipartBlobImpl::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv) @@ -125,15 +156,19 @@ MultipartBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength, } // we can create our blob now - RefPtr impl = - new MultipartBlobImpl(blobImpls, aContentType); + RefPtr impl = Create(blobImpls, aContentType, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + return impl.forget(); } void -MultipartBlobImpl::InitializeBlob() +MultipartBlobImpl::InitializeBlob(ErrorResult& aRv) { - SetLengthAndModifiedDate(); + SetLengthAndModifiedDate(aRv); + NS_WARN_IF(aRv.Failed()); } void @@ -187,11 +222,12 @@ MultipartBlobImpl::InitializeBlob( mBlobImpls = blobSet.GetBlobImpls(); - SetLengthAndModifiedDate(); + SetLengthAndModifiedDate(aRv); + NS_WARN_IF(aRv.Failed()); } void -MultipartBlobImpl::SetLengthAndModifiedDate() +MultipartBlobImpl::SetLengthAndModifiedDate(ErrorResult& aRv) { MOZ_ASSERT(mLength == UINT64_MAX); MOZ_ASSERT(mLastModificationDate == INT64_MAX); @@ -208,16 +244,19 @@ MultipartBlobImpl::SetLengthAndModifiedDate() MOZ_ASSERT(!blob->IsDateUnknown()); #endif - ErrorResult error; - uint64_t subBlobLength = blob->GetSize(error); - MOZ_ALWAYS_TRUE(!error.Failed()); + uint64_t subBlobLength = blob->GetSize(aRv); + if (NS_WARN_IF(aRv.Failed())) { + return; + } MOZ_ASSERT(UINT64_MAX - subBlobLength >= totalLength); totalLength += subBlobLength; if (blob->IsFile()) { - int64_t partLastModified = blob->GetLastModified(error); - MOZ_ALWAYS_TRUE(!error.Failed()); + int64_t partLastModified = blob->GetLastModified(aRv); + if (NS_WARN_IF(aRv.Failed())) { + return; + } if (lastModified < partLastModified) { lastModified = partLastModified; @@ -314,7 +353,8 @@ MultipartBlobImpl::InitializeChromeFile(Blob& aBlob, blobSet.AppendBlobImpl(aBlob.Impl()); mBlobImpls = blobSet.GetBlobImpls(); - SetLengthAndModifiedDate(); + SetLengthAndModifiedDate(aRv); + NS_WARN_IF(aRv.Failed()); } void @@ -385,7 +425,8 @@ MultipartBlobImpl::InitializeChromeFile(nsPIDOMWindow* aWindow, blobSet.AppendBlobImpl(static_cast(blob.get())->Impl()); mBlobImpls = blobSet.GetBlobImpls(); - SetLengthAndModifiedDate(); + SetLengthAndModifiedDate(aRv); + NS_WARN_IF(aRv.Failed()); } void diff --git a/dom/base/MultipartBlobImpl.h b/dom/base/MultipartBlobImpl.h index 2a0778be28..2239a4936e 100644 --- a/dom/base/MultipartBlobImpl.h +++ b/dom/base/MultipartBlobImpl.h @@ -25,25 +25,17 @@ public: NS_DECL_ISUPPORTS_INHERITED // Create as a file - MultipartBlobImpl(const nsTArray>& aBlobImpls, - const nsAString& aName, - const nsAString& aContentType) - : BlobImplBase(aName, aContentType, UINT64_MAX), - mBlobImpls(aBlobImpls), - mIsFromNsIFile(false) - { - SetLengthAndModifiedDate(); - } + static already_AddRefed + Create(const nsTArray>& aBlobImpls, + const nsAString& aName, + const nsAString& aContentType, + ErrorResult& aRv); // Create as a blob - MultipartBlobImpl(const nsTArray>& aBlobImpls, - const nsAString& aContentType) - : BlobImplBase(aContentType, UINT64_MAX), - mBlobImpls(aBlobImpls), - mIsFromNsIFile(false) - { - SetLengthAndModifiedDate(); - } + static already_AddRefed + Create(const nsTArray>& aBlobImpls, + const nsAString& aContentType, + ErrorResult& aRv); // Create as a file to be later initialized explicit MultipartBlobImpl(const nsAString& aName) @@ -59,7 +51,7 @@ public: { } - void InitializeBlob(); + void InitializeBlob(ErrorResult& aRv); void InitializeBlob( JSContext* aCx, @@ -120,9 +112,26 @@ public: virtual bool MayBeClonedToOtherThreads() const override; protected: + MultipartBlobImpl(const nsTArray>& aBlobImpls, + const nsAString& aName, + const nsAString& aContentType) + : BlobImplBase(aName, aContentType, UINT64_MAX), + mBlobImpls(aBlobImpls), + mIsFromNsIFile(false) + { + } + + MultipartBlobImpl(const nsTArray>& aBlobImpls, + const nsAString& aContentType) + : BlobImplBase(aContentType, UINT64_MAX), + mBlobImpls(aBlobImpls), + mIsFromNsIFile(false) + { + } + virtual ~MultipartBlobImpl() {} - void SetLengthAndModifiedDate(); + void SetLengthAndModifiedDate(ErrorResult& aRv); nsTArray> mBlobImpls; bool mIsFromNsIFile; diff --git a/dom/base/ShadowRoot.cpp b/dom/base/ShadowRoot.cpp index 8c5a78d8cb..968602f6de 100644 --- a/dom/base/ShadowRoot.cpp +++ b/dom/base/ShadowRoot.cpp @@ -316,7 +316,7 @@ ShadowRoot::DistributeSingleNode(nsIContent* aContent) if (!isIndexFound) { // We have still not found an index in the insertion point, // thus it must be at the end. - MOZ_ASSERT(childIterator.Seek(aContent), + MOZ_ASSERT(childIterator.Seek(aContent, nullptr), "Trying to match a node that is not a candidate to be matched"); insertionPoint->AppendMatchedNode(aContent); } diff --git a/dom/base/StructuredCloneHolder.cpp b/dom/base/StructuredCloneHolder.cpp index 1c00f0191e..3b3659500f 100644 --- a/dom/base/StructuredCloneHolder.cpp +++ b/dom/base/StructuredCloneHolder.cpp @@ -556,7 +556,8 @@ namespace { // Recursive! already_AddRefed EnsureBlobForBackgroundManager(BlobImpl* aBlobImpl, - PBackgroundChild* aManager = nullptr) + PBackgroundChild* aManager, + ErrorResult& aRv) { MOZ_ASSERT(aBlobImpl); RefPtr blobImpl = aBlobImpl; @@ -605,7 +606,11 @@ EnsureBlobForBackgroundManager(BlobImpl* aBlobImpl, RefPtr& newSubBlobImpl = newSubBlobImpls[index]; - newSubBlobImpl = EnsureBlobForBackgroundManager(subBlobImpl, aManager); + newSubBlobImpl = EnsureBlobForBackgroundManager(subBlobImpl, aManager, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + MOZ_ASSERT(newSubBlobImpl); if (subBlobImpl != newSubBlobImpl) { @@ -621,9 +626,14 @@ EnsureBlobForBackgroundManager(BlobImpl* aBlobImpl, nsString name; blobImpl->GetName(name); - blobImpl = new MultipartBlobImpl(newSubBlobImpls, name, contentType); + blobImpl = MultipartBlobImpl::Create(newSubBlobImpls, name, + contentType, aRv); } else { - blobImpl = new MultipartBlobImpl(newSubBlobImpls, contentType); + blobImpl = MultipartBlobImpl::Create(newSubBlobImpls, contentType, aRv); + } + + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; } MOZ_ALWAYS_TRUE(NS_SUCCEEDED(blobImpl->SetMutable(false))); @@ -641,7 +651,13 @@ ReadBlob(JSContext* aCx, MOZ_ASSERT(aIndex < aHolder->BlobImpls().Length()); RefPtr blobImpl = aHolder->BlobImpls()[aIndex]; - blobImpl = EnsureBlobForBackgroundManager(blobImpl); + ErrorResult rv; + blobImpl = EnsureBlobForBackgroundManager(blobImpl, nullptr, rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); + return nullptr; + } + MOZ_ASSERT(blobImpl); // RefPtr needs to go out of scope before toObjectOrNull() is @@ -669,7 +685,14 @@ WriteBlob(JSStructuredCloneWriter* aWriter, MOZ_ASSERT(aBlob); MOZ_ASSERT(aHolder); - RefPtr blobImpl = EnsureBlobForBackgroundManager(aBlob->Impl()); + ErrorResult rv; + RefPtr blobImpl = + EnsureBlobForBackgroundManager(aBlob->Impl(), nullptr, rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); + return false; + } + MOZ_ASSERT(blobImpl); MOZ_ALWAYS_TRUE(NS_SUCCEEDED(blobImpl->SetMutable(false))); @@ -715,7 +738,13 @@ ReadFileList(JSContext* aCx, RefPtr blobImpl = aHolder->BlobImpls()[index]; MOZ_ASSERT(blobImpl->IsFile()); - blobImpl = EnsureBlobForBackgroundManager(blobImpl); + ErrorResult rv; + blobImpl = EnsureBlobForBackgroundManager(blobImpl, nullptr, rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); + return nullptr; + } + MOZ_ASSERT(blobImpl); RefPtr file = File::Create(aHolder->ParentDuringRead(), blobImpl); @@ -754,14 +783,22 @@ WriteFileList(JSStructuredCloneWriter* aWriter, return false; } + ErrorResult rv; + nsTArray> blobImpls; + for (uint32_t i = 0; i < aFileList->Length(); ++i) { RefPtr blobImpl = - EnsureBlobForBackgroundManager(aFileList->Item(i)->Impl()); - MOZ_ASSERT(blobImpl); + EnsureBlobForBackgroundManager(aFileList->Item(i)->Impl(), nullptr, rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); + return false; + } - aHolder->BlobImpls().AppendElement(blobImpl); + MOZ_ASSERT(blobImpl); + blobImpls.AppendElement(blobImpl); } + aHolder->BlobImpls().AppendElements(blobImpls); return true; } @@ -805,7 +842,12 @@ ReadFormData(JSContext* aCx, File::Create(aHolder->ParentDuringRead(), blobImpl); MOZ_ASSERT(file); - formData->Append(name, *file, thirdArg); + ErrorResult rv; + formData->Append(name, *file, thirdArg, rv); + if (NS_WARN_IF(rv.Failed())) { + return nullptr; + } + } else { MOZ_ASSERT(tag == 0); @@ -817,7 +859,11 @@ ReadFormData(JSContext* aCx, return nullptr; } - formData->Append(name, value); + ErrorResult rv; + formData->Append(name, value, rv); + if (NS_WARN_IF(rv.Failed())) { + return nullptr; + } } } @@ -866,16 +912,16 @@ WriteFormData(JSStructuredCloneWriter* aWriter, { } static bool - Write(const nsString& aName, bool isFile, const nsString& aValue, - File* aFile, void* aClosure) + Write(const nsString& aName, const OwningFileOrUSVString& aValue, + void* aClosure) { Closure* closure = static_cast(aClosure); if (!WriteString(closure->mWriter, aName)) { return false; } - if (isFile) { - BlobImpl* blobImpl = aFile->Impl(); + if (aValue.IsFile()) { + BlobImpl* blobImpl = aValue.GetAsFile()->Impl(); if (!JS_WriteUint32Pair(closure->mWriter, SCTAG_DOM_BLOB, closure->mHolder->BlobImpls().Length())) { return false; @@ -886,9 +932,10 @@ WriteFormData(JSStructuredCloneWriter* aWriter, } size_t charSize = sizeof(nsString::char_type); - if (!JS_WriteUint32Pair(closure->mWriter, 0, aValue.Length()) || - !JS_WriteBytes(closure->mWriter, aValue.get(), - aValue.Length() * charSize)) { + if (!JS_WriteUint32Pair(closure->mWriter, 0, + aValue.GetAsUSVString().Length()) || + !JS_WriteBytes(closure->mWriter, aValue.GetAsUSVString().get(), + aValue.GetAsUSVString().Length() * charSize)) { return false; } diff --git a/dom/base/WindowOrientationObserver.cpp b/dom/base/WindowOrientationObserver.cpp index d7ce628448..733a961adc 100644 --- a/dom/base/WindowOrientationObserver.cpp +++ b/dom/base/WindowOrientationObserver.cpp @@ -9,6 +9,8 @@ #include "nsGlobalWindow.h" #include "mozilla/Hal.h" +using namespace mozilla::dom; + /** * This class is used by nsGlobalWindow to implement window.orientation * and window.onorientationchange. This class is defined in its own file diff --git a/dom/base/moz.build b/dom/base/moz.build index b4e31153f0..a4b1a5bddc 100644 --- a/dom/base/moz.build +++ b/dom/base/moz.build @@ -16,7 +16,6 @@ XPIDL_SOURCES += [ 'nsIDOMDOMCursor.idl', 'nsIDOMDOMRequest.idl', 'nsIDOMFileList.idl', - 'nsIDOMFileReader.idl', 'nsIDOMFormData.idl', 'nsIDOMParser.idl', 'nsIDOMSerializer.idl', @@ -179,6 +178,7 @@ EXPORTS.mozilla.dom += [ 'EventSource.h', 'File.h', 'FileList.h', + 'FileReader.h', 'FragmentOrElement.h', 'FromParser.h', 'ImageEncoder.h', @@ -243,8 +243,8 @@ UNIFIED_SOURCES += [ 'Element.cpp', 'EventSource.cpp', 'File.cpp', - 'FileIOObject.cpp', 'FileList.cpp', + 'FileReader.cpp', 'FragmentOrElement.cpp', 'ImageEncoder.cpp', 'ImportManager.cpp', @@ -271,7 +271,6 @@ UNIFIED_SOURCES += [ 'nsDOMAttributeMap.cpp', 'nsDOMCaretPosition.cpp', 'nsDOMClassInfo.cpp', - 'nsDOMFileReader.cpp', 'nsDOMMutationObserver.cpp', 'nsDOMNavigationTiming.cpp', 'nsDOMScriptObjectFactory.cpp', diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index e2276ef643..3e608fd0ae 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -6616,22 +6616,6 @@ nsContentUtils::FindInternalContentViewer(const nsACString& aType, return nullptr; } -bool -nsContentUtils::GetContentSecurityPolicy(nsIContentSecurityPolicy** aCSP) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - nsCOMPtr csp; - nsresult rv = SubjectPrincipal()->GetCsp(getter_AddRefs(csp)); - if (NS_FAILED(rv)) { - NS_ERROR("CSP: Failed to get CSP from principal."); - return false; - } - - csp.forget(aCSP); - return true; -} - // static bool nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern, diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index 0ce82d255c..70ea5510c0 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -505,11 +505,6 @@ public: return sSecurityManager; } - /** - * Get the ContentSecurityPolicy for a JS context. - **/ - static bool GetContentSecurityPolicy(nsIContentSecurityPolicy** aCSP); - // Returns the subject principal. Guaranteed to return non-null. May only // be called when nsContentUtils is initialized. static nsIPrincipal* SubjectPrincipal(); diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 46191a06e8..f38329bb82 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -2282,8 +2282,7 @@ struct InterfaceShimEntry { // interface that has interface constants that sites might be getting off // of Ci. const InterfaceShimEntry kInterfaceShimMap[] = -{ { "nsIDOMFileReader", "FileReader" }, - { "nsIXMLHttpRequest", "XMLHttpRequest" }, +{ { "nsIXMLHttpRequest", "XMLHttpRequest" }, { "nsIDOMDOMException", "DOMException" }, { "nsIDOMNode", "Node" }, { "nsIDOMCSSPrimitiveValue", "CSSPrimitiveValue" }, diff --git a/dom/base/nsDOMMutationObserver.cpp b/dom/base/nsDOMMutationObserver.cpp index 27a8c04259..19f2125998 100644 --- a/dom/base/nsDOMMutationObserver.cpp +++ b/dom/base/nsDOMMutationObserver.cpp @@ -846,8 +846,7 @@ nsDOMMutationObserver::HandleMutation() } ClearPendingRecords(); - mozilla::ErrorResult rv; - mCallback->Call(this, mutations, *this, rv); + mCallback->Call(this, mutations, *this); } class AsyncMutationHandler : public nsRunnable diff --git a/dom/base/nsFormData.cpp b/dom/base/nsFormData.cpp index 6b16217b9e..ef93974699 100644 --- a/dom/base/nsFormData.cpp +++ b/dom/base/nsFormData.cpp @@ -25,7 +25,8 @@ namespace { // Implements steps 3 and 4 of the "create an entry" algorithm of FormData. already_AddRefed -CreateNewFileInstance(Blob& aBlob, const Optional& aFilename) +CreateNewFileInstance(Blob& aBlob, const Optional& aFilename, + ErrorResult& aRv) { // Step 3 "If value is a Blob object and not a File object, set value to // a new File object, representing the same bytes, whose name attribute value @@ -47,10 +48,15 @@ CreateNewFileInstance(Blob& aBlob, const Optional& aFilename) filename = NS_LITERAL_STRING("blob"); } - return aBlob.ToFile(filename); + RefPtr file = aBlob.ToFile(filename, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + return file.forget(); } -} // anonymous namespace +} // namespace // ------------------------------------------------------------------------- // nsISupports @@ -61,7 +67,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFormData) NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner) for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) { - ImplCycleCollectionUnlink(tmp->mFormData[i].fileValue); + ImplCycleCollectionUnlink(tmp->mFormData[i].value); } NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER @@ -71,8 +77,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFormData) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner) for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) { - ImplCycleCollectionTraverse(cb,tmp->mFormData[i].fileValue, - "mFormData[i].fileValue", 0); + ImplCycleCollectionTraverse(cb, tmp->mFormData[i].value, + "mFormData[i].GetAsFile()", 0); } NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS @@ -101,16 +107,22 @@ nsFormData::GetEncodedSubmission(nsIURI* aURI, } void -nsFormData::Append(const nsAString& aName, const nsAString& aValue) +nsFormData::Append(const nsAString& aName, const nsAString& aValue, + ErrorResult& aRv) { AddNameValuePair(aName, aValue); } void nsFormData::Append(const nsAString& aName, Blob& aBlob, - const Optional& aFilename) + const Optional& aFilename, + ErrorResult& aRv) { - RefPtr file = CreateNewFileInstance(aBlob, aFilename); + RefPtr file = CreateNewFileInstance(aBlob, aFilename, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return; + } + AddNameFilePair(aName, file); } @@ -126,24 +138,13 @@ nsFormData::Delete(const nsAString& aName) } } -void -nsFormData::ExtractValue(const FormDataTuple& aTuple, - OwningFileOrUSVString* aOutValue) -{ - if (aTuple.valueIsFile) { - aOutValue->SetAsFile() = aTuple.fileValue; - } else { - aOutValue->SetAsUSVString() = aTuple.stringValue; - } -} - void nsFormData::Get(const nsAString& aName, Nullable& aOutValue) { for (uint32_t i = 0; i < mFormData.Length(); ++i) { if (aName.Equals(mFormData[i].name)) { - ExtractValue(mFormData[i], &aOutValue.SetValue()); + aOutValue.SetValue() = mFormData[i].value; return; } } @@ -158,7 +159,7 @@ nsFormData::GetAll(const nsAString& aName, for (uint32_t i = 0; i < mFormData.Length(); ++i) { if (aName.Equals(mFormData[i].name)) { OwningFileOrUSVString* element = aValues.AppendElement(); - ExtractValue(mFormData[i], element); + *element = mFormData[i].value; } } } @@ -207,28 +208,54 @@ nsFormData::RemoveAllOthersAndGetFirstFormDataTuple(const nsAString& aName) void nsFormData::Set(const nsAString& aName, Blob& aBlob, - const Optional& aFilename) + const Optional& aFilename, + ErrorResult& aRv) { FormDataTuple* tuple = RemoveAllOthersAndGetFirstFormDataTuple(aName); if (tuple) { - RefPtr file = CreateNewFileInstance(aBlob, aFilename); + RefPtr file = CreateNewFileInstance(aBlob, aFilename, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return; + } + SetNameFilePair(tuple, aName, file); } else { - Append(aName, aBlob, aFilename); + Append(aName, aBlob, aFilename, aRv); } } void -nsFormData::Set(const nsAString& aName, const nsAString& aValue) +nsFormData::Set(const nsAString& aName, const nsAString& aValue, + ErrorResult& aRv) { FormDataTuple* tuple = RemoveAllOthersAndGetFirstFormDataTuple(aName); if (tuple) { SetNameValuePair(tuple, aName, aValue); } else { - Append(aName, aValue); + Append(aName, aValue, aRv); } } +uint32_t +nsFormData::GetIterableLength() const +{ + return mFormData.Length(); +} + +const nsAString& +nsFormData::GetKeyAtIndex(uint32_t aIndex) const +{ + MOZ_ASSERT(aIndex < mFormData.Length()); + return mFormData[aIndex].name; +} + +const OwningFileOrUSVString& +nsFormData::GetValueAtIndex(uint32_t aIndex) const +{ + MOZ_ASSERT(aIndex < mFormData.Length()); + return mFormData[aIndex].value; +} + // ------------------------------------------------------------------------- // nsIDOMFormData @@ -252,7 +279,12 @@ nsFormData::Append(const nsAString& aName, nsIVariant* aValue) RefPtr blob = static_cast(domBlob.get()); if (domBlob) { Optional temp; - Append(aName, *blob, temp); + ErrorResult rv; + Append(aName, *blob, temp, rv); + if (NS_WARN_IF(rv.Failed())) { + return rv.StealNSResult(); + } + return NS_OK; } } @@ -265,7 +297,12 @@ nsFormData::Append(const nsAString& aName, nsIVariant* aValue) nsString valAsString; valAsString.Adopt(stringData, stringLen); - Append(aName, valAsString); + ErrorResult error; + Append(aName, valAsString, error); + if (NS_WARN_IF(error.Failed())) { + return error.StealNSResult(); + } + return NS_OK; } @@ -297,11 +334,13 @@ nsFormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength, nsFSMultipartFormData fs(NS_LITERAL_CSTRING("UTF-8"), nullptr); for (uint32_t i = 0; i < mFormData.Length(); ++i) { - if (mFormData[i].valueIsFile) { - fs.AddNameFilePair(mFormData[i].name, mFormData[i].fileValue); - } - else { - fs.AddNameValuePair(mFormData[i].name, mFormData[i].stringValue); + if (mFormData[i].value.IsFile()) { + fs.AddNameFilePair(mFormData[i].name, mFormData[i].value.GetAsFile()); + } else if (mFormData[i].value.IsUSVString()) { + fs.AddNameValuePair(mFormData[i].name, + mFormData[i].value.GetAsUSVString()); + } else { + fs.AddNameFilePair(mFormData[i].name, nullptr); } } diff --git a/dom/base/nsFormData.h b/dom/base/nsFormData.h index 0ec96f5945..d6e06b05e5 100644 --- a/dom/base/nsFormData.h +++ b/dom/base/nsFormData.h @@ -37,13 +37,12 @@ private: typedef mozilla::dom::Blob Blob; typedef mozilla::dom::File File; + typedef mozilla::dom::OwningFileOrUSVString OwningFileOrUSVString; struct FormDataTuple { nsString name; - nsString stringValue; - RefPtr fileValue; - bool valueIsFile; + OwningFileOrUSVString value; }; // Returns the FormDataTuple to modify. This may be null, in which case @@ -57,8 +56,7 @@ private: { MOZ_ASSERT(aData); aData->name = aName; - aData->stringValue = aValue; - aData->valueIsFile = false; + aData->value.SetAsUSVString() = aValue; } void SetNameFilePair(FormDataTuple* aData, @@ -67,12 +65,11 @@ private: { MOZ_ASSERT(aData); aData->name = aName; - aData->fileValue = aFile; - aData->valueIsFile = true; + if (aFile) { + aData->value.SetAsFile() = aFile; + } } - void ExtractValue(const FormDataTuple& aTuple, - mozilla::dom::OwningFileOrUSVString* aOutValue); public: explicit nsFormData(nsISupports* aOwner = nullptr); @@ -96,16 +93,24 @@ public: Constructor(const mozilla::dom::GlobalObject& aGlobal, const mozilla::dom::Optional >& aFormElement, mozilla::ErrorResult& aRv); - void Append(const nsAString& aName, const nsAString& aValue); + void Append(const nsAString& aName, const nsAString& aValue, + mozilla::ErrorResult& aRv); void Append(const nsAString& aName, Blob& aBlob, - const mozilla::dom::Optional& aFilename); + const mozilla::dom::Optional& aFilename, + mozilla::ErrorResult& aRv); void Delete(const nsAString& aName); - void Get(const nsAString& aName, mozilla::dom::Nullable& aOutValue); - void GetAll(const nsAString& aName, nsTArray& aValues); + void Get(const nsAString& aName, mozilla::dom::Nullable& aOutValue); + void GetAll(const nsAString& aName, nsTArray& aValues); bool Has(const nsAString& aName); void Set(const nsAString& aName, Blob& aBlob, - const mozilla::dom::Optional& aFilename); - void Set(const nsAString& aName, const nsAString& aValue); + const mozilla::dom::Optional& aFilename, + mozilla::ErrorResult& aRv); + void Set(const nsAString& aName, const nsAString& aValue, + mozilla::ErrorResult& aRv); + + uint32_t GetIterableLength() const; + const nsAString& GetKeyAtIndex(uint32_t aIndex) const; + const OwningFileOrUSVString& GetValueAtIndex(uint32_t aIndex) const; // nsFormSubmission virtual nsresult GetEncodedSubmission(nsIURI* aURI, @@ -120,9 +125,9 @@ public: virtual nsresult AddNameFilePair(const nsAString& aName, File* aFile) override; - typedef bool (*FormDataEntryCallback)(const nsString& aName, bool aIsFile, - const nsString& aValue, - File* aFile, void* aClosure); + typedef bool (*FormDataEntryCallback)(const nsString& aName, + const OwningFileOrUSVString& aValue, + void* aClosure); uint32_t Length() const @@ -137,8 +142,7 @@ public: { for (uint32_t i = 0; i < mFormData.Length(); ++i) { FormDataTuple& tuple = mFormData[i]; - if (!aFunc(tuple.name, tuple.valueIsFile, tuple.stringValue, - tuple.fileValue, aClosure)) { + if (!aFunc(tuple.name, tuple.value, aClosure)) { return false; } } diff --git a/dom/base/nsIDOMFileReader.idl b/dom/base/nsIDOMFileReader.idl deleted file mode 100644 index 98b8559f87..0000000000 --- a/dom/base/nsIDOMFileReader.idl +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsIDOMEventTarget.idl" - -interface nsIDOMEventListener; -interface nsIDOMBlob; - -[builtinclass, uuid(2f34c719-bc14-4546-9fb9-2bab75e56e45)] -interface nsIDOMFileReader : nsIDOMEventTarget -{ - [implicit_jscontext] - void readAsArrayBuffer(in nsIDOMBlob filedata); - void readAsBinaryString(in nsIDOMBlob filedata); - void readAsText(in nsIDOMBlob filedata, [optional] in DOMString encoding); - void readAsDataURL(in nsIDOMBlob file); - - void abort(); - - const unsigned short EMPTY = 0; - const unsigned short LOADING = 1; - const unsigned short DONE = 2; - readonly attribute unsigned short readyState; - - [implicit_jscontext] - readonly attribute jsval result; - - // This is a DOMError - readonly attribute nsISupports error; - - [implicit_jscontext] attribute jsval onloadstart; - [implicit_jscontext] attribute jsval onprogress; - [implicit_jscontext] attribute jsval onload; - [implicit_jscontext] attribute jsval onabort; - [implicit_jscontext] attribute jsval onerror; - [implicit_jscontext] attribute jsval onloadend; -}; - -%{ C++ -#define NS_FILEREADER_CID \ -{0x06aa7c21, 0xfe05, 0x4cf2, \ -{0xb1, 0xc4, 0x0c, 0x71, 0x26, 0xa4, 0xf7, 0x13}} -#define NS_FILEREADER_CONTRACTID \ -"@mozilla.org/files/filereader;1" -%} diff --git a/dom/base/nsXMLHttpRequest.cpp b/dom/base/nsXMLHttpRequest.cpp index f96364a921..d18d161fe1 100644 --- a/dom/base/nsXMLHttpRequest.cpp +++ b/dom/base/nsXMLHttpRequest.cpp @@ -795,7 +795,7 @@ nsXMLHttpRequest::CreateResponseParsedJSON(JSContext* aCx) } void -nsXMLHttpRequest::CreatePartialBlob() +nsXMLHttpRequest::CreatePartialBlob(ErrorResult& aRv) { if (mDOMBlob) { // Use progress info to determine whether load is complete, but use @@ -804,9 +804,8 @@ nsXMLHttpRequest::CreatePartialBlob() if (mLoadTotal == mLoadTransferred) { mResponseBlob = mDOMBlob; } else { - ErrorResult rv; mResponseBlob = mDOMBlob->CreateSlice(0, mDataAvailable, - EmptyString(), rv); + EmptyString(), aRv); } return; } @@ -821,7 +820,7 @@ nsXMLHttpRequest::CreatePartialBlob() mChannel->GetContentType(contentType); } - mResponseBlob = mBlobSet->GetBlobInternal(GetOwner(), contentType); + mResponseBlob = mBlobSet->GetBlobInternal(GetOwner(), contentType, aRv); } NS_IMETHODIMP nsXMLHttpRequest::GetResponseType(nsAString& aResponseType) @@ -1015,7 +1014,7 @@ nsXMLHttpRequest::GetResponse(JSContext* aCx, } if (!mResponseBlob) { - CreatePartialBlob(); + CreatePartialBlob(aRv); } } @@ -1687,8 +1686,10 @@ nsXMLHttpRequest::Open(const nsACString& inMethod, const nsACString& url, nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL; } - // If we have the document, use it - if (doc) { + // If we have the document, use it. Unfortunately, for dedicated workers + // 'doc' ends up being the parent document, which is not the document + // that we want to use. So make sure to avoid using 'doc' in that situation. + if (doc && doc->NodePrincipal() == mPrincipal) { rv = NS_NewChannel(getter_AddRefs(mChannel), uri, doc, @@ -2221,8 +2222,14 @@ nsXMLHttpRequest::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult // Also, no-store response cannot be written in persistent cache. nsAutoCString contentType; mChannel->GetContentType(contentType); - mResponseBlob = mBlobSet->GetBlobInternal(GetOwner(), contentType); + + ErrorResult rv; + mResponseBlob = mBlobSet->GetBlobInternal(GetOwner(), contentType, rv); mBlobSet = nullptr; + + if (NS_WARN_IF(rv.Failed())) { + return rv.StealNSResult(); + } } NS_ASSERTION(mResponseBody.IsEmpty(), "mResponseBody should be empty"); NS_ASSERTION(mResponseText.IsEmpty(), "mResponseText should be empty"); diff --git a/dom/base/nsXMLHttpRequest.h b/dom/base/nsXMLHttpRequest.h index 6f6a8179d8..373ba15ac0 100644 --- a/dom/base/nsXMLHttpRequest.h +++ b/dom/base/nsXMLHttpRequest.h @@ -605,7 +605,7 @@ protected: uint32_t count, uint32_t *writeCount); nsresult CreateResponseParsedJSON(JSContext* aCx); - void CreatePartialBlob(); + void CreatePartialBlob(ErrorResult& aRv); bool CreateDOMBlob(nsIRequest *request); // Change the state of the object with this. The broadcast argument // determines if the onreadystatechange listener should be called. diff --git a/dom/base/test/file_bug1198095.js b/dom/base/test/file_bug1198095.js new file mode 100644 index 0000000000..d85e474019 --- /dev/null +++ b/dom/base/test/file_bug1198095.js @@ -0,0 +1,26 @@ +var { classes: Cc, interfaces: Ci, utils: Cu } = Components; +Cu.importGlobalProperties(["File"]); + +function createFileWithData(message) { + var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); + var testFile = dirSvc.get("ProfD", Ci.nsIFile); + testFile.append("fileAPItestfileBug1198095"); + + var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream); + outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate + 0666, 0); + + outStream.write(message, message.length); + outStream.close(); + + var domFile = new File(testFile); + return domFile; +} + +addMessageListener("file.open", function (message) { + sendAsyncMessage("file.opened", createFileWithData(message)); +}); + +addMessageListener("file.modify", function (message) { + sendAsyncMessage("file.modified", createFileWithData(message)); +}); diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini index 7c294409e8..4b0b245cd8 100644 --- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -257,6 +257,7 @@ support-files = referrer_change_server.sjs file_change_policy_redirect.html empty_worker.js + file_bug1198095.js [test_anonymousContent_api.html] [test_anonymousContent_append_after_reflow.html] @@ -846,3 +847,4 @@ skip-if = e10s || os != 'linux' || buildapp != 'browser' skip-if = buildapp == 'b2g' #no ssl support [test_document.all_iteration.html] [test_performance_translate.html] +[test_bug1198095.html] diff --git a/dom/base/test/test_bug1198095.html b/dom/base/test/test_bug1198095.html new file mode 100644 index 0000000000..dfdfa017f1 --- /dev/null +++ b/dom/base/test/test_bug1198095.html @@ -0,0 +1,77 @@ + + + + + Test for Bug 1198095 + + + + + +Mozilla Bug 1198095 + +
+
+
+ diff --git a/dom/base/test/test_ipc_messagemanager_blob.html b/dom/base/test/test_ipc_messagemanager_blob.html index c8872c93ee..fa8967888e 100644 --- a/dom/base/test/test_ipc_messagemanager_blob.html +++ b/dom/base/test/test_ipc_messagemanager_blob.html @@ -26,9 +26,7 @@ return; } - let reader = - Components.classes["@mozilla.org/files/filereader;1"] - .createInstance(Components.interfaces.nsIDOMFileReader); + let reader = new FileReader(); reader.addEventListener("load", function() { let response = reader.result == "this is a great success!" ? message.json : diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 28ef7d1fd8..7c3a862f7b 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -513,7 +513,6 @@ DOMInterfaces = { }, 'FileReader': { - 'nativeType': 'nsDOMFileReader', 'implicitJSContext': [ 'readAsArrayBuffer' ], }, diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index ccf7ecf3ea..edd45d9326 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -14542,16 +14542,33 @@ class CGCallback(CGClass): assert args[0].name == "cx" and args[0].argType == "JSContext*" assert args[1].name == "aThisVal" and args[1].argType == "JS::Handle" args = args[2:] + + # Now remember which index the ErrorResult argument is at; + # we'll need this below. + assert args[-1].name == "aRv" and args[-1].argType == "ErrorResult&" + rvIndex = len(args) - 1 + assert rvIndex >= 0 + # Record the names of all the arguments, so we can use them when we call # the private method. argnames = [arg.name for arg in args] argnamesWithThis = ["s.GetContext()", "thisValJS"] + argnames argnamesWithoutThis = ["s.GetContext()", "JS::UndefinedHandleValue"] + argnames # Now that we've recorded the argnames for our call to our private - # method, insert our optional arguments for the execution reason and for - # deciding whether the CallSetup should re-throw exceptions on aRv. + # method, insert our optional argument for the execution reason. args.append(Argument("const char*", "aExecutionReason", "nullptr")) + + # Make copies of the arg list for the two "without rv" overloads. Note + # that those don't need aExceptionHandling or aCompartment arguments + # because those would make not sense anyway: the only sane thing to do + # with exceptions in the "without rv" cases is to report them. + argsWithoutRv = list(args) + argsWithoutRv.pop(rvIndex) + argsWithoutThisAndRv = list(argsWithoutRv) + + # Add the potional argument for deciding whether the CallSetup should + # re-throw exceptions on aRv. args.append(Argument("ExceptionHandling", "aExceptionHandling", "eReportExceptions")) # And the argument for communicating when exceptions should really be @@ -14563,6 +14580,22 @@ class CGCallback(CGClass): # And now insert our template argument. argsWithoutThis = list(args) args.insert(0, Argument("const T&", "thisVal")) + argsWithoutRv.insert(0, Argument("const T&", "thisVal")) + + argnamesWithoutThisAndRv = [arg.name for arg in argsWithoutThisAndRv] + argnamesWithoutThisAndRv.insert(rvIndex, "rv"); + # If we just leave things like that, and have no actual arguments in the + # IDL, we will end up trying to call the templated "without rv" overload + # with "rv" as the thisVal. That's no good. So explicitly append the + # aExceptionHandling and aCompartment values we need to end up matching + # the signature of our non-templated "with rv" overload. + argnamesWithoutThisAndRv.extend(["eReportExceptions", "nullptr"]) + + argnamesWithoutRv = [arg.name for arg in argsWithoutRv] + # Note that we need to insert at rvIndex + 1, since we inserted a + # thisVal arg at the start. + argnamesWithoutRv.insert(rvIndex + 1, "rv") + errorReturn = method.getDefaultRetval() setupCall = fill( @@ -14602,6 +14635,20 @@ class CGCallback(CGClass): errorReturn=errorReturn, methodName=method.name, callArgs=", ".join(argnamesWithoutThis)) + bodyWithThisWithoutRv = fill( + """ + IgnoredErrorResult rv; + return ${methodName}(${callArgs}); + """, + methodName=method.name, + callArgs=", ".join(argnamesWithoutRv)) + bodyWithoutThisAndRv = fill( + """ + IgnoredErrorResult rv; + return ${methodName}(${callArgs}); + """, + methodName=method.name, + callArgs=", ".join(argnamesWithoutThisAndRv)) return [ClassMethod(method.name, method.returnType, args, bodyInHeader=True, @@ -14610,6 +14657,13 @@ class CGCallback(CGClass): ClassMethod(method.name, method.returnType, argsWithoutThis, bodyInHeader=True, body=bodyWithoutThis), + ClassMethod(method.name, method.returnType, argsWithoutRv, + bodyInHeader=True, + templateArgs=["typename T"], + body=bodyWithThisWithoutRv), + ClassMethod(method.name, method.returnType, argsWithoutThisAndRv, + bodyInHeader=True, + body=bodyWithoutThisAndRv), method] def deps(self): diff --git a/dom/bindings/ErrorResult.h b/dom/bindings/ErrorResult.h index 6e24b93298..2eba6d4875 100644 --- a/dom/bindings/ErrorResult.h +++ b/dom/bindings/ErrorResult.h @@ -398,6 +398,16 @@ private: void operator=(const ErrorResult&) = delete; }; +// A class for use when an ErrorResult should just automatically be ignored. +class IgnoredErrorResult : public ErrorResult +{ +public: + ~IgnoredErrorResult() + { + SuppressException(); + } +}; + /****************************************************************************** ** Macros for checking results ******************************************************************************/ diff --git a/dom/fetch/FetchUtil.cpp b/dom/fetch/FetchUtil.cpp index 94f4dd99c5..943e63707b 100644 --- a/dom/fetch/FetchUtil.cpp +++ b/dom/fetch/FetchUtil.cpp @@ -203,7 +203,9 @@ public: bool URLParamsIterator(const nsString& aName, const nsString& aValue) override { - mFormData->Append(aName, aValue); + ErrorResult rv; + mFormData->Append(aName, aValue, rv); + MOZ_ASSERT(!rv.Failed()); return true; } @@ -392,7 +394,9 @@ private: NS_ConvertUTF8toUTF16 name(mName); if (mFilename.IsVoid()) { - mFormData->Append(name, NS_ConvertUTF8toUTF16(body)); + ErrorResult rv; + mFormData->Append(name, NS_ConvertUTF8toUTF16(body), rv); + MOZ_ASSERT(!rv.Failed()); } else { // Unfortunately we've to copy the data first since all our strings are // going to free it. We also need fallible alloc, so we can't just use @@ -417,7 +421,11 @@ private: NS_ConvertUTF8toUTF16(mFilename), NS_ConvertUTF8toUTF16(mContentType), /* aLastModifiedDate */ 0); Optional dummy; - mFormData->Append(name, *file, dummy); + ErrorResult rv; + mFormData->Append(name, *file, dummy, rv); + if (NS_WARN_IF(rv.Failed())) { + return false; + } } return true; diff --git a/dom/geolocation/nsGeolocation.cpp b/dom/geolocation/nsGeolocation.cpp index 60c6c1e28c..781c2f9c10 100644 --- a/dom/geolocation/nsGeolocation.cpp +++ b/dom/geolocation/nsGeolocation.cpp @@ -330,8 +330,7 @@ PositionError::NotifyCallback(const GeoPositionErrorCallback& aCallback) PositionErrorCallback* callback = aCallback.GetWebIDLCallback(); if (callback) { - ErrorResult err; - callback->Call(*this, err); + callback->Call(*this); } } else { nsIDOMGeoPositionErrorCallback* callback = aCallback.GetXPCOMCallback(); @@ -654,11 +653,10 @@ nsGeolocationRequest::SendLocation(nsIDOMGeoPosition* aPosition) nsAutoMicroTask mt; if (mCallback.HasWebIDLCallback()) { - ErrorResult err; PositionCallback* callback = mCallback.GetWebIDLCallback(); MOZ_ASSERT(callback); - callback->Call(*wrapped, err); + callback->Call(*wrapped); } else { nsIDOMGeoPositionCallback* callback = mCallback.GetXPCOMCallback(); diff --git a/dom/html/test/file_iframe_sandbox_g_if1.html b/dom/html/test/file_iframe_sandbox_g_if1.html index 90ca6074ac..9a985faf97 100644 --- a/dom/html/test/file_iframe_sandbox_g_if1.html +++ b/dom/html/test/file_iframe_sandbox_g_if1.html @@ -42,14 +42,9 @@ // test loading with relative url - this should fail since we are // sandboxed and have a null principal - try { - var worker_js = new Worker('file_iframe_sandbox_worker.js'); - } catch (e) { - ok(e.name === "SecurityError", "a worker in a sandboxed document should throw when loading from a relative URI"); - } - + var worker_js = new Worker('file_iframe_sandbox_worker.js'); worker_js.onerror = function(error) { - ok(false, "a worker in a sandboxed document should not tell the load error via error event"); + ok(true, "a worker in a sandboxed document should tell the load error via error event"); } worker_js.addEventListener('message', function(event) { diff --git a/dom/html/test/formData_test.js b/dom/html/test/formData_test.js index 613dc98238..4194f12332 100644 --- a/dom/html/test/formData_test.js +++ b/dom/html/test/formData_test.js @@ -105,6 +105,56 @@ function testFilename() { is(f.get("file3").name, "", "File's filename is returned even if empty."); } +function testIterable() { + var fd = new FormData(); + fd.set('1','2'); + fd.set('2','4'); + fd.set('3','6'); + fd.set('4','8'); + fd.set('5','10'); + + var key_iter = fd.keys(); + var value_iter = fd.values(); + var entries_iter = fd.entries(); + for (var i = 0; i < 5; ++i) { + var v = i + 1; + var key = key_iter.next(); + var value = value_iter.next(); + var entry = entries_iter.next(); + is(key.value, v.toString(), "Correct Key iterator: " + v.toString()); + ok(!key.done, "key.done is false"); + is(value.value, (v * 2).toString(), "Correct Value iterator: " + (v * 2).toString()); + ok(!value.done, "value.done is false"); + is(entry.value[0], v.toString(), "Correct Entry 0 iterator: " + v.toString()); + is(entry.value[1], (v * 2).toString(), "Correct Entry 1 iterator: " + (v * 2).toString()); + ok(!entry.done, "entry.done is false"); + } + + var last = key_iter.next(); + ok(last.done, "Nothing more to read."); + is(last.value, undefined, "Undefined is the last key"); + + last = value_iter.next(); + ok(last.done, "Nothing more to read."); + is(last.value, undefined, "Undefined is the last value"); + + last = entries_iter.next(); + ok(last.done, "Nothing more to read."); + + key_iter = fd.keys(); + key_iter.next(); + key_iter.next(); + fd.delete('1'); + fd.delete('2'); + fd.delete('3'); + fd.delete('4'); + fd.delete('5'); + + last = key_iter.next(); + ok(last.done, "Nothing more to read."); + is(last.value, undefined, "Undefined is the last key"); +} + function testSend(doneCb) { var xhr = new XMLHttpRequest(); xhr.open("POST", "form_submit_server.sjs"); @@ -161,6 +211,7 @@ function runTest(doneCb) { testSet(); testIterate(); testFilename(); + testIterable(); // Finally, send an XHR and verify the response matches. testSend(doneCb); } diff --git a/dom/indexedDB/test/test_message_manager_ipc.html b/dom/indexedDB/test/test_message_manager_ipc.html index 5a45b90a00..7fae1402ea 100644 --- a/dom/indexedDB/test/test_message_manager_ipc.html +++ b/dom/indexedDB/test/test_message_manager_ipc.html @@ -50,11 +50,6 @@ function childFrameScript() { sendAsyncMessage(mmName, { op: "done", result: result }); } - function createFileReader() { - return Cc["@mozilla.org/files/filereader;1"] - .createInstance(Ci.nsIDOMFileReader); - } - function grabAndContinue(arg) { testGenerator.send(arg); } @@ -78,7 +73,7 @@ function childFrameScript() { info("Reading blob"); - let reader = createFileReader(); + let reader = new FileReader(); reader.addEventListener("load", grabAndContinue); reader.readAsText(blob); @@ -94,7 +89,7 @@ function childFrameScript() { info("Reading slice"); - reader = createFileReader(); + reader = new FileReader(); reader.addEventListener("load", grabAndContinue); reader.readAsText(slice); @@ -155,7 +150,7 @@ function childFrameScript() { info("Reading blob"); - reader = createFileReader(); + reader = new FileReader(); reader.addEventListener("load", grabAndContinue); reader.readAsText(blob); @@ -190,7 +185,7 @@ function childFrameScript() { info("Reading Slice"); - reader = createFileReader(); + reader = new FileReader(); reader.addEventListener("load", grabAndContinue); reader.readAsText(slice); diff --git a/dom/indexedDB/test/unit/test_blob_file_backed.js b/dom/indexedDB/test/unit/test_blob_file_backed.js index 48857cecd1..40f49eeb13 100644 --- a/dom/indexedDB/test/unit/test_blob_file_backed.js +++ b/dom/indexedDB/test/unit/test_blob_file_backed.js @@ -3,14 +3,9 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -let disableWorkerTest = "This test uses SpecialPowers"; +var disableWorkerTest = "This test uses SpecialPowers"; -let testGenerator = testSteps(); - -function createFileReader() { - return SpecialPowers.Cc["@mozilla.org/files/filereader;1"] - .createInstance(SpecialPowers.Ci.nsIDOMFileReader); -} +var testGenerator = testSteps(); function testSteps() { @@ -48,7 +43,7 @@ function testSteps() is(file.size, fileData.length, "Correct size"); is(file.type, fileType, "Correct type"); - let fileReader = createFileReader(); + let fileReader = new FileReader(); fileReader.onload = grabEventAndContinueHandler; fileReader.readAsText(file); @@ -85,7 +80,7 @@ function testSteps() is(file.size, fileData.length, "Correct size"); is(file.type, fileType, "Correct type"); - fileReader = createFileReader(); + fileReader = new FileReader(); fileReader.onload = grabEventAndContinueHandler; fileReader.readAsText(file); diff --git a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js index bd1c0b0f7a..0a72f8511d 100644 --- a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js +++ b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js @@ -52,7 +52,7 @@ if (!this.runTest) { enableExperimental(); } - Cu.importGlobalProperties(["indexedDB", "Blob", "File"]); + Cu.importGlobalProperties(["indexedDB", "Blob", "File", "FileReader"]); do_test_pending(); testGenerator.next(); @@ -342,12 +342,6 @@ function getFile(name, type, str) return new File([str], name, {type: type}); } -function getFileReader() -{ - return SpecialPowers.Cc["@mozilla.org/files/filereader;1"] - .createInstance(SpecialPowers.Ci.nsIDOMFileReader); -} - function compareBuffers(buffer1, buffer2) { if (buffer1.byteLength != buffer2.byteLength) { @@ -391,7 +385,7 @@ function verifyBlob(blob1, blob2) } if (!buffer2) { - let reader = getFileReader(); + let reader = new FileReader(); reader.readAsArrayBuffer(blob2); reader.onload = function(event) { buffer2 = event.target.result; @@ -403,7 +397,7 @@ function verifyBlob(blob1, blob2) } } - let reader = getFileReader(); + let reader = new FileReader(); reader.readAsArrayBuffer(blob1); reader.onload = function(event) { buffer1 = event.target.result; diff --git a/dom/ipc/Blob.cpp b/dom/ipc/Blob.cpp index 8c5c89bd56..e2ae557277 100644 --- a/dom/ipc/Blob.cpp +++ b/dom/ipc/Blob.cpp @@ -904,13 +904,17 @@ CreateBlobImpl(const nsTArray& aBlobDatas, MOZ_ASSERT(!isMutable); } + ErrorResult rv; RefPtr blobImpl; if (!hasRecursed && aMetadata.IsFile()) { - blobImpl = - new MultipartBlobImpl(blobImpls, aMetadata.mName, aMetadata.mContentType); + blobImpl = MultipartBlobImpl::Create(blobImpls, aMetadata.mName, + aMetadata.mContentType, rv); } else { - blobImpl = - new MultipartBlobImpl(blobImpls, aMetadata.mContentType); + blobImpl = MultipartBlobImpl::Create(blobImpls, aMetadata.mContentType, rv); + } + + if (NS_WARN_IF(rv.Failed())) { + return nullptr; } MOZ_ALWAYS_TRUE(NS_SUCCEEDED(blobImpl->SetMutable(false))); diff --git a/dom/ipc/tests/test_blob_sliced_from_parent_process.html b/dom/ipc/tests/test_blob_sliced_from_parent_process.html index 00f8b13110..8a00ed5083 100644 --- a/dom/ipc/tests/test_blob_sliced_from_parent_process.html +++ b/dom/ipc/tests/test_blob_sliced_from_parent_process.html @@ -44,11 +44,6 @@ function childFrameScript() { sendAsyncMessage(messageName, { op: "done", result: result }); } - function createFileReader() { - return Cc["@mozilla.org/files/filereader;1"] - .createInstance(Ci.nsIDOMFileReader); - } - function grabAndContinue(arg) { testGenerator.send(arg); } @@ -65,7 +60,7 @@ function childFrameScript() { info("Reading blob"); - let reader = createFileReader(); + let reader = new FileReader(); reader.addEventListener("load", grabAndContinue); reader.readAsText(blob); @@ -84,7 +79,7 @@ function childFrameScript() { info("Reading slice"); - reader = createFileReader(); + reader = new FileReader(); reader.addEventListener("load", grabAndContinue); reader.readAsText(slice); diff --git a/dom/media/moz.build b/dom/media/moz.build index 1eb33dc6af..9e5acc1887 100644 --- a/dom/media/moz.build +++ b/dom/media/moz.build @@ -301,6 +301,11 @@ if CONFIG['MOZ_WEBRTC']: DEFINES['MOZILLA_INTERNAL_API'] = True +if CONFIG['OS_TARGET'] == 'WINNT': + DEFINES['WEBRTC_WIN'] = True +else: + DEFINES['WEBRTC_POSIX'] = True + if CONFIG['MOZ_OMX_DECODER']: DEFINES['MOZ_OMX_DECODER'] = True diff --git a/dom/media/omx/OMXCodecWrapper.cpp b/dom/media/omx/OMXCodecWrapper.cpp index d3df99ec41..df43dd8a42 100644 --- a/dom/media/omx/OMXCodecWrapper.cpp +++ b/dom/media/omx/OMXCodecWrapper.cpp @@ -45,12 +45,18 @@ enum BufferState bool OMXCodecReservation::ReserveOMXCodec() { - if (mClient) { - // Already tried reservation. - return false; + if (!mClient) { + mClient = new mozilla::MediaSystemResourceClient(mType); + } else { + if (mOwned) { + //CODEC_ERROR("OMX Reservation: (%d) already owned", (int) mType); + return true; + } + //CODEC_ERROR("OMX Reservation: (%d) already NOT owned", (int) mType); } - mClient = new mozilla::MediaSystemResourceClient(mType); - return mClient->AcquireSyncNoWait(); // don't wait if resrouce is not available + mOwned = mClient->AcquireSyncNoWait(); // don't wait if resource is not available + //CODEC_ERROR("OMX Reservation: (%d) Acquire was %s", (int) mType, mOwned ? "Successful" : "Failed"); + return mOwned; } void @@ -59,7 +65,12 @@ OMXCodecReservation::ReleaseOMXCodec() if (!mClient) { return; } - mClient->ReleaseResource(); + //CODEC_ERROR("OMX Reservation: Releasing resource: (%d) %s", (int) mType, mOwned ? "Owned" : "Not owned"); + if (mOwned) { + mClient->ReleaseResource(); + mClient = nullptr; + mOwned = false; + } } OMXAudioEncoder* diff --git a/dom/media/omx/OMXCodecWrapper.h b/dom/media/omx/OMXCodecWrapper.h index aee9157ad4..fe8a2d994d 100644 --- a/dom/media/omx/OMXCodecWrapper.h +++ b/dom/media/omx/OMXCodecWrapper.h @@ -26,7 +26,7 @@ namespace android { class OMXCodecReservation : public RefBase { public: - OMXCodecReservation(bool aEncoder) + OMXCodecReservation(bool aEncoder) : mOwned(false) { mType = aEncoder ? mozilla::MediaSystemResourceType::VIDEO_ENCODER : mozilla::MediaSystemResourceType::VIDEO_DECODER; @@ -45,6 +45,7 @@ public: private: mozilla::MediaSystemResourceType mType; + bool mOwned; // We already own this resource RefPtr mClient; }; diff --git a/dom/media/systemservices/CamerasChild.cpp b/dom/media/systemservices/CamerasChild.cpp index d4adf6f024..094887d21e 100644 --- a/dom/media/systemservices/CamerasChild.cpp +++ b/dom/media/systemservices/CamerasChild.cpp @@ -647,7 +647,7 @@ bool CamerasChild::RecvDeliverFrame(const int& capEngine, const int& capId, mozilla::ipc::Shmem&& shmem, - const int& size, + const size_t& size, const uint32_t& time_stamp, const int64_t& ntp_time, const int64_t& render_time) diff --git a/dom/media/systemservices/CamerasChild.h b/dom/media/systemservices/CamerasChild.h index 0ead231447..16202adc7b 100644 --- a/dom/media/systemservices/CamerasChild.h +++ b/dom/media/systemservices/CamerasChild.h @@ -85,7 +85,7 @@ public: // IPC messages recevied, received on the PBackground thread // these are the actual callbacks with data virtual bool RecvDeliverFrame(const int&, const int&, mozilla::ipc::Shmem&&, - const int&, const uint32_t&, const int64_t&, + const size_t&, const uint32_t&, const int64_t&, const int64_t&) override; virtual bool RecvFrameSizeChange(const int&, const int&, const int& w, const int& h) override; @@ -159,9 +159,9 @@ private: Mutex mRequestMutex; // Hold to wait for an async response to our calls Monitor mReplyMonitor; - // Async resposne valid? + // Async response valid? bool mReceivedReply; - // Aynsc reponses data contents; + // Async responses data contents; bool mReplySuccess; int mReplyInteger; webrtc::CaptureCapability mReplyCapability; diff --git a/dom/media/systemservices/CamerasParent.cpp b/dom/media/systemservices/CamerasParent.cpp index 6459ccab98..9bbc112ad3 100644 --- a/dom/media/systemservices/CamerasParent.cpp +++ b/dom/media/systemservices/CamerasParent.cpp @@ -16,6 +16,8 @@ #include "nsThreadUtils.h" #include "nsXPCOM.h" +#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" + #undef LOG #undef LOG_ENABLED mozilla::LazyLogModule gCamerasParentLog("CamerasParent"); @@ -90,7 +92,7 @@ public: int cap_id, ShmemBuffer buffer, unsigned char* altbuffer, - int size, + size_t size, uint32_t time_stamp, int64_t ntp_time, int64_t render_time) @@ -136,7 +138,7 @@ private: int mCapId; ShmemBuffer mBuffer; mozilla::UniquePtr mAlternateBuffer; - int mSize; + size_t mSize; uint32_t mTimeStamp; int64_t mNtpTime; int64_t mRenderTime; @@ -184,6 +186,7 @@ CamerasParent::DispatchToVideoCaptureThread(nsRunnable *event) void CamerasParent::StopVideoCapture() { + LOG((__PRETTY_FUNCTION__)); // We are called from the main thread (xpcom-shutdown) or // from PBackground (when the Actor shuts down). // Shut down the WebRTC stack (on the capture thread) @@ -232,7 +235,7 @@ CamerasParent::DeliverFrameOverIPC(CaptureEngine cap_engine, int cap_id, ShmemBuffer buffer, unsigned char* altbuffer, - int size, + size_t size, uint32_t time_stamp, int64_t ntp_time, int64_t render_time) @@ -280,7 +283,7 @@ CamerasParent::GetBuffer(size_t aSize) int CallbackHelper::DeliverFrame(unsigned char* buffer, - int size, + size_t size, uint32_t time_stamp, int64_t ntp_time, int64_t render_time, @@ -309,6 +312,17 @@ CallbackHelper::DeliverFrame(unsigned char* buffer, thread->Dispatch(runnable, NS_DISPATCH_NORMAL); return 0; } +// XXX!!! FIX THIS -- we should move to pure DeliverI420Frame +int +CallbackHelper::DeliverI420Frame(const webrtc::I420VideoFrame& webrtc_frame) +{ + return DeliverFrame(const_cast(webrtc_frame.buffer(webrtc::kYPlane)), + CalcBufferSize(webrtc::kI420, webrtc_frame.width(), webrtc_frame.height()), + webrtc_frame.timestamp(), + webrtc_frame.ntp_time_ms(), + webrtc_frame.render_time_ms(), + (void*) webrtc_frame.native_handle()); +} bool CamerasParent::RecvReleaseFrame(mozilla::ipc::Shmem&& s) { @@ -393,6 +407,7 @@ CamerasParent::SetupEngine(CaptureEngine aCapEngine) void CamerasParent::CloseEngines() { + LOG((__PRETTY_FUNCTION__)); if (!mWebRTCAlive) { return; } @@ -686,10 +701,12 @@ CamerasParent::RecvReleaseCaptureDevice(const int& aCapEngine, RefPtr ipc_runnable = media::NewRunnableFrom([self, error, numdev]() -> nsresult { if (self->IsShuttingDown()) { + LOG(("In Shutdown, not Releasing")); return NS_ERROR_FAILURE; } if (error) { Unused << self->SendReplyFailure(); + LOG(("Failed to free device nr %d", numdev)); return NS_ERROR_FAILURE; } else { Unused << self->SendReplySuccess(); diff --git a/dom/media/systemservices/CamerasParent.h b/dom/media/systemservices/CamerasParent.h index cbbfc79dc6..e3c95e9d2c 100644 --- a/dom/media/systemservices/CamerasParent.h +++ b/dom/media/systemservices/CamerasParent.h @@ -41,11 +41,12 @@ public: virtual int FrameSizeChange(unsigned int w, unsigned int h, unsigned int streams) override; virtual int DeliverFrame(unsigned char* buffer, - int size, + size_t size, uint32_t time_stamp, int64_t ntp_time, int64_t render_time, void *handle) override; + virtual int DeliverI420Frame(const webrtc::I420VideoFrame& webrtc_frame) override; virtual bool IsTextureSupported() override { return false; }; friend CamerasParent; @@ -108,7 +109,7 @@ public: int cap_id, ShmemBuffer buffer, unsigned char* altbuffer, - int size, + size_t size, uint32_t time_stamp, int64_t ntp_time, int64_t render_time); diff --git a/dom/media/systemservices/LoadManager.cpp b/dom/media/systemservices/LoadManager.cpp index 55506bab8d..b090c80555 100644 --- a/dom/media/systemservices/LoadManager.cpp +++ b/dom/media/systemservices/LoadManager.cpp @@ -170,14 +170,6 @@ LoadManagerSingleton::AddObserver(webrtc::CPULoadStateObserver * aObserver) LOG(("LoadManager - Adding Observer")); MutexAutoLock lock(mLock); mObservers.AppendElement(aObserver); - if (mObservers.Length() == 1) { - if (!mLoadMonitor) { - mLoadMonitor = new LoadMonitor(mLoadMeasurementInterval); - mLoadMonitor->Init(mLoadMonitor); - mLoadMonitor->SetLoadChangeCallback(this); - mLastStateChange = TimeStamp::Now(); - } - } } void diff --git a/dom/media/systemservices/MediaUtils.h b/dom/media/systemservices/MediaUtils.h index d50472ffd6..bde0c913fa 100644 --- a/dom/media/systemservices/MediaUtils.h +++ b/dom/media/systemservices/MediaUtils.h @@ -10,6 +10,7 @@ #include "nsAutoPtr.h" #include "nsThreadUtils.h" #include "nsIAsyncShutdown.h" +#include "base/task.h" namespace mozilla { namespace media { diff --git a/dom/media/systemservices/PCameras.ipdl b/dom/media/systemservices/PCameras.ipdl index 637b04a95a..a71e054cb1 100644 --- a/dom/media/systemservices/PCameras.ipdl +++ b/dom/media/systemservices/PCameras.ipdl @@ -27,7 +27,7 @@ child: async FrameSizeChange(int capEngine, int cap_id, int w, int h); // transfers ownership of |buffer| from parent to child async DeliverFrame(int capEngine, int cap_id, - Shmem buffer, int size, uint32_t time_stamp, + Shmem buffer, size_t size, uint32_t time_stamp, int64_t ntp_time, int64_t render_time); async ReplyNumberOfCaptureDevices(int numdev); async ReplyNumberOfCapabilities(int numdev); diff --git a/dom/media/systemservices/moz.build b/dom/media/systemservices/moz.build index 27a5f68ac7..3645b57baf 100644 --- a/dom/media/systemservices/moz.build +++ b/dom/media/systemservices/moz.build @@ -26,6 +26,11 @@ if CONFIG['MOZ_WEBRTC']: '/media/webrtc/signaling', '/media/webrtc/trunk', ] +if CONFIG['OS_TARGET'] == 'WINNT': + DEFINES['WEBRTC_WIN'] = True +else: + DEFINES['WEBRTC_POSIX'] = True + if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'): EXPORTS += [ diff --git a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp index ebb2bbb2ce..c527ac03a2 100644 --- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp +++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp @@ -271,7 +271,7 @@ MediaEngineRemoteVideoSource::FrameSizeChange(unsigned int w, unsigned int h, int MediaEngineRemoteVideoSource::DeliverFrame(unsigned char* buffer, - int size, + size_t size, uint32_t time_stamp, int64_t ntp_time, int64_t render_time, @@ -283,7 +283,7 @@ MediaEngineRemoteVideoSource::DeliverFrame(unsigned char* buffer, return 0; } - if (mWidth*mHeight + 2*(((mWidth+1)/2)*((mHeight+1)/2)) != size) { + if ((size_t) (mWidth*mHeight + 2*(((mWidth+1)/2)*((mHeight+1)/2))) != size) { MOZ_ASSERT(false, "Wrong size frame in DeliverFrame!"); return 0; } diff --git a/dom/media/webrtc/MediaEngineRemoteVideoSource.h b/dom/media/webrtc/MediaEngineRemoteVideoSource.h index 3415c8b101..ab0b3cccc5 100644 --- a/dom/media/webrtc/MediaEngineRemoteVideoSource.h +++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.h @@ -38,6 +38,10 @@ #include "NullTransport.h" +namespace webrtc { +class I420VideoFrame; +} + namespace mozilla { /** @@ -53,11 +57,13 @@ public: virtual int FrameSizeChange(unsigned int w, unsigned int h, unsigned int streams) override; virtual int DeliverFrame(unsigned char* buffer, - int size, + size_t size, uint32_t time_stamp, int64_t ntp_time, int64_t render_time, void *handle) override; + // XXX!!!! FIX THIS + virtual int DeliverI420Frame(const webrtc::I420VideoFrame& webrtc_frame) override { return 0; }; virtual bool IsTextureSupported() override { return false; }; // MediaEngineCameraVideoSource diff --git a/dom/media/webrtc/MediaEngineWebRTC.cpp b/dom/media/webrtc/MediaEngineWebRTC.cpp index 650656c5c0..23040d2182 100644 --- a/dom/media/webrtc/MediaEngineWebRTC.cpp +++ b/dom/media/webrtc/MediaEngineWebRTC.cpp @@ -251,7 +251,7 @@ MediaEngineWebRTC::EnumerateAudioDevices(dom::MediaSourceEnum aMediaSource, JNIEnv* const env = jni::GetEnvForThread(); MOZ_ALWAYS_TRUE(!env->GetJavaVM(&jvm)); - if (webrtc::VoiceEngine::SetAndroidObjects(jvm, env, (void*)context) != 0) { + if (webrtc::VoiceEngine::SetAndroidObjects(jvm, (void*)context) != 0) { LOG(("VoiceEngine:SetAndroidObjects Failed")); return; } diff --git a/dom/media/webrtc/moz.build b/dom/media/webrtc/moz.build index 7789514afc..3e1a538ab4 100644 --- a/dom/media/webrtc/moz.build +++ b/dom/media/webrtc/moz.build @@ -20,6 +20,10 @@ EXPORTS += [ ] if CONFIG['MOZ_WEBRTC']: + if CONFIG['OS_TARGET'] == 'WINNT': + DEFINES['WEBRTC_WIN'] = True + else: + DEFINES['WEBRTC_POSIX'] = True EXPORTS += ['AudioOutputObserver.h', 'MediaEngineRemoteVideoSource.h', 'MediaEngineWebRTC.h'] diff --git a/dom/mobilemessage/gonk/MmsService.js b/dom/mobilemessage/gonk/MmsService.js index b9386c7de4..a58ea4eb6d 100644 --- a/dom/mobilemessage/gonk/MmsService.js +++ b/dom/mobilemessage/gonk/MmsService.js @@ -8,7 +8,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; -Cu.importGlobalProperties(['Blob']); +Cu.importGlobalProperties(['Blob', 'FileReader']); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/PhoneNumberUtils.jsm"); @@ -1303,8 +1303,7 @@ SendTransaction.prototype = Object.create(CancellableTransaction.prototype, { return; } - let fileReader = Cc["@mozilla.org/files/filereader;1"] - .createInstance(Ci.nsIDOMFileReader); + let fileReader = new FileReader(); fileReader.addEventListener("loadend", (aEvent) => { let arrayBuffer = aEvent.target.result; aPart.content = new Uint8Array(arrayBuffer); diff --git a/dom/security/test/csp/file_child-src_iframe.html b/dom/security/test/csp/file_child-src_iframe.html new file mode 100644 index 0000000000..3534aa329b --- /dev/null +++ b/dom/security/test/csp/file_child-src_iframe.html @@ -0,0 +1,61 @@ + + + + Bug 1045891 + + + + + + diff --git a/dom/security/test/csp/file_child-src_inner_frame.html b/dom/security/test/csp/file_child-src_inner_frame.html new file mode 100644 index 0000000000..e42102430e --- /dev/null +++ b/dom/security/test/csp/file_child-src_inner_frame.html @@ -0,0 +1,21 @@ + + + + Bug 1045891 + + + + + + diff --git a/dom/security/test/csp/file_child-src_service_worker.html b/dom/security/test/csp/file_child-src_service_worker.html new file mode 100644 index 0000000000..c970dc4f48 --- /dev/null +++ b/dom/security/test/csp/file_child-src_service_worker.html @@ -0,0 +1,29 @@ + + + + Bug 1045891 + + + + + diff --git a/dom/security/test/csp/file_child-src_service_worker.js b/dom/security/test/csp/file_child-src_service_worker.js new file mode 100644 index 0000000000..53f7687077 --- /dev/null +++ b/dom/security/test/csp/file_child-src_service_worker.js @@ -0,0 +1,3 @@ +this.addEventListener('install', function(event) { + close(); +}); diff --git a/dom/security/test/csp/file_child-src_shared_worker-redirect.html b/dom/security/test/csp/file_child-src_shared_worker-redirect.html new file mode 100644 index 0000000000..313915302e --- /dev/null +++ b/dom/security/test/csp/file_child-src_shared_worker-redirect.html @@ -0,0 +1,47 @@ + + + + Bug 1045891 + + + + + diff --git a/dom/security/test/csp/file_child-src_shared_worker.html b/dom/security/test/csp/file_child-src_shared_worker.html new file mode 100644 index 0000000000..0e9a56a294 --- /dev/null +++ b/dom/security/test/csp/file_child-src_shared_worker.html @@ -0,0 +1,34 @@ + + + + Bug 1045891 + + + + + diff --git a/dom/security/test/csp/file_child-src_shared_worker.js b/dom/security/test/csp/file_child-src_shared_worker.js new file mode 100644 index 0000000000..0fca1394c3 --- /dev/null +++ b/dom/security/test/csp/file_child-src_shared_worker.js @@ -0,0 +1,8 @@ +onconnect = function(e) { + var port = e.ports[0]; + port.addEventListener('message', function(e) { + port.postMessage('success'); + }); + + port.start(); +} diff --git a/dom/security/test/csp/file_child-src_shared_worker_data.html b/dom/security/test/csp/file_child-src_shared_worker_data.html new file mode 100644 index 0000000000..a4befe4ca3 --- /dev/null +++ b/dom/security/test/csp/file_child-src_shared_worker_data.html @@ -0,0 +1,37 @@ + + + + + Bug 1045891 + + + + + diff --git a/dom/security/test/csp/file_child-src_worker-redirect.html b/dom/security/test/csp/file_child-src_worker-redirect.html new file mode 100644 index 0000000000..dbceec1cc9 --- /dev/null +++ b/dom/security/test/csp/file_child-src_worker-redirect.html @@ -0,0 +1,50 @@ + + + + Bug 1045891 + + + + + diff --git a/dom/security/test/csp/file_child-src_worker.html b/dom/security/test/csp/file_child-src_worker.html new file mode 100644 index 0000000000..9300d3f617 --- /dev/null +++ b/dom/security/test/csp/file_child-src_worker.html @@ -0,0 +1,32 @@ + + + + Bug 1045891 + + + + + diff --git a/dom/security/test/csp/file_child-src_worker.js b/dom/security/test/csp/file_child-src_worker.js new file mode 100644 index 0000000000..1d93cac6b9 --- /dev/null +++ b/dom/security/test/csp/file_child-src_worker.js @@ -0,0 +1,4 @@ +onmessage = function(e) { + postMessage('worker'); +}; + diff --git a/dom/security/test/csp/file_child-src_worker_data.html b/dom/security/test/csp/file_child-src_worker_data.html new file mode 100644 index 0000000000..e9e22f01da --- /dev/null +++ b/dom/security/test/csp/file_child-src_worker_data.html @@ -0,0 +1,33 @@ + + + + Bug 1045891 + + + + + diff --git a/dom/security/test/csp/file_main.html^headers^ b/dom/security/test/csp/file_main.html^headers^ index c7fdbae204..3338de389b 100644 --- a/dom/security/test/csp/file_main.html^headers^ +++ b/dom/security/test/csp/file_main.html^headers^ @@ -1 +1 @@ -Content-Security-Policy: default-src 'self' ; style-src 'unsafe-inline' 'self' +Content-Security-Policy: default-src 'self' blob: ; style-src 'unsafe-inline' 'self' diff --git a/dom/security/test/csp/file_main.js b/dom/security/test/csp/file_main.js index 864a5d230b..0bc15b6827 100644 --- a/dom/security/test/csp/file_main.js +++ b/dom/security/test/csp/file_main.js @@ -1,16 +1,28 @@ -// some javascript for the CSP XHR tests -// +function doXHR(uri) { + try { + var xhr = new XMLHttpRequest(); + xhr.open("GET", uri); + xhr.send(); + } catch(ex) {} +} +doXHR("http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs?testid=xhr_good"); +doXHR("http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid=xhr_bad"); +fetch("http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs?testid=fetch_good"); +fetch("http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid=fetch_bad"); +navigator.sendBeacon("http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs?testid=beacon_good"); try { - var xhr_good = new XMLHttpRequest(); - var xhr_good_uri ="http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs?testid=xhr_good"; - xhr_good.open("GET", xhr_good_uri, true); - xhr_good.send(null); -} catch(e) {} + navigator.sendBeacon("http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid=beacon_bad"); +} catch(ex) {} -try { - var xhr_bad = new XMLHttpRequest(); - var xhr_bad_uri ="http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid=xhr_bad"; - xhr_bad.open("GET", xhr_bad_uri, true); - xhr_bad.send(null); -} catch(e) {} + +new Worker("file_main_worker.js").postMessage({inherited : false}); + + +var blobxhr = new XMLHttpRequest(); +blobxhr.open("GET", "file_main_worker.js") +blobxhr.responseType = "blob"; +blobxhr.send(); +blobxhr.onload = () => { + new Worker(URL.createObjectURL(blobxhr.response)).postMessage({inherited : true}); +} diff --git a/dom/security/test/csp/file_main_worker.js b/dom/security/test/csp/file_main_worker.js new file mode 100644 index 0000000000..d8953eec74 --- /dev/null +++ b/dom/security/test/csp/file_main_worker.js @@ -0,0 +1,28 @@ +function doXHR(uri) { + try { + var xhr = new XMLHttpRequest(); + xhr.open("GET", uri); + xhr.send(); + } catch(ex) {} +} + +var sameBase = "http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs?testid="; +var crossBase = "http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid="; + +onmessage = (e) => { + for (base of [sameBase, crossBase]) { + var prefix; + var suffix; + if (e.data.inherited) { + prefix = base + "worker_inherited_" + suffix = base == sameBase ? "_good" : "_bad"; + } + else { + prefix = base + "worker_" + suffix = base == sameBase ? "_same_good" : "_cross_good"; + } + doXHR(prefix + "xhr" + suffix); + fetch(prefix + "fetch" + suffix); + try { importScripts(prefix + "script" + suffix); } catch(ex) {} + } +} diff --git a/dom/security/test/csp/file_redirect_worker.sjs b/dom/security/test/csp/file_redirect_worker.sjs new file mode 100644 index 0000000000..27df6a5fdf --- /dev/null +++ b/dom/security/test/csp/file_redirect_worker.sjs @@ -0,0 +1,34 @@ +// SJS file to serve resources for CSP redirect tests +// This file redirects to a specified resource. +const THIS_SITE = "http://mochi.test:8888"; +const OTHER_SITE = "http://example.com"; + +function handleRequest(request, response) +{ + var query = {}; + request.queryString.split('&').forEach(function (val) { + var [name, value] = val.split('='); + query[name] = unescape(value); + }); + + var resource = query['path']; + + response.setHeader("Cache-Control", "no-cache", false); + var loc = ''; + + // redirect to a resource on this site + if (query["redir"] == "same") { + loc = THIS_SITE+resource+"#"+query['page_id'] + } + + // redirect to a resource on a different site + else if (query["redir"] == "other") { + loc = OTHER_SITE+resource+"#"+query['page_id'] + } + + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", loc, false); + + response.write(''); + return; +} diff --git a/dom/security/test/csp/file_redirects_main.html b/dom/security/test/csp/file_redirects_main.html index 651f44d384..5c9affea04 100644 --- a/dom/security/test/csp/file_redirects_main.html +++ b/dom/security/test/csp/file_redirects_main.html @@ -11,17 +11,18 @@ var thisSite = "http://mochi.test:8888"; var otherSite = "http://example.com"; var page = "/tests/dom/security/test/csp/file_redirects_page.sjs"; -var tests = { "font-src": thisSite+page+"?testid=font-src&csp=1", - "frame-src": thisSite+page+"?testid=frame-src&csp=1", - "img-src": thisSite+page+"?testid=img-src&csp=1", - "media-src": thisSite+page+"?testid=media-src&csp=1", - "object-src": thisSite+page+"?testid=object-src&csp=1", - "script-src": thisSite+page+"?testid=script-src&csp=1", - "style-src": thisSite+page+"?testid=style-src&csp=1", - "worker": thisSite+page+"?testid=worker&csp=1", - "xhr-src": thisSite+page+"?testid=xhr-src&csp=1", - "script-src-from-worker": thisSite+page+"?testid=script-src-from-worker&csp=1", - "img-src-from-css": thisSite+page+"?testid=img-src-from-css&csp=1", +var tests = { "font-src": thisSite+page+"?testid=font-src", + "frame-src": thisSite+page+"?testid=frame-src", + "img-src": thisSite+page+"?testid=img-src", + "media-src": thisSite+page+"?testid=media-src", + "object-src": thisSite+page+"?testid=object-src", + "script-src": thisSite+page+"?testid=script-src", + "style-src": thisSite+page+"?testid=style-src", + "worker": thisSite+page+"?testid=worker", + "xhr-src": thisSite+page+"?testid=xhr-src", + "from-worker": thisSite+page+"?testid=from-worker", + "from-blob-worker": thisSite+page+"?testid=from-blob-worker", + "img-src-from-css": thisSite+page+"?testid=img-src-from-css", }; var container = document.getElementById("container"); diff --git a/dom/security/test/csp/file_redirects_page.sjs b/dom/security/test/csp/file_redirects_page.sjs index 58eff8af64..9e3c0d0350 100644 --- a/dom/security/test/csp/file_redirects_page.sjs +++ b/dom/security/test/csp/file_redirects_page.sjs @@ -14,9 +14,13 @@ function handleRequest(request, response) var resource = "/tests/dom/security/test/csp/file_redirects_resource.sjs"; // CSP header value - if (query["csp"] == 1) { - response.setHeader("Content-Security-Policy", "default-src 'self' ; style-src 'self' 'unsafe-inline'", false); + var additional = "" + if (query['testid'] == "worker") { + additional = "; script-src 'self' 'unsafe-inline'"; } + response.setHeader("Content-Security-Policy", + "default-src 'self' blob: ; style-src 'self' 'unsafe-inline'" + additional, + false); // downloadable font that redirects to another site if (query["testid"] == "font-src") { @@ -61,13 +65,13 @@ function handleRequest(request, response) // external stylesheet that redirects to another site if (query["testid"] == "style-src") { - response.write(''); + response.write(''); return; } // worker script resource that redirects to another site if (query["testid"] == "worker") { - response.write(''); + response.write(''); return; } @@ -84,13 +88,27 @@ function handleRequest(request, response) return; } - if (query["testid"] == "script-src-from-worker") { + if (query["testid"] == "from-worker") { // loads a script; launches a worker; that worker uses importscript; which then gets redirected // So it's: - // '); + // .. calls xhr("res=xhr-resp") + // .. calls fetch("res=xhr-resp") + response.write(''); + return; + } + + if (query["testid"] == "from-blob-worker") { + // loads a script; launches a worker; that worker uses importscript; which then gets redirected + // So it's: + // '); return; } } diff --git a/dom/security/test/csp/file_redirects_resource.sjs b/dom/security/test/csp/file_redirects_resource.sjs index b921bd608b..d281f19d8b 100644 --- a/dom/security/test/csp/file_redirects_resource.sjs +++ b/dom/security/test/csp/file_redirects_resource.sjs @@ -102,38 +102,45 @@ function handleRequest(request, response) // script that loads an internal worker that uses importScripts on a redirect // to an external script. - if (query["res"] == "loadWorkerThatImports") { + if (query["res"] == "loadWorkerThatMakesRequests") { // this creates a worker (same origin) that imports a redirecting script. - let workerURL = thisSite + resource + '?res=importScriptWorker&id=' + query["id"]; + let workerURL = thisSite + resource + '?res=makeRequestsWorker&id=' + query["id"]; response.setHeader("Content-Type", "application/javascript", false); - response.write("var w=new Worker('" + workerURL + "'); w.onmessage=function(event){ alert(event.data); }"); + response.write("new Worker('" + workerURL + "');"); + return; + } + + // script that loads an internal worker that uses importScripts on a redirect + // to an external script. + if (query["res"] == "loadBlobWorkerThatMakesRequests") { + // this creates a worker (same origin) that imports a redirecting script. + let workerURL = thisSite + resource + '?res=makeRequestsWorker&id=' + query["id"]; + response.setHeader("Content-Type", "application/javascript", false); + response.write("var x = new XMLHttpRequest(); x.open('GET', '" + workerURL + "'); "); + response.write("x.responseType = 'blob'; x.send(); "); + response.write("x.onload = () => { new Worker(URL.createObjectURL(x.response)); };"); return; } // source for a worker that simply calls importScripts on a script that // redirects. - if (query["res"] == "importScriptWorker") { + if (query["res"] == "makeRequestsWorker") { // this is code for a worker that imports a redirected script. - let scriptURL = thisSite + resource + "?redir=other&res=script&id=" + query["id"]; + let scriptURL = thisSite + resource + "?redir=other&res=script&id=script-src-redir-" + query["id"]; + let xhrURL = thisSite + resource + "?redir=other&res=xhr-resp&id=xhr-src-redir-" + query["id"]; + let fetchURL = thisSite + resource + "?redir=other&res=xhr-resp&id=fetch-src-redir-" + query["id"]; response.setHeader("Content-Type", "application/javascript", false); - response.write("importScripts('" + scriptURL + "');"); + response.write("try { importScripts('" + scriptURL + "'); } catch(ex) {} "); + response.write("var x = new XMLHttpRequest(); x.open('GET', '" + xhrURL + "'); x.send();"); + response.write("fetch('" + fetchURL + "');"); return; } // script that invokes XHR if (query["res"] == "xhr") { - response.setHeader("Content-Type", "text/html", false); - var resp = 'var x = new XMLHttpRequest(); x.open("GET", "' + otherSite + - resource+'?res=xhr-resp&testid=xhr-src-redir", false); ' + - 'x.send(null);'; - response.write(resp); - return; - } - - if (query["res"] == "xhr") { - response.setHeader("Content-Type", "text/html", false); - var resp = 'var x = new XMLHttpRequest(); x.open("GET", "' + otherSite + - resource+'?res=xhr-resp&testid=xhr-src-redir", false); ' + + response.setHeader("Content-Type", "application/javascript", false); + var resp = 'var x = new XMLHttpRequest();x.open("GET", "' + thisSite + + resource+'?redir=other&res=xhr-resp&id=xhr-src-redir", false);\n' + 'x.send(null);'; response.write(resp); return; diff --git a/dom/security/test/csp/file_service_worker.html b/dom/security/test/csp/file_service_worker.html new file mode 100644 index 0000000000..00a2b40206 --- /dev/null +++ b/dom/security/test/csp/file_service_worker.html @@ -0,0 +1,19 @@ + + + + Bug 1208559 - ServiceWorker registration not governed by CSP + + + + + diff --git a/dom/security/test/csp/file_service_worker.js b/dom/security/test/csp/file_service_worker.js new file mode 100644 index 0000000000..1bf583f4cc --- /dev/null +++ b/dom/security/test/csp/file_service_worker.js @@ -0,0 +1 @@ +dump("service workers: hello world"); diff --git a/dom/security/test/csp/file_worker_redirect.html b/dom/security/test/csp/file_worker_redirect.html deleted file mode 100644 index be80f5795f..0000000000 --- a/dom/security/test/csp/file_worker_redirect.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - Bug 949706 - CSP: Correct handling of web workers importing scripts that get redirected - - - - - diff --git a/dom/security/test/csp/file_worker_redirect.sjs b/dom/security/test/csp/file_worker_redirect.sjs deleted file mode 100644 index 6c4acd6e7a..0000000000 --- a/dom/security/test/csp/file_worker_redirect.sjs +++ /dev/null @@ -1,37 +0,0 @@ -// testserver customized for the needs of: -// Bug 949706 - CSP: Correct handling of web workers importing scripts that get redirected - -function handleRequest(request, response) -{ - response.setHeader("Cache-Control", "no-cache", false); - response.setHeader("Content-Type", "text/html", false); - - var query = request.queryString; - - if (query === "stage_0_script_loads_worker") { - var newWorker = - "var myWorker = new Worker(\"file_worker_redirect.sjs?stage_1_worker_import_scripts\");" + - "myWorker.onmessage = function (event) { parent.checkResult(\"allowed\"); };" + - "myWorker.onerror = function (event) { parent.checkResult(\"blocked\"); };"; - response.write(newWorker); - return; - } - - if (query === "stage_1_worker_import_scripts") { - response.write("importScripts(\"file_worker_redirect.sjs?stage_2_redirect_imported_script\");"); - return; - } - - if (query === "stage_2_redirect_imported_script") { - var newLocation = - "http://test1.example.com/tests/dom/security/test/csp/file_worker_redirect.sjs?stage_3_target_script"; - response.setStatusLine("1.1", 302, "Found"); - response.setHeader("Location", newLocation, false); - return; - } - - if (query === "stage_3_target_script") { - response.write("postMessage(\"imported script loaded\");"); - return; - } -} diff --git a/dom/security/test/csp/mochitest.ini b/dom/security/test/csp/mochitest.ini index 53ea996acd..fae1bb1c7c 100644 --- a/dom/security/test/csp/mochitest.ini +++ b/dom/security/test/csp/mochitest.ini @@ -43,6 +43,7 @@ support-files = file_main.html file_main.html^headers^ file_main.js + file_main_worker.js file_web_manifest.html file_web_manifest_remote.html file_web_manifest_https.html @@ -115,8 +116,6 @@ support-files = file_multi_policy_injection_bypass_2.html^headers^ file_null_baseuri.html file_form-action.html - file_worker_redirect.html - file_worker_redirect.sjs file_referrerdirective.html referrerdirective.sjs file_upgrade_insecure.html @@ -128,6 +127,21 @@ support-files = file_upgrade_insecure_referrer_server.sjs file_upgrade_insecure_cors.html file_upgrade_insecure_cors_server.sjs + file_service_worker.html + file_service_worker.js + file_child-src_iframe.html + file_child-src_inner_frame.html + file_child-src_worker.html + file_child-src_worker_data.html + file_child-src_worker-redirect.html + file_child-src_worker.js + file_child-src_service_worker.html + file_child-src_service_worker.js + file_child-src_shared_worker.html + file_child-src_shared_worker_data.html + file_child-src_shared_worker-redirect.html + file_child-src_shared_worker.js + file_redirect_worker.sjs [test_base-uri.html] [test_blob_data_schemes.html] @@ -181,7 +195,6 @@ skip-if = buildapp == 'b2g' # intermittent orange (bug 1028490) [test_null_baseuri.html] [test_referrerdirective.html] skip-if = buildapp == 'b2g' #no ssl support -[test_worker_redirect.html] [test_upgrade_insecure.html] # no ssl support as well as websocket tests do not work (see test_websocket.html) skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolkit == 'android' @@ -191,3 +204,10 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolk skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolkit == 'android' [test_upgrade_insecure_cors.html] skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolkit == 'android' +[test_service_worker.html] +skip-if = buildapp == 'b2g' #no ssl support +[test_child-src_worker.html] +skip-if = buildapp == 'b2g' #investigate in bug 1222904 +[test_child-src_worker_data.html] +[test_child-src_worker-redirect.html] +[test_child-src_iframe.html] diff --git a/dom/security/test/csp/test_CSP.html b/dom/security/test/csp/test_CSP.html index 2b508bd0d1..253ea8d3a7 100644 --- a/dom/security/test/csp/test_CSP.html +++ b/dom/security/test/csp/test_CSP.html @@ -25,6 +25,22 @@ window.tests = { script_bad: -1, xhr_good: -1, xhr_bad: -1, + fetch_good: -1, + fetch_bad: -1, + beacon_good: -1, + beacon_bad: -1, + worker_xhr_same_good: -1, + worker_xhr_cross_good: -1, + worker_fetch_same_good: -1, + worker_fetch_cross_good: -1, + worker_script_same_good: -1, + worker_script_cross_good: -1, + worker_inherited_xhr_good: -1, + worker_inherited_xhr_bad: -1, + worker_inherited_fetch_good: -1, + worker_inherited_fetch_bad: -1, + worker_inherited_script_good: -1, + worker_inherited_script_bad: -1, media_good: -1, media_bad: -1, font_good: -1, @@ -81,10 +97,11 @@ examiner.prototype = { window.examiner = new examiner(); window.testResult = function(testname, result, msg) { - //test already complete.... forget it... remember the first result. + // test already complete.... forget it... remember the first result. if (window.tests[testname] != -1) return; + ok(testname in window.tests, "It's a real test"); window.tests[testname] = result; is(result, true, testname + ' test: ' + msg); diff --git a/dom/security/test/csp/test_child-src_iframe.html b/dom/security/test/csp/test_child-src_iframe.html new file mode 100644 index 0000000000..b4ba36f89f --- /dev/null +++ b/dom/security/test/csp/test_child-src_iframe.html @@ -0,0 +1,114 @@ + + + + Bug 1045891 + + + + + +

+ + + + + diff --git a/dom/security/test/csp/test_child-src_worker-redirect.html b/dom/security/test/csp/test_child-src_worker-redirect.html new file mode 100644 index 0000000000..dfb99149cc --- /dev/null +++ b/dom/security/test/csp/test_child-src_worker-redirect.html @@ -0,0 +1,125 @@ + + + + Bug 1045891 + + + + + +

+ + + + + diff --git a/dom/security/test/csp/test_child-src_worker.html b/dom/security/test/csp/test_child-src_worker.html new file mode 100644 index 0000000000..1216e4e2f0 --- /dev/null +++ b/dom/security/test/csp/test_child-src_worker.html @@ -0,0 +1,131 @@ + + + + Bug 1045891 + + + + + +

+ + + + + diff --git a/dom/security/test/csp/test_child-src_worker_data.html b/dom/security/test/csp/test_child-src_worker_data.html new file mode 100644 index 0000000000..089d32dbec --- /dev/null +++ b/dom/security/test/csp/test_child-src_worker_data.html @@ -0,0 +1,126 @@ + + + + Bug 1045891 + + + + + +

+ + + + + diff --git a/dom/security/test/csp/test_redirects.html b/dom/security/test/csp/test_redirects.html index 4656dd70de..4a588dcbe1 100644 --- a/dom/security/test/csp/test_redirects.html +++ b/dom/security/test/csp/test_redirects.html @@ -86,10 +86,16 @@ var testExpectedResults = { "font-src": true, "worker-redir": false, "xhr-src": true, "xhr-src-redir": false, - "script-src-from-worker": true, /* test runs */ - "script-src-redir-from-worker": false, /* redir is blocked */ - "img-src-from-css": true, /* test runs */ - "img-src-redir-from-css": false, /* redir is blocked */ + "from-worker": true, + "script-src-redir-from-worker": true, /* redir is allowed since policy isn't inherited */ + "xhr-src-redir-from-worker": true, /* redir is allowed since policy isn't inherited */ + "fetch-src-redir-from-worker": true, /* redir is allowed since policy isn't inherited */ + "from-blob-worker": true, + "script-src-redir-from-blob-worker": false, + "xhr-src-redir-from-blob-worker": false, + "fetch-src-redir-from-blob-worker": false, + "img-src-from-css": true, + "img-src-redir-from-css": false, }; // takes the name of the test, the URL that was tested, and whether the diff --git a/dom/security/test/csp/test_service_worker.html b/dom/security/test/csp/test_service_worker.html new file mode 100644 index 0000000000..d1dfac7301 --- /dev/null +++ b/dom/security/test/csp/test_service_worker.html @@ -0,0 +1,62 @@ + + + + Bug 1208559 - ServiceWorker registration not governed by CSP + + + + + + + + + + diff --git a/dom/security/test/csp/test_worker_redirect.html b/dom/security/test/csp/test_worker_redirect.html deleted file mode 100644 index 62a43c77b3..0000000000 --- a/dom/security/test/csp/test_worker_redirect.html +++ /dev/null @@ -1,76 +0,0 @@ - - - - Bug 949706 - CSP: Correct handling of web workers importing scripts that get redirected - - - - - - - - - - diff --git a/dom/tests/mochitest/general/frameStoragePrevented.html b/dom/tests/mochitest/general/frameStoragePrevented.html index b29cf2c9d0..3554d6082c 100644 --- a/dom/tests/mochitest/general/frameStoragePrevented.html +++ b/dom/tests/mochitest/general/frameStoragePrevented.html @@ -4,7 +4,7 @@ frame for storage prevented test - - - - -

- -

-
-
-
-
diff --git a/dom/workers/test/test_csp.html^headers^ b/dom/workers/test/test_csp.html^headers^
index b91ba384d9..1c93210799 100644
--- a/dom/workers/test/test_csp.html^headers^
+++ b/dom/workers/test/test_csp.html^headers^
@@ -1,2 +1,2 @@
 Cache-Control: no-cache
-Content-Security-Policy: default-src 'self'
+Content-Security-Policy: default-src 'self' blob:
diff --git a/dom/workers/test/test_csp.js b/dom/workers/test/test_csp.js
index cc6fcd3d04..dcbcd8c3a1 100644
--- a/dom/workers/test/test_csp.js
+++ b/dom/workers/test/test_csp.js
@@ -2,49 +2,47 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
-msg = null;
-var errors = 5;
+var tests = 3;
 
-onerror = function(event) {
-  ok(true, msg);
-  if (!--errors) SimpleTest.finish();
-}
-
-msg = "No Eval allowed";
-worker = new Worker("csp_worker.js");
-worker.postMessage(0);
-worker.onmessage = function(event) {
-  ok(false, "Eval succeeded!");
-}
-
-msg = "No Eval allowed 2";
-worker = new Worker("csp_worker.js");
-worker.postMessage(4);
-worker.onmessage = function(event) {
-  ok(false, "Eval succeeded!");
-}
-
-msg = "ImportScripts data:";
-worker = new Worker("csp_worker.js");
-worker.postMessage(-1);
-worker.onmessage = function(event) {
-  ok(false, "Eval succeeded!");
-}
-
-msg = "ImportScripts javascript:";
-worker = new Worker("csp_worker.js");
-worker.postMessage(-2);
-worker.onmessage = function(event) {
-  ok(false, "Eval succeeded!");
-}
-
-msg = "Loading data:something";
-try {
-  worker = new Worker("data:application/javascript;base64,ZHVtcCgnaGVsbG8gd29ybGQnKQo=");
-  ok(false, "Should have thrown!");
-} catch (e) {
-  ok(true, "Threw as expected.");
-}
-
-worker = new Worker("javascript:dump(123);");
 SimpleTest.waitForExplicitFinish();
+
+testDone = function(event) {
+  if (!--tests) SimpleTest.finish();
+}
+
+// Workers don't inherit CSP
+worker = new Worker("csp_worker.js");
+worker.postMessage({ do: "eval" });
+worker.onmessage = function(event) {
+  is(event.data, 42, "Eval succeeded!");
+  testDone();
+}
+
+// blob: workers *do* inherit CSP
+xhr = new XMLHttpRequest;
+xhr.open("GET", "csp_worker.js");
+xhr.responseType = "blob";
+xhr.send();
+xhr.onload = (e) => {
+  uri = URL.createObjectURL(e.target.response);
+  worker = new Worker(uri);
+  worker.postMessage({ do: "eval" })
+  worker.onmessage = function(event) {
+    is(event.data, "Error: call to eval() blocked by CSP", "Eval threw");
+    testDone();
+  }
+}
+
+xhr = new XMLHttpRequest;
+xhr.open("GET", "csp_worker.js");
+xhr.responseType = "blob";
+xhr.send();
+xhr.onload = (e) => {
+  uri = URL.createObjectURL(e.target.response);
+  worker = new Worker(uri);
+  worker.postMessage({ do: "nest", uri: uri, level: 3 })
+  worker.onmessage = function(event) {
+    is(event.data, "Error: call to eval() blocked by CSP", "Eval threw in nested worker");
+    testDone();
+  }
+}
diff --git a/dom/workers/test/test_loadError.html b/dom/workers/test/test_loadError.html
index 355300c304..778b6ed771 100644
--- a/dom/workers/test/test_loadError.html
+++ b/dom/workers/test/test_loadError.html
@@ -13,55 +13,53 @@
 
-  
-
-
-  
-    
-      
-    
-    
-      
-      
-    
-  
Local Preview
- - diff --git a/media/webrtc/trunk/webrtc/test/manual/iframe-apprtc.html b/media/webrtc/trunk/webrtc/test/manual/iframe-apprtc.html deleted file mode 100644 index 31e0db10c0..0000000000 --- a/media/webrtc/trunk/webrtc/test/manual/iframe-apprtc.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - AppRTC web app in an IFRAME - - - - AppRTC in an <iframe> element:
- - - diff --git a/media/webrtc/trunk/webrtc/test/manual/iframe-video.html b/media/webrtc/trunk/webrtc/test/manual/iframe-video.html deleted file mode 100644 index 3cb532b091..0000000000 --- a/media/webrtc/trunk/webrtc/test/manual/iframe-video.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - IFRAME Single Local Preview (Video Only) - - - - - - \ No newline at end of file diff --git a/media/webrtc/trunk/webrtc/test/manual/multiple-audio.html b/media/webrtc/trunk/webrtc/test/manual/multiple-audio.html deleted file mode 100644 index 80e4b646c6..0000000000 --- a/media/webrtc/trunk/webrtc/test/manual/multiple-audio.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - Multiple Local Preview (Audio Only) - - - - - - - - - - - - - - - - - - - - - - -
Sound test
- - diff --git a/media/webrtc/trunk/webrtc/test/manual/multiple-video.html b/media/webrtc/trunk/webrtc/test/manual/multiple-video.html deleted file mode 100644 index fd82bf82cf..0000000000 --- a/media/webrtc/trunk/webrtc/test/manual/multiple-video.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - Multiple Local Preview (Video Only) - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Local Preview
- - diff --git a/media/webrtc/trunk/webrtc/test/manual/single-audio.html b/media/webrtc/trunk/webrtc/test/manual/single-audio.html deleted file mode 100644 index b5d1ed464a..0000000000 --- a/media/webrtc/trunk/webrtc/test/manual/single-audio.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - Single Local Preview (Audio Only) - - - - - - - - - - - - - -
Sound test
- - diff --git a/media/webrtc/trunk/webrtc/test/manual/single-video.html b/media/webrtc/trunk/webrtc/test/manual/single-video.html deleted file mode 100644 index 7a88dcf97d..0000000000 --- a/media/webrtc/trunk/webrtc/test/manual/single-video.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - Single Local Preview (Video Only) - - - - - - - - - - - - - -
Local Preview
- - diff --git a/media/webrtc/trunk/webrtc/test/manual/two-video-devices.html b/media/webrtc/trunk/webrtc/test/manual/two-video-devices.html deleted file mode 100644 index 44c0947bdc..0000000000 --- a/media/webrtc/trunk/webrtc/test/manual/two-video-devices.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - Single Local Preview (Video Only) - - - - - - - - - - - - - - -
Local Preview
- - \ No newline at end of file diff --git a/media/webrtc/trunk/webrtc/test/metrics.gyp b/media/webrtc/trunk/webrtc/test/metrics.gyp index 0486a7c9ea..eda0b054ee 100644 --- a/media/webrtc/trunk/webrtc/test/metrics.gyp +++ b/media/webrtc/trunk/webrtc/test/metrics.gyp @@ -21,7 +21,7 @@ 'type': 'static_library', 'dependencies': [ '<(webrtc_root)/common_video/common_video.gyp:common_video', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', ], 'sources': [ 'testsupport/metrics/video_metrics.h', diff --git a/media/webrtc/trunk/webrtc/test/mock_transport.h b/media/webrtc/trunk/webrtc/test/mock_transport.h index 388ee92e9d..5b1cb8dfb6 100644 --- a/media/webrtc/trunk/webrtc/test/mock_transport.h +++ b/media/webrtc/trunk/webrtc/test/mock_transport.h @@ -19,9 +19,9 @@ namespace webrtc { class MockTransport : public webrtc::Transport { public: MOCK_METHOD3(SendPacket, - int(int channel, const void* data, int len)); + int(int channel, const void* data, size_t len)); MOCK_METHOD3(SendRTCPPacket, - int(int channel, const void* data, int len)); + int(int channel, const void* data, size_t len)); }; } // namespace webrtc #endif // WEBRTC_TEST_MOCK_TRANSPORT_H_ diff --git a/media/webrtc/trunk/webrtc/test/null_transport.h b/media/webrtc/trunk/webrtc/test/null_transport.h index e8d4d10275..b80f751b1e 100644 --- a/media/webrtc/trunk/webrtc/test/null_transport.h +++ b/media/webrtc/trunk/webrtc/test/null_transport.h @@ -19,8 +19,8 @@ class PacketReceiver; namespace test { class NullTransport : public newapi::Transport { public: - virtual bool SendRtp(const uint8_t* packet, size_t length) OVERRIDE; - virtual bool SendRtcp(const uint8_t* packet, size_t length) OVERRIDE; + bool SendRtp(const uint8_t* packet, size_t length) override; + bool SendRtcp(const uint8_t* packet, size_t length) override; }; } // namespace test } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/test/rtcp_packet_parser.cc b/media/webrtc/trunk/webrtc/test/rtcp_packet_parser.cc index 558bee379e..b9e430fe9f 100644 --- a/media/webrtc/trunk/webrtc/test/rtcp_packet_parser.cc +++ b/media/webrtc/trunk/webrtc/test/rtcp_packet_parser.cc @@ -10,6 +10,8 @@ #include "webrtc/test/rtcp_packet_parser.h" +#include "testing/gtest/include/gtest/gtest.h" + namespace webrtc { namespace test { @@ -17,9 +19,10 @@ RtcpPacketParser::RtcpPacketParser() {} RtcpPacketParser::~RtcpPacketParser() {} -void RtcpPacketParser::Parse(const void *data, int len) { +void RtcpPacketParser::Parse(const void *data, size_t len) { const uint8_t* packet = static_cast(data); RTCPUtility::RTCPParserV2 parser(packet, len, true); + EXPECT_TRUE(parser.IsValid()); for (RTCPUtility::RTCPPacketTypes type = parser.Begin(); type != RTCPUtility::kRtcpNotValidCode; type = parser.Iterate()) { diff --git a/media/webrtc/trunk/webrtc/test/rtcp_packet_parser.h b/media/webrtc/trunk/webrtc/test/rtcp_packet_parser.h index f7d36ba804..cc890b4f2f 100644 --- a/media/webrtc/trunk/webrtc/test/rtcp_packet_parser.h +++ b/media/webrtc/trunk/webrtc/test/rtcp_packet_parser.h @@ -631,7 +631,7 @@ class RtcpPacketParser { RtcpPacketParser(); ~RtcpPacketParser(); - void Parse(const void *packet, int packet_len); + void Parse(const void *packet, size_t packet_len); SenderReport* sender_report() { return &sender_report_; } ReceiverReport* receiver_report() { return &receiver_report_; } diff --git a/media/webrtc/trunk/webrtc/test/rtp_file_reader.cc b/media/webrtc/trunk/webrtc/test/rtp_file_reader.cc index fd3116ebb3..26151bba1f 100644 --- a/media/webrtc/trunk/webrtc/test/rtp_file_reader.cc +++ b/media/webrtc/trunk/webrtc/test/rtp_file_reader.cc @@ -17,8 +17,9 @@ #include #include "webrtc/base/checks.h" +#include "webrtc/base/format_macros.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" namespace webrtc { namespace test { @@ -42,11 +43,78 @@ static uint16_t kPacketHeaderSize = 8; } \ } while (0) +bool ReadUint32(uint32_t* out, FILE* file) { + *out = 0; + for (size_t i = 0; i < 4; ++i) { + *out <<= 8; + uint8_t tmp; + if (fread(&tmp, 1, sizeof(uint8_t), file) != sizeof(uint8_t)) + return false; + *out |= tmp; + } + return true; +} + +bool ReadUint16(uint16_t* out, FILE* file) { + *out = 0; + for (size_t i = 0; i < 2; ++i) { + *out <<= 8; + uint8_t tmp; + if (fread(&tmp, 1, sizeof(uint8_t), file) != sizeof(uint8_t)) + return false; + *out |= tmp; + } + return true; +} + class RtpFileReaderImpl : public RtpFileReader { public: virtual bool Init(const std::string& filename) = 0; }; +class InterleavedRtpFileReader : public RtpFileReaderImpl { + public: + virtual ~InterleavedRtpFileReader() { + if (file_ != NULL) { + fclose(file_); + file_ = NULL; + } + } + + virtual bool Init(const std::string& filename) { + file_ = fopen(filename.c_str(), "rb"); + if (file_ == NULL) { + printf("ERROR: Can't open file: %s\n", filename.c_str()); + return false; + } + return true; + } + virtual bool NextPacket(RtpPacket* packet) { + assert(file_ != NULL); + packet->length = RtpPacket::kMaxPacketBufferSize; + uint32_t len = 0; + TRY(ReadUint32(&len, file_)); + if (packet->length < len) { + FATAL() << "Packet is too large to fit: " << len << " bytes vs " + << packet->length + << " bytes allocated. Consider increasing the buffer " + "size"; + } + if (fread(packet->data, 1, len, file_) != len) + return false; + + packet->length = len; + packet->original_length = len; + packet->time_ms = time_ms_; + time_ms_ += 5; + return true; + } + + private: + FILE* file_ = NULL; + int64_t time_ms_ = 0; +}; + // Read RTP packets from file in rtpdump format, as documented at: // http://www.cs.columbia.edu/irt/software/rtptools/ class RtpDumpReader : public RtpFileReaderImpl { @@ -91,25 +159,25 @@ class RtpDumpReader : public RtpFileReaderImpl { uint32_t source; uint16_t port; uint16_t padding; - TRY(Read(&start_sec)); - TRY(Read(&start_usec)); - TRY(Read(&source)); - TRY(Read(&port)); - TRY(Read(&padding)); + TRY(ReadUint32(&start_sec, file_)); + TRY(ReadUint32(&start_usec, file_)); + TRY(ReadUint32(&source, file_)); + TRY(ReadUint16(&port, file_)); + TRY(ReadUint16(&padding, file_)); return true; } - virtual bool NextPacket(Packet* packet) OVERRIDE { + bool NextPacket(RtpPacket* packet) override { uint8_t* rtp_data = packet->data; - packet->length = Packet::kMaxPacketBufferSize; + packet->length = RtpPacket::kMaxPacketBufferSize; uint16_t len; uint16_t plen; uint32_t offset; - TRY(Read(&len)); - TRY(Read(&plen)); - TRY(Read(&offset)); + TRY(ReadUint16(&len, file_)); + TRY(ReadUint16(&plen, file_)); + TRY(ReadUint32(&offset, file_)); // Use 'len' here because a 'plen' of 0 specifies rtcp. len -= kPacketHeaderSize; @@ -130,30 +198,6 @@ class RtpDumpReader : public RtpFileReaderImpl { } private: - bool Read(uint32_t* out) { - *out = 0; - for (size_t i = 0; i < 4; ++i) { - *out <<= 8; - uint8_t tmp; - if (fread(&tmp, 1, sizeof(uint8_t), file_) != sizeof(uint8_t)) - return false; - *out |= tmp; - } - return true; - } - - bool Read(uint16_t* out) { - *out = 0; - for (size_t i = 0; i < 2; ++i) { - *out <<= 8; - uint8_t tmp; - if (fread(&tmp, 1, sizeof(uint8_t), file_) != sizeof(uint8_t)) - return false; - *out |= tmp; - } - return true; - } - FILE* file_; DISALLOW_COPY_AND_ASSIGN(RtpDumpReader); @@ -221,7 +265,7 @@ class PcapReader : public RtpFileReaderImpl { } } - bool Init(const std::string& filename) OVERRIDE { + bool Init(const std::string& filename) override { return Initialize(filename) == kResultSuccess; } @@ -259,15 +303,15 @@ class PcapReader : public RtpFileReaderImpl { } printf("Total packets in file: %d\n", total_packet_count); - printf("Total RTP/RTCP packets: %d\n", static_cast(packets_.size())); + printf("Total RTP/RTCP packets: %" PRIuS "\n", packets_.size()); for (SsrcMapIterator mit = packets_by_ssrc_.begin(); mit != packets_by_ssrc_.end(); ++mit) { uint32_t ssrc = mit->first; const std::vector& packet_numbers = mit->second; uint8_t pt = packets_[packet_numbers[0]].rtp_header.payloadType; - printf("SSRC: %08x, %d packets, pt=%d\n", ssrc, - static_cast(packet_numbers.size()), pt); + printf("SSRC: %08x, %" PRIuS " packets, pt=%d\n", ssrc, + packet_numbers.size(), pt); } // TODO(solenberg): Better validation of identified SSRC streams. @@ -290,8 +334,8 @@ class PcapReader : public RtpFileReaderImpl { return kResultSuccess; } - virtual bool NextPacket(Packet* packet) OVERRIDE { - uint32_t length = Packet::kMaxPacketBufferSize; + bool NextPacket(RtpPacket* packet) override { + uint32_t length = RtpPacket::kMaxPacketBufferSize; if (NextPcap(packet->data, &length, &packet->time_ms) != kResultSuccess) return false; packet->length = static_cast(length); @@ -597,6 +641,9 @@ RtpFileReader* RtpFileReader::Create(FileFormat format, case kRtpDump: reader = new RtpDumpReader(); break; + case kLengthPacketInterleaved: + reader = new InterleavedRtpFileReader(); + break; } if (!reader->Init(filename)) { delete reader; diff --git a/media/webrtc/trunk/webrtc/test/rtp_file_reader.h b/media/webrtc/trunk/webrtc/test/rtp_file_reader.h index 095ce76726..c302d4fbde 100644 --- a/media/webrtc/trunk/webrtc/test/rtp_file_reader.h +++ b/media/webrtc/trunk/webrtc/test/rtp_file_reader.h @@ -16,31 +16,29 @@ namespace webrtc { namespace test { + +struct RtpPacket { + // Accommodate for 50 ms packets of 32 kHz PCM16 samples (3200 bytes) plus + // some overhead. + static const size_t kMaxPacketBufferSize = 3500; + uint8_t data[kMaxPacketBufferSize]; + size_t length; + // The length the packet had on wire. Will be different from |length| when + // reading a header-only RTP dump. + size_t original_length; + + uint32_t time_ms; +}; + class RtpFileReader { public: - enum FileFormat { - kPcap, - kRtpDump, - }; - - struct Packet { - // Accommodate for 50 ms packets of 32 kHz PCM16 samples (3200 bytes) plus - // some overhead. - static const size_t kMaxPacketBufferSize = 3500; - uint8_t data[kMaxPacketBufferSize]; - size_t length; - // The length the packet had on wire. Will be different from |length| when - // reading a header-only RTP dump. - size_t original_length; - - uint32_t time_ms; - }; + enum FileFormat { kPcap, kRtpDump, kLengthPacketInterleaved }; virtual ~RtpFileReader() {} static RtpFileReader* Create(FileFormat format, const std::string& filename); - virtual bool NextPacket(Packet* packet) = 0; + virtual bool NextPacket(RtpPacket* packet) = 0; }; } // namespace test } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/test/rtp_file_reader_unittest.cc b/media/webrtc/trunk/webrtc/test/rtp_file_reader_unittest.cc index 54fb874b63..929813f999 100644 --- a/media/webrtc/trunk/webrtc/test/rtp_file_reader_unittest.cc +++ b/media/webrtc/trunk/webrtc/test/rtp_file_reader_unittest.cc @@ -11,8 +11,8 @@ #include #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/test/rtp_file_reader.h" #include "webrtc/test/testsupport/fileutils.h" @@ -30,7 +30,7 @@ class TestRtpFileReader : public ::testing::Test { } int CountRtpPackets() { - test::RtpFileReader::Packet packet; + test::RtpPacket packet; int c = 0; while (rtp_packet_source_->NextPacket(&packet)) { if (headers_only_file_) @@ -43,7 +43,7 @@ class TestRtpFileReader : public ::testing::Test { } private: - scoped_ptr rtp_packet_source_; + rtc::scoped_ptr rtp_packet_source_; bool headers_only_file_; }; @@ -71,7 +71,7 @@ class TestPcapFileReader : public ::testing::Test { int CountRtpPackets() { int c = 0; - test::RtpFileReader::Packet packet; + test::RtpPacket packet; while (rtp_packet_source_->NextPacket(&packet)) { EXPECT_EQ(packet.length, packet.original_length); c++; @@ -81,7 +81,7 @@ class TestPcapFileReader : public ::testing::Test { PacketsPerSsrc CountRtpPacketsPerSsrc() { PacketsPerSsrc pps; - test::RtpFileReader::Packet packet; + test::RtpPacket packet; while (rtp_packet_source_->NextPacket(&packet)) { RtpUtility::RtpHeaderParser rtp_header_parser(packet.data, packet.length); webrtc::RTPHeader header; @@ -93,7 +93,7 @@ class TestPcapFileReader : public ::testing::Test { } private: - scoped_ptr rtp_packet_source_; + rtc::scoped_ptr rtp_packet_source_; }; TEST_F(TestPcapFileReader, TestEthernetIIFrame) { diff --git a/media/webrtc/trunk/webrtc/test/rtp_file_writer.cc b/media/webrtc/trunk/webrtc/test/rtp_file_writer.cc new file mode 100644 index 0000000000..4acaa27815 --- /dev/null +++ b/media/webrtc/trunk/webrtc/test/rtp_file_writer.cc @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/test/rtp_file_writer.h" + +#include + +#include + +#include "webrtc/base/checks.h" +#include "webrtc/base/constructormagic.h" + +namespace webrtc { +namespace test { + +static const uint16_t kPacketHeaderSize = 8; +static const char kFirstLine[] = "#!rtpplay1.0 0.0.0.0/0\n"; + +// Write RTP packets to file in rtpdump format, as documented at: +// http://www.cs.columbia.edu/irt/software/rtptools/ +class RtpDumpWriter : public RtpFileWriter { + public: + explicit RtpDumpWriter(FILE* file) : file_(file) { + CHECK(file_ != NULL); + Init(); + } + virtual ~RtpDumpWriter() { + if (file_ != NULL) { + fclose(file_); + file_ = NULL; + } + } + + bool WritePacket(const RtpPacket* packet) override { + uint16_t len = static_cast(packet->length + kPacketHeaderSize); + CHECK_GE(packet->original_length, packet->length); + uint16_t plen = static_cast(packet->original_length); + uint32_t offset = packet->time_ms; + CHECK(WriteUint16(len)); + CHECK(WriteUint16(plen)); + CHECK(WriteUint32(offset)); + return fwrite(packet->data, sizeof(uint8_t), packet->length, file_) == + packet->length; + } + + private: + bool Init() { + fprintf(file_, "%s", kFirstLine); + + CHECK(WriteUint32(0)); + CHECK(WriteUint32(0)); + CHECK(WriteUint32(0)); + CHECK(WriteUint16(0)); + CHECK(WriteUint16(0)); + + return true; + } + + bool WriteUint32(uint32_t in) { + // Loop through shifts = {24, 16, 8, 0}. + for (int shifts = 24; shifts >= 0; shifts -= 8) { + uint8_t tmp = static_cast((in >> shifts) & 0xFF); + if (fwrite(&tmp, sizeof(uint8_t), 1, file_) != 1) + return false; + } + return true; + } + + bool WriteUint16(uint16_t in) { + // Write 8 MSBs. + uint8_t tmp = static_cast((in >> 8) & 0xFF); + if (fwrite(&tmp, sizeof(uint8_t), 1, file_) != 1) + return false; + // Write 8 LSBs. + tmp = static_cast(in & 0xFF); + if (fwrite(&tmp, sizeof(uint8_t), 1, file_) != 1) + return false; + return true; + } + + FILE* file_; + + DISALLOW_COPY_AND_ASSIGN(RtpDumpWriter); +}; + +RtpFileWriter* RtpFileWriter::Create(FileFormat format, + const std::string& filename) { + FILE* file = fopen(filename.c_str(), "wb"); + if (file == NULL) { + printf("ERROR: Can't open file: %s\n", filename.c_str()); + return NULL; + } + switch (format) { + case kRtpDump: + return new RtpDumpWriter(file); + } + fclose(file); + return NULL; +} + +} // namespace test +} // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/test/rtp_file_writer.h b/media/webrtc/trunk/webrtc/test/rtp_file_writer.h new file mode 100644 index 0000000000..453b27762e --- /dev/null +++ b/media/webrtc/trunk/webrtc/test/rtp_file_writer.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef WEBRTC_TEST_RTP_FILE_WRITER_H_ +#define WEBRTC_TEST_RTP_FILE_WRITER_H_ + +#include + +#include "webrtc/common_types.h" +#include "webrtc/test/rtp_file_reader.h" + +namespace webrtc { +namespace test { +class RtpFileWriter { + public: + enum FileFormat { + kRtpDump, + }; + + virtual ~RtpFileWriter() {} + static RtpFileWriter* Create(FileFormat format, const std::string& filename); + + virtual bool WritePacket(const RtpPacket* packet) = 0; +}; +} // namespace test +} // namespace webrtc +#endif // WEBRTC_TEST_RTP_FILE_WRITER_H_ diff --git a/media/webrtc/trunk/webrtc/test/rtp_file_writer_unittest.cc b/media/webrtc/trunk/webrtc/test/rtp_file_writer_unittest.cc new file mode 100644 index 0000000000..2c7c88cc3f --- /dev/null +++ b/media/webrtc/trunk/webrtc/test/rtp_file_writer_unittest.cc @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include + +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/scoped_ptr.h" +#include "webrtc/test/rtp_file_reader.h" +#include "webrtc/test/rtp_file_writer.h" +#include "webrtc/test/testsupport/fileutils.h" + +namespace webrtc { + +class RtpFileWriterTest : public ::testing::Test { + public: + void Init(const std::string& filename) { + filename_ = test::OutputPath() + filename; + rtp_writer_.reset( + test::RtpFileWriter::Create(test::RtpFileWriter::kRtpDump, filename_)); + } + + void WriteRtpPackets(int num_packets) { + ASSERT_TRUE(rtp_writer_.get() != NULL); + test::RtpPacket packet; + for (int i = 1; i <= num_packets; ++i) { + packet.length = i; + packet.original_length = i; + packet.time_ms = i; + memset(packet.data, i, packet.length); + EXPECT_TRUE(rtp_writer_->WritePacket(&packet)); + } + } + + void CloseOutputFile() { rtp_writer_.reset(); } + + void VerifyFileContents(int expected_packets) { + ASSERT_TRUE(rtp_writer_.get() == NULL) + << "Must call CloseOutputFile before VerifyFileContents"; + rtc::scoped_ptr rtp_reader( + test::RtpFileReader::Create(test::RtpFileReader::kRtpDump, filename_)); + ASSERT_TRUE(rtp_reader.get() != NULL); + test::RtpPacket packet; + int i = 0; + while (rtp_reader->NextPacket(&packet)) { + ++i; + EXPECT_EQ(static_cast(i), packet.length); + EXPECT_EQ(static_cast(i), packet.original_length); + EXPECT_EQ(static_cast(i), packet.time_ms); + for (int j = 0; j < i; ++j) { + EXPECT_EQ(i, packet.data[j]); + } + } + EXPECT_EQ(expected_packets, i); + } + + private: + rtc::scoped_ptr rtp_writer_; + std::string filename_; +}; + +TEST_F(RtpFileWriterTest, WriteToRtpDump) { + Init("test_rtp_file_writer.rtp"); + WriteRtpPackets(10); + CloseOutputFile(); + VerifyFileContents(10); +} + +} // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/test/rtp_rtcp_observer.h b/media/webrtc/trunk/webrtc/test/rtp_rtcp_observer.h index 11531b3b2d..dd731f04db 100644 --- a/media/webrtc/trunk/webrtc/test/rtp_rtcp_observer.h +++ b/media/webrtc/trunk/webrtc/test/rtp_rtcp_observer.h @@ -47,7 +47,6 @@ class RtpRtcpObserver { virtual EventTypeWrapper Wait() { EventTypeWrapper result = observation_complete_->Wait(timeout_ms_); - observation_complete_->Reset(); return result; } @@ -128,7 +127,7 @@ class RtpRtcpObserver { on_rtcp_(on_rtcp) {} private: - virtual bool SendRtp(const uint8_t* packet, size_t length) OVERRIDE { + bool SendRtp(const uint8_t* packet, size_t length) override { EXPECT_FALSE(RtpHeaderParser::IsRtcp(packet, length)); Action action; { @@ -145,7 +144,7 @@ class RtpRtcpObserver { return true; // Will never happen, makes compiler happy. } - virtual bool SendRtcp(const uint8_t* packet, size_t length) OVERRIDE { + bool SendRtcp(const uint8_t* packet, size_t length) override { EXPECT_TRUE(RtpHeaderParser::IsRtcp(packet, length)); Action action; { @@ -170,9 +169,9 @@ class RtpRtcpObserver { }; protected: - const scoped_ptr crit_; - const scoped_ptr observation_complete_; - const scoped_ptr parser_; + const rtc::scoped_ptr crit_; + const rtc::scoped_ptr observation_complete_; + const rtc::scoped_ptr parser_; private: PacketTransport send_transport_, receive_transport_; diff --git a/media/webrtc/trunk/webrtc/test/test.gyp b/media/webrtc/trunk/webrtc/test/test.gyp index 7aba2f5739..ea831a1471 100644 --- a/media/webrtc/trunk/webrtc/test/test.gyp +++ b/media/webrtc/trunk/webrtc/test/test.gyp @@ -17,7 +17,8 @@ 'type': 'static_library', 'dependencies': [ '<(DEPTH)/testing/gtest.gyp:gtest', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', + '<(webrtc_root)/common.gyp:webrtc_common', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', ], 'sources': [ 'channel_transport/channel_transport.cc', @@ -60,8 +61,12 @@ 'rtcp_packet_parser.h', 'rtp_file_reader.cc', 'rtp_file_reader.h', + 'rtp_file_writer.cc', + 'rtp_file_writer.h', ], 'dependencies': [ + '<(DEPTH)/webrtc/common.gyp:webrtc_common', + '<(DEPTH)/testing/gtest.gyp:gtest', '<(webrtc_root)/modules/modules.gyp:rtp_rtcp', ], }, @@ -73,7 +78,20 @@ 'field_trial.h', ], 'dependencies': [ - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', + '<(webrtc_root)/common.gyp:webrtc_common', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', + ], + }, + { + 'target_name': 'histogram', + 'type': 'static_library', + 'sources': [ + 'histogram.cc', + 'histogram.h', + ], + 'dependencies': [ + '<(webrtc_root)/common.gyp:webrtc_common', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', ], }, { @@ -84,9 +102,9 @@ ], 'dependencies': [ 'field_trial', + 'histogram', '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:metrics_default', ], }, { @@ -95,7 +113,8 @@ 'dependencies': [ '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/testing/gmock.gyp:gmock', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', + '<(webrtc_root)/common.gyp:gtest_prod', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', ], 'sources': [ 'testsupport/fileutils.cc', @@ -104,7 +123,6 @@ 'testsupport/frame_reader.h', 'testsupport/frame_writer.cc', 'testsupport/frame_writer.h', - 'testsupport/gtest_prod_util.h', 'testsupport/gtest_disable.h', 'testsupport/mock/mock_frame_reader.h', 'testsupport/mock/mock_frame_writer.h', @@ -123,11 +141,11 @@ 'type': 'static_library', 'dependencies': [ 'field_trial', + 'histogram', 'test_support', '<(DEPTH)/testing/gmock.gyp:gmock', '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:metrics_default', ], 'sources': [ 'run_all_unittests.cc', diff --git a/media/webrtc/trunk/webrtc/test/test_suite.h b/media/webrtc/trunk/webrtc/test/test_suite.h index e28fb23353..c166f283a5 100644 --- a/media/webrtc/trunk/webrtc/test/test_suite.h +++ b/media/webrtc/trunk/webrtc/test/test_suite.h @@ -18,7 +18,7 @@ // any gtest based tests that are linked into your executable. #include "webrtc/base/constructormagic.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/base/scoped_ptr.h" namespace webrtc { namespace test { @@ -41,7 +41,7 @@ class TestSuite { DISALLOW_COPY_AND_ASSIGN(TestSuite); private: - scoped_ptr trace_to_stderr_; + rtc::scoped_ptr trace_to_stderr_; }; } // namespace test diff --git a/media/webrtc/trunk/webrtc/test/test_support_unittests.isolate b/media/webrtc/trunk/webrtc/test/test_support_unittests.isolate index c1419e7e60..3fd89d602e 100644 --- a/media/webrtc/trunk/webrtc/test/test_support_unittests.isolate +++ b/media/webrtc/trunk/webrtc/test/test_support_unittests.isolate @@ -7,14 +7,6 @@ # be found in the AUTHORS file in the root of the source tree. { 'conditions': [ - ['OS=="android"', { - 'variables': { - 'files': [ - '<(DEPTH)/data/', - '<(DEPTH)/resources/', - ], - }, - }], ['OS=="linux" or OS=="mac" or OS=="win"', { 'variables': { 'command': [ diff --git a/media/webrtc/trunk/webrtc/test/testsupport/fileutils.cc b/media/webrtc/trunk/webrtc/test/testsupport/fileutils.cc index 36ca391c41..8301e77165 100644 --- a/media/webrtc/trunk/webrtc/test/testsupport/fileutils.cc +++ b/media/webrtc/trunk/webrtc/test/testsupport/fileutils.cc @@ -23,7 +23,7 @@ #else #include -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/base/scoped_ptr.h" #define GET_CURRENT_DIR getcwd #endif @@ -168,7 +168,7 @@ std::string TempFilename(const std::string &dir, const std::string &prefix) { return ""; #else int len = dir.size() + prefix.size() + 2 + 6; - scoped_ptr tempname(new char[len]); + rtc::scoped_ptr tempname(new char[len]); snprintf(tempname.get(), len, "%s/%sXXXXXX", dir.c_str(), prefix.c_str()); diff --git a/media/webrtc/trunk/webrtc/test/testsupport/frame_reader.h b/media/webrtc/trunk/webrtc/test/testsupport/frame_reader.h index 4ee90f90b4..9b50ec7bf4 100644 --- a/media/webrtc/trunk/webrtc/test/testsupport/frame_reader.h +++ b/media/webrtc/trunk/webrtc/test/testsupport/frame_reader.h @@ -54,12 +54,12 @@ class FrameReaderImpl : public FrameReader { // frame_length_in_bytes The size of each frame. // For YUV this is 3 * width * height / 2 FrameReaderImpl(std::string input_filename, size_t frame_length_in_bytes); - virtual ~FrameReaderImpl(); - virtual bool Init() OVERRIDE; - virtual bool ReadFrame(uint8_t* source_buffer) OVERRIDE; - virtual void Close() OVERRIDE; - virtual size_t FrameLength() OVERRIDE; - virtual int NumberOfFrames() OVERRIDE; + ~FrameReaderImpl() override; + bool Init() override; + bool ReadFrame(uint8_t* source_buffer) override; + void Close() override; + size_t FrameLength() override; + int NumberOfFrames() override; private: std::string input_filename_; diff --git a/media/webrtc/trunk/webrtc/test/testsupport/frame_writer.h b/media/webrtc/trunk/webrtc/test/testsupport/frame_writer.h index daa3894a50..8a6b1c2152 100644 --- a/media/webrtc/trunk/webrtc/test/testsupport/frame_writer.h +++ b/media/webrtc/trunk/webrtc/test/testsupport/frame_writer.h @@ -52,11 +52,11 @@ class FrameWriterImpl : public FrameWriter { // frame_length_in_bytes The size of each frame. // For YUV: 3*width*height/2 FrameWriterImpl(std::string output_filename, size_t frame_length_in_bytes); - virtual ~FrameWriterImpl(); - virtual bool Init() OVERRIDE; - virtual bool WriteFrame(uint8_t* frame_buffer) OVERRIDE; - virtual void Close() OVERRIDE; - virtual size_t FrameLength() OVERRIDE; + ~FrameWriterImpl() override; + bool Init() override; + bool WriteFrame(uint8_t* frame_buffer) override; + void Close() override; + size_t FrameLength() override; private: std::string output_filename_; diff --git a/media/webrtc/trunk/webrtc/test/testsupport/metrics/video_metrics.cc b/media/webrtc/trunk/webrtc/test/testsupport/metrics/video_metrics.cc index 1e19806b4d..0202a71ebe 100644 --- a/media/webrtc/trunk/webrtc/test/testsupport/metrics/video_metrics.cc +++ b/media/webrtc/trunk/webrtc/test/testsupport/metrics/video_metrics.cc @@ -111,8 +111,8 @@ int CalculateMetrics(VideoMetricsType video_metrics_type, const size_t frame_length = 3 * width * height >> 1; I420VideoFrame ref_frame; I420VideoFrame test_frame; - scoped_ptr ref_buffer(new uint8_t[frame_length]); - scoped_ptr test_buffer(new uint8_t[frame_length]); + rtc::scoped_ptr ref_buffer(new uint8_t[frame_length]); + rtc::scoped_ptr test_buffer(new uint8_t[frame_length]); // Set decoded image parameters. int half_width = (width + 1) / 2; @@ -124,9 +124,9 @@ int CalculateMetrics(VideoMetricsType video_metrics_type, while (ref_bytes == frame_length && test_bytes == frame_length) { // Converting from buffer to plane representation. ConvertToI420(kI420, ref_buffer.get(), 0, 0, width, height, 0, - kRotateNone, &ref_frame); + kVideoRotation_0, &ref_frame); ConvertToI420(kI420, test_buffer.get(), 0, 0, width, height, 0, - kRotateNone, &test_frame); + kVideoRotation_0, &test_frame); switch (video_metrics_type) { case kPSNR: CalculateFrame(kPSNR, &ref_frame, &test_frame, frame_number, diff --git a/media/webrtc/trunk/webrtc/test/testsupport/packet_reader.cc b/media/webrtc/trunk/webrtc/test/testsupport/packet_reader.cc index 54552bd0f5..e27ec22f16 100644 --- a/media/webrtc/trunk/webrtc/test/testsupport/packet_reader.cc +++ b/media/webrtc/trunk/webrtc/test/testsupport/packet_reader.cc @@ -12,6 +12,7 @@ #include #include +#include namespace webrtc { namespace test { @@ -22,10 +23,9 @@ PacketReader::PacketReader() PacketReader::~PacketReader() {} void PacketReader::InitializeReading(uint8_t* data, - int data_length_in_bytes, - int packet_size_in_bytes) { + size_t data_length_in_bytes, + size_t packet_size_in_bytes) { assert(data); - assert(data_length_in_bytes >= 0); assert(packet_size_in_bytes > 0); data_ = data; data_length_ = data_length_in_bytes; @@ -40,16 +40,9 @@ int PacketReader::NextPacket(uint8_t** packet_pointer) { return -1; } *packet_pointer = data_ + currentIndex_; - // Check if we're about to read the last packet: - if (data_length_ - currentIndex_ <= packet_size_) { - int size = data_length_ - currentIndex_; - currentIndex_ = data_length_; - assert(size >= 0); - return size; - } - currentIndex_ += packet_size_; - assert(packet_size_ >= 0); - return packet_size_; + size_t old_index = currentIndex_; + currentIndex_ = std::min(currentIndex_ + packet_size_, data_length_); + return static_cast(currentIndex_ - old_index); } } // namespace test diff --git a/media/webrtc/trunk/webrtc/test/testsupport/packet_reader.h b/media/webrtc/trunk/webrtc/test/testsupport/packet_reader.h index e84ecd96b5..b58db4d093 100644 --- a/media/webrtc/trunk/webrtc/test/testsupport/packet_reader.h +++ b/media/webrtc/trunk/webrtc/test/testsupport/packet_reader.h @@ -11,6 +11,7 @@ #ifndef WEBRTC_TEST_TESTSUPPORT_PACKET_READER_H_ #define WEBRTC_TEST_TESTSUPPORT_PACKET_READER_H_ +#include #include "webrtc/typedefs.h" namespace webrtc { @@ -24,12 +25,12 @@ class PacketReader { // Inizializes a new reading operation. Must be done before invoking the // NextPacket method. - // * data_length_in_bytes is the length of the data byte array. Must be >= 0. + // * data_length_in_bytes is the length of the data byte array. // 0 length will result in no packets are read. // * packet_size_in_bytes is the number of bytes to read in each NextPacket // method call. Must be > 0 - virtual void InitializeReading(uint8_t* data, int data_length_in_bytes, - int packet_size_in_bytes); + virtual void InitializeReading(uint8_t* data, size_t data_length_in_bytes, + size_t packet_size_in_bytes); // Moves the supplied pointer to the beginning of the next packet. // Returns: @@ -41,9 +42,9 @@ class PacketReader { private: uint8_t* data_; - int data_length_; - int packet_size_; - int currentIndex_; + size_t data_length_; + size_t packet_size_; + size_t currentIndex_; bool initialized_; }; diff --git a/media/webrtc/trunk/webrtc/test/testsupport/packet_reader_unittest.cc b/media/webrtc/trunk/webrtc/test/testsupport/packet_reader_unittest.cc index 83cde6957d..2679be473f 100644 --- a/media/webrtc/trunk/webrtc/test/testsupport/packet_reader_unittest.cc +++ b/media/webrtc/trunk/webrtc/test/testsupport/packet_reader_unittest.cc @@ -26,11 +26,11 @@ class PacketReaderTest: public PacketRelatedTest { void TearDown() { delete reader_; } - void VerifyPacketData(int expected_length, + void VerifyPacketData(size_t expected_length, int actual_length, uint8_t* original_data_pointer, uint8_t* new_data_pointer) { - EXPECT_EQ(expected_length, actual_length); + EXPECT_EQ(static_cast(expected_length), actual_length); EXPECT_EQ(*original_data_pointer, *new_data_pointer); EXPECT_EQ(0, memcmp(original_data_pointer, new_data_pointer, actual_length)); @@ -82,7 +82,7 @@ TEST_F(PacketReaderTest, NormalOnePacketData) { // Reading another one shall result in 0 bytes: length_to_read = reader_->NextPacket(&data_pointer); EXPECT_EQ(0, length_to_read); - EXPECT_EQ(kPacketSizeInBytes, data_pointer - data); + EXPECT_EQ(kPacketSizeInBytes, static_cast(data_pointer - data)); } // Test with data length that will result in 3 packets @@ -105,7 +105,8 @@ TEST_F(PacketReaderTest, NormalLargeData) { // Reading another one shall result in 0 bytes: length_to_read = reader_->NextPacket(&packet_data_pointer_); EXPECT_EQ(0, length_to_read); - EXPECT_EQ(kPacketDataLength, packet_data_pointer_ - packet_data_); + EXPECT_EQ(kPacketDataLength, + static_cast(packet_data_pointer_ - packet_data_)); } // Test with empty data. diff --git a/media/webrtc/trunk/webrtc/test/testsupport/trace_to_stderr.h b/media/webrtc/trunk/webrtc/test/testsupport/trace_to_stderr.h index 12208349d8..88f1811740 100644 --- a/media/webrtc/trunk/webrtc/test/testsupport/trace_to_stderr.h +++ b/media/webrtc/trunk/webrtc/test/testsupport/trace_to_stderr.h @@ -28,7 +28,7 @@ class TraceToStderr : public TraceCallback { // This is useful for offline test tools, where the file time is much more // informative than the real time. explicit TraceToStderr(bool override_time); - virtual ~TraceToStderr(); + ~TraceToStderr() override; // Every subsequent trace printout will use |time|. Has no effect if // |override_time| in the constructor was set to false. @@ -39,9 +39,7 @@ class TraceToStderr : public TraceCallback { virtual void SetTimeSeconds(float time); // Implements TraceCallback. - virtual void Print(TraceLevel level, - const char* msg_array, - int length) OVERRIDE; + void Print(TraceLevel level, const char* msg_array, int length) override; private: bool override_time_; diff --git a/media/webrtc/trunk/webrtc/test/testsupport/unittest_utils.h b/media/webrtc/trunk/webrtc/test/testsupport/unittest_utils.h index bb244a441a..ba6db9883b 100644 --- a/media/webrtc/trunk/webrtc/test/testsupport/unittest_utils.h +++ b/media/webrtc/trunk/webrtc/test/testsupport/unittest_utils.h @@ -14,8 +14,8 @@ namespace webrtc { namespace test { -const int kPacketSizeInBytes = 1500; -const int kPacketDataLength = kPacketSizeInBytes * 2 + 1; +const size_t kPacketSizeInBytes = 1500; +const size_t kPacketDataLength = kPacketSizeInBytes * 2 + 1; const int kPacketDataNumberOfPackets = 3; // A base test fixture for packet related tests. Contains diff --git a/media/webrtc/trunk/webrtc/test/vcm_capturer.cc b/media/webrtc/trunk/webrtc/test/vcm_capturer.cc index a5820bfe11..f9976d21c0 100644 --- a/media/webrtc/trunk/webrtc/test/vcm_capturer.cc +++ b/media/webrtc/trunk/webrtc/test/vcm_capturer.cc @@ -87,9 +87,9 @@ void VcmCapturer::Destroy() { VcmCapturer::~VcmCapturer() { Destroy(); } void VcmCapturer::OnIncomingCapturedFrame(const int32_t id, - I420VideoFrame& frame) { + const I420VideoFrame& frame) { if (started_) - input_->SwapFrame(&frame); + input_->IncomingCapturedFrame(frame); } void VcmCapturer::OnCaptureDelayChanged(const int32_t id, const int32_t delay) { diff --git a/media/webrtc/trunk/webrtc/test/vcm_capturer.h b/media/webrtc/trunk/webrtc/test/vcm_capturer.h index dde3edc2f7..c73eeb1ce9 100644 --- a/media/webrtc/trunk/webrtc/test/vcm_capturer.h +++ b/media/webrtc/trunk/webrtc/test/vcm_capturer.h @@ -24,13 +24,12 @@ class VcmCapturer : public VideoCapturer, public VideoCaptureDataCallback { size_t height, size_t target_fps); virtual ~VcmCapturer(); - virtual void Start() OVERRIDE; - virtual void Stop() OVERRIDE; + void Start() override; + void Stop() override; - virtual void OnIncomingCapturedFrame( - const int32_t id, I420VideoFrame& frame) OVERRIDE; // NOLINT - virtual void OnCaptureDelayChanged(const int32_t id, const int32_t delay) - OVERRIDE; + void OnIncomingCapturedFrame(const int32_t id, + const I420VideoFrame& frame) override; // NOLINT + void OnCaptureDelayChanged(const int32_t id, const int32_t delay) override; private: explicit VcmCapturer(VideoSendStreamInput* input); diff --git a/media/webrtc/trunk/webrtc/test/video_renderer.cc b/media/webrtc/trunk/webrtc/test/video_renderer.cc index 1a0c6133ce..03c4948910 100644 --- a/media/webrtc/trunk/webrtc/test/video_renderer.cc +++ b/media/webrtc/trunk/webrtc/test/video_renderer.cc @@ -17,8 +17,9 @@ namespace webrtc { namespace test { class NullRenderer : public VideoRenderer { - virtual void RenderFrame(const I420VideoFrame& video_frame, - int time_to_render_ms) OVERRIDE {} + void RenderFrame(const I420VideoFrame& video_frame, + int time_to_render_ms) override {} + bool IsTextureSupported() const override { return false; } }; VideoRenderer* VideoRenderer::Create(const char* window_title, diff --git a/media/webrtc/trunk/webrtc/test/webrtc_test_common.gyp b/media/webrtc/trunk/webrtc/test/webrtc_test_common.gyp index cd076639c4..ea6e4052db 100644 --- a/media/webrtc/trunk/webrtc/test/webrtc_test_common.gyp +++ b/media/webrtc/trunk/webrtc/test/webrtc_test_common.gyp @@ -57,8 +57,9 @@ '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', '<(webrtc_root)/base/base.gyp:rtc_base', + '<(webrtc_root)/common.gyp:webrtc_common', '<(webrtc_root)/modules/modules.gyp:media_file', - '<(webrtc_root)/modules/modules.gyp:video_render_module_impl', + '<(webrtc_root)/modules/modules.gyp:video_render', '<(webrtc_root)/test/test.gyp:frame_generator', '<(webrtc_root)/test/test.gyp:test_support', '<(webrtc_root)/test/test.gyp:rtp_test_utils', @@ -151,12 +152,14 @@ 'webrtc_test_common', '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/testing/gmock.gyp:gmock', - '<(webrtc_root)/modules/modules.gyp:video_capture_module_impl', + '<(webrtc_root)/modules/modules.gyp:video_capture', '<(webrtc_root)/test/test.gyp:test_support_main', ], 'sources': [ 'fake_network_pipe_unittest.cc', + 'frame_generator_unittest.cc', 'rtp_file_reader_unittest.cc', + 'rtp_file_writer_unittest.cc', ], }, ], #targets diff --git a/media/webrtc/trunk/webrtc/test/win/d3d_renderer.h b/media/webrtc/trunk/webrtc/test/win/d3d_renderer.h index 7f375351a2..4fa6c7ef46 100644 --- a/media/webrtc/trunk/webrtc/test/win/d3d_renderer.h +++ b/media/webrtc/trunk/webrtc/test/win/d3d_renderer.h @@ -27,8 +27,9 @@ class D3dRenderer : public VideoRenderer { size_t height); virtual ~D3dRenderer(); - virtual void RenderFrame(const webrtc::I420VideoFrame& frame, int delta) - OVERRIDE; + void RenderFrame(const webrtc::I420VideoFrame& frame, int delta) override; + bool IsTextureSupported() const override { return false; } + private: D3dRenderer(size_t width, size_t height); diff --git a/media/webrtc/trunk/webrtc/tools/agc/activity_metric.cc b/media/webrtc/trunk/webrtc/tools/agc/activity_metric.cc new file mode 100644 index 0000000000..a51216acd9 --- /dev/null +++ b/media/webrtc/trunk/webrtc/tools/agc/activity_metric.cc @@ -0,0 +1,384 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + + +#include +#include +#include + +#include + +#include "gflags/gflags.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/audio_processing/agc/agc.h" +#include "webrtc/modules/audio_processing/agc/agc_audio_proc.h" +#include "webrtc/modules/audio_processing/agc/common.h" +#include "webrtc/modules/audio_processing/agc/histogram.h" +#include "webrtc/modules/audio_processing/agc/pitch_based_vad.h" +#include "webrtc/modules/audio_processing/agc/standalone_vad.h" +#include "webrtc/modules/audio_processing/agc/utility.h" +#include "webrtc/modules/interface/module_common_types.h" + +static const int kAgcAnalWindowSamples = 100; +static const double kDefaultActivityThreshold = 0.3; + +DEFINE_bool(standalone_vad, true, "enable stand-alone VAD"); +DEFINE_string(true_vad, "", "name of a file containing true VAD in 'int'" + " format"); +DEFINE_string(video_vad, "", "name of a file containing video VAD (activity" + " probabilities) in double format. One activity per 10ms is" + " required. If no file is given the video information is not" + " incorporated. Negative activity is interpreted as video is" + " not adapted and the statistics are not computed during" + " the learning phase. Note that the negative video activities" + " are ONLY allowed at the beginning."); +DEFINE_string(result, "", "name of a file to write the results. The results" + " will be appended to the end of the file. This is optional."); +DEFINE_string(audio_content, "", "name of a file where audio content is written" + " to, in double format."); +DEFINE_double(activity_threshold, kDefaultActivityThreshold, + "Activity threshold"); + +namespace webrtc { + +// TODO(turajs) A new CL will be committed soon where ExtractFeatures will +// notify the caller of "silence" input, instead of bailing out. We would not +// need the following function when such a change is made. + +// Add some dither to quiet frames. This avoids the ExtractFeatures skip a +// silence frame. Otherwise true VAD would drift with respect to the audio. +// We only consider mono inputs. +static void DitherSilence(AudioFrame* frame) { + ASSERT_EQ(1, frame->num_channels_); + const double kRmsSilence = 5; + const double sum_squared_silence = kRmsSilence * kRmsSilence * + frame->samples_per_channel_; + double sum_squared = 0; + for (int n = 0; n < frame->samples_per_channel_; n++) + sum_squared += frame->data_[n] * frame->data_[n]; + if (sum_squared <= sum_squared_silence) { + for (int n = 0; n < frame->samples_per_channel_; n++) + frame->data_[n] = (rand() & 0xF) - 8; + } +} + +class AgcStat { + public: + AgcStat() + : video_index_(0), + activity_threshold_(kDefaultActivityThreshold), + audio_content_(Histogram::Create(kAgcAnalWindowSamples)), + audio_processing_(new AgcAudioProc()), + vad_(new PitchBasedVad()), + standalone_vad_(StandaloneVad::Create()), + audio_content_fid_(NULL) { + for (int n = 0; n < kMaxNumFrames; n++) + video_vad_[n] = 0.5; + } + + ~AgcStat() { + if (audio_content_fid_ != NULL) { + fclose(audio_content_fid_); + } + } + + void set_audio_content_file(FILE* audio_content_fid) { + audio_content_fid_ = audio_content_fid; + } + + int AddAudio(const AudioFrame& frame, double p_video, + int* combined_vad) { + if (frame.num_channels_ != 1 || + frame.samples_per_channel_ != + kSampleRateHz / 100 || + frame.sample_rate_hz_ != kSampleRateHz) + return -1; + video_vad_[video_index_++] = p_video; + AudioFeatures features; + audio_processing_->ExtractFeatures( + frame.data_, frame.samples_per_channel_, &features); + if (FLAGS_standalone_vad) { + standalone_vad_->AddAudio(frame.data_, + frame.samples_per_channel_); + } + if (features.num_frames > 0) { + double p[kMaxNumFrames] = {0.5, 0.5, 0.5, 0.5}; + if (FLAGS_standalone_vad) { + standalone_vad_->GetActivity(p, kMaxNumFrames); + } + // TODO(turajs) combining and limiting are used in the source files as + // well they can be moved to utility. + // Combine Video and stand-alone VAD. + for (int n = 0; n < features.num_frames; n++) { + double p_active = p[n] * video_vad_[n]; + double p_passive = (1 - p[n]) * (1 - video_vad_[n]); + p[n] = p_active / (p_active + p_passive); + // Limit probabilities. + p[n] = std::min(std::max(p[n], 0.01), 0.99); + } + if (vad_->VoicingProbability(features, p) < 0) + return -1; + for (int n = 0; n < features.num_frames; n++) { + audio_content_->Update(features.rms[n], p[n]); + double ac = audio_content_->AudioContent(); + if (audio_content_fid_ != NULL) { + fwrite(&ac, sizeof(ac), 1, audio_content_fid_); + } + if (ac > kAgcAnalWindowSamples * activity_threshold_) { + combined_vad[n] = 1; + } else { + combined_vad[n] = 0; + } + } + video_index_ = 0; + } + return features.num_frames; + } + + void Reset() { + audio_content_->Reset(); + } + + void SetActivityThreshold(double activity_threshold) { + activity_threshold_ = activity_threshold; + } + + private: + int video_index_; + double activity_threshold_; + double video_vad_[kMaxNumFrames]; + rtc::scoped_ptr audio_content_; + rtc::scoped_ptr audio_processing_; + rtc::scoped_ptr vad_; + rtc::scoped_ptr standalone_vad_; + + FILE* audio_content_fid_; +}; + + +void void_main(int argc, char* argv[]) { + webrtc::AgcStat agc_stat; + + FILE* pcm_fid = fopen(argv[1], "rb"); + ASSERT_TRUE(pcm_fid != NULL) << "Cannot open PCM file " << argv[1]; + + if (argc < 2) { + fprintf(stderr, "\nNot Enough arguments\n"); + } + + FILE* true_vad_fid = NULL; + ASSERT_GT(FLAGS_true_vad.size(), 0u) << "Specify the file containing true " + "VADs using --true_vad flag."; + true_vad_fid = fopen(FLAGS_true_vad.c_str(), "rb"); + ASSERT_TRUE(true_vad_fid != NULL) << "Cannot open the active list " << + FLAGS_true_vad; + + FILE* results_fid = NULL; + if (FLAGS_result.size() > 0) { + // True if this is the first time writing to this function and we add a + // header to the beginning of the file. + bool write_header; + // Open in the read mode. If it fails, the file doesn't exist and has to + // write a header for it. Otherwise no need to write a header. + results_fid = fopen(FLAGS_result.c_str(), "r"); + if (results_fid == NULL) { + write_header = true; + } else { + fclose(results_fid); + write_header = false; + } + // Open in append mode. + results_fid = fopen(FLAGS_result.c_str(), "a"); + ASSERT_TRUE(results_fid != NULL) << "Cannot open the file, " << + FLAGS_result << ", to write the results."; + // Write the header if required. + if (write_header) { + fprintf(results_fid, "%% Total Active, Misdetection, " + "Total inactive, False Positive, On-sets, Missed segments, " + "Average response\n"); + } + } + + FILE* video_vad_fid = NULL; + if (FLAGS_video_vad.size() > 0) { + video_vad_fid = fopen(FLAGS_video_vad.c_str(), "rb"); + ASSERT_TRUE(video_vad_fid != NULL) << "Cannot open the file, " << + FLAGS_video_vad << " to read video-based VAD decisions.\n"; + } + + // AgsStat will be the owner of this file and will close it at its + // destructor. + FILE* audio_content_fid = NULL; + if (FLAGS_audio_content.size() > 0) { + audio_content_fid = fopen(FLAGS_audio_content.c_str(), "wb"); + ASSERT_TRUE(audio_content_fid != NULL) << "Cannot open file, " << + FLAGS_audio_content << " to write audio-content.\n"; + agc_stat.set_audio_content_file(audio_content_fid); + } + + webrtc::AudioFrame frame; + frame.num_channels_ = 1; + frame.sample_rate_hz_ = 16000; + frame.samples_per_channel_ = frame.sample_rate_hz_ / 100; + const size_t kSamplesToRead = frame.num_channels_ * + frame.samples_per_channel_; + + agc_stat.SetActivityThreshold(FLAGS_activity_threshold); + + int ret_val = 0; + int num_frames = 0; + int agc_vad[kMaxNumFrames]; + uint8_t true_vad[kMaxNumFrames]; + double p_video = 0.5; + int total_active = 0; + int total_passive = 0; + int total_false_positive = 0; + int total_missed_detection = 0; + int onset_adaptation = 0; + int num_onsets = 0; + bool onset = false; + uint8_t previous_true_vad = 0; + int num_not_adapted = 0; + int true_vad_index = 0; + bool in_false_positive_region = false; + int total_false_positive_duration = 0; + bool video_adapted = false; + while (kSamplesToRead == fread(frame.data_, sizeof(int16_t), + kSamplesToRead, pcm_fid)) { + assert(true_vad_index < kMaxNumFrames); + ASSERT_EQ(1u, fread(&true_vad[true_vad_index], sizeof(*true_vad), 1, + true_vad_fid)) + << "Size mismatch between True-VAD and the PCM file.\n"; + if (video_vad_fid != NULL) { + ASSERT_EQ(1u, fread(&p_video, sizeof(p_video), 1, video_vad_fid)) << + "Not enough video-based VAD probabilities."; + } + + // Negative video activity indicates that the video-based VAD is not yet + // adapted. Disregards the learning phase in statistics. + if (p_video < 0) { + if (video_adapted) { + fprintf(stderr, "Negative video probabilities ONLY allowed at the " + "beginning of the sequence, not in the middle.\n"); + exit(1); + } + continue; + } else { + video_adapted = true; + } + + num_frames++; + uint8_t last_true_vad; + if (true_vad_index == 0) { + last_true_vad = previous_true_vad; + } else { + last_true_vad = true_vad[true_vad_index - 1]; + } + if (last_true_vad == 1 && true_vad[true_vad_index] == 0) { + agc_stat.Reset(); + } + true_vad_index++; + + DitherSilence(&frame); + + ret_val = agc_stat.AddAudio(frame, p_video, agc_vad); + ASSERT_GE(ret_val, 0); + + if (ret_val > 0) { + ASSERT_TRUE(ret_val == true_vad_index); + for (int n = 0; n < ret_val; n++) { + if (true_vad[n] == 1) { + total_active++; + if (previous_true_vad == 0) { + num_onsets++; + onset = true; + } + if (agc_vad[n] == 0) { + total_missed_detection++; + if (onset) + onset_adaptation++; + } else { + in_false_positive_region = false; + onset = false; + } + } else if (true_vad[n] == 0) { + // Check if |on_set| flag is still up. If so it means that we totally + // missed an active region + if (onset) + num_not_adapted++; + onset = false; + + total_passive++; + if (agc_vad[n] == 1) { + total_false_positive++; + in_false_positive_region = true; + } + if (in_false_positive_region) { + total_false_positive_duration++; + } + } else { + ASSERT_TRUE(false) << "Invalid value for true-VAD.\n"; + } + previous_true_vad = true_vad[n]; + } + true_vad_index = 0; + } + } + + if (results_fid != NULL) { + fprintf(results_fid, "%4d %4d %4d %4d %4d %4d %4.0f %4.0f\n", + total_active, + total_missed_detection, + total_passive, + total_false_positive, + num_onsets, + num_not_adapted, + static_cast(onset_adaptation) / (num_onsets + 1e-12), + static_cast(total_false_positive_duration) / + (total_passive + 1e-12)); + } + fprintf(stdout, "%4d %4d %4d %4d %4d %4d %4.0f %4.0f\n", + total_active, + total_missed_detection, + total_passive, + total_false_positive, + num_onsets, + num_not_adapted, + static_cast(onset_adaptation) / (num_onsets + 1e-12), + static_cast(total_false_positive_duration) / + (total_passive + 1e-12)); + + fclose(true_vad_fid); + fclose(pcm_fid); + if (video_vad_fid != NULL) { + fclose(video_vad_fid); + } + if (results_fid != NULL) { + fclose(results_fid); + } +} + +} // namespace webrtc + +int main(int argc, char* argv[]) { + char kUsage[] = + "\nCompute the number of misdetected and false-positive frames. Not\n" + " that for each frame of audio (10 ms) there should be one true\n" + " activity. If any video-based activity is given, there should also be\n" + " one probability per frame.\n" + "\nUsage:\n\n" + "activity_metric input_pcm [options]\n" + "where 'input_pcm' is the input audio sampled at 16 kHz in 16 bits " + "format.\n\n"; + google::SetUsageMessage(kUsage); + google::ParseCommandLineFlags(&argc, &argv, true); + webrtc::void_main(argc, argv); + return 0; +} diff --git a/media/webrtc/trunk/webrtc/tools/agc/agc_harness.cc b/media/webrtc/trunk/webrtc/tools/agc/agc_harness.cc new file mode 100644 index 0000000000..ae8d942295 --- /dev/null +++ b/media/webrtc/trunk/webrtc/tools/agc/agc_harness.cc @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// Refer to kUsage below for a description. + +#include "gflags/gflags.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/scoped_ptr.h" +#include "webrtc/system_wrappers/interface/sleep.h" +#include "webrtc/system_wrappers/interface/trace.h" +#include "webrtc/test/channel_transport/include/channel_transport.h" +#include "webrtc/test/testsupport/trace_to_stderr.h" +#include "webrtc/tools/agc/agc_manager.h" +#include "webrtc/voice_engine/include/voe_audio_processing.h" +#include "webrtc/voice_engine/include/voe_base.h" +#include "webrtc/voice_engine/include/voe_codec.h" +#include "webrtc/voice_engine/include/voe_external_media.h" +#include "webrtc/voice_engine/include/voe_file.h" +#include "webrtc/voice_engine/include/voe_hardware.h" +#include "webrtc/voice_engine/include/voe_network.h" +#include "webrtc/voice_engine/include/voe_volume_control.h" + +DEFINE_bool(codecs, false, "print out available codecs"); +DEFINE_int32(pt, 103, "codec payload type (defaults to ISAC/16000/1)"); +DEFINE_bool(internal, true, "use the internal AGC in 'serial' mode, or as the " + "first voice engine's AGC in parallel mode"); +DEFINE_bool(parallel, false, "run internal and public AGCs in parallel, with " + "left- and right-panning respectively. Not compatible with -aec."); +DEFINE_bool(devices, false, "print out capture devices and indexes to be used " + "with the capture flags"); +DEFINE_int32(capture1, 0, "capture device index for the first voice engine"); +DEFINE_int32(capture2, 0, "capture device index for second voice engine"); +DEFINE_int32(render1, 0, "render device index for first voice engine"); +DEFINE_int32(render2, 0, "render device index for second voice engine"); +DEFINE_bool(aec, false, "runs two voice engines in parallel, with the first " + "playing out a file and sending its captured signal to the second voice " + "engine. Also enables echo cancellation."); +DEFINE_bool(ns, true, "enable noise suppression"); +DEFINE_bool(highpass, true, "enable high pass filter"); +DEFINE_string(filename, "", "filename for the -aec mode"); + +namespace webrtc { +namespace { + +const char kUsage[] = + "\nWithout additional flags, sets up a simple VoiceEngine loopback call\n" + "with the default audio devices and runs forever. The internal AGC is\n" + "enabled and the public disabled.\n\n" + + "It can also run the public AGC in parallel with the internal, panned to\n" + "opposite stereo channels on the default render device. The capture\n" + "devices for each can be selected (recommended, because otherwise they\n" + "will fight for the level on the same device).\n\n" + + "Lastly, it can be used for local AEC testing. In this mode, the first\n" + "voice engine plays out a file over the selected render device (normally\n" + "loudspeakers) and records from the selected capture device. The second\n" + "voice engine receives the capture signal and plays it out over the\n" + "selected render device (normally headphones). This allows the user to\n" + "test an echo scenario with the first voice engine, while monitoring the\n" + "result with the second."; + +class AgcVoiceEngine { + public: + enum Pan { + NoPan, + PanLeft, + PanRight + }; + + AgcVoiceEngine(bool internal, int tx_port, int rx_port, int capture_idx, + int render_idx) + : voe_(VoiceEngine::Create()), + base_(VoEBase::GetInterface(voe_)), + hardware_(VoEHardware::GetInterface(voe_)), + codec_(VoECodec::GetInterface(voe_)), + manager_(new AgcManager(voe_)), + channel_(-1), + capture_idx_(capture_idx), + render_idx_(render_idx) { + SetUp(internal, tx_port, rx_port); + } + + ~AgcVoiceEngine() { + TearDown(); + } + + void SetUp(bool internal, int tx_port, int rx_port) { + ASSERT_TRUE(voe_ != NULL); + ASSERT_TRUE(base_ != NULL); + ASSERT_TRUE(hardware_ != NULL); + ASSERT_TRUE(codec_ != NULL); + VoEAudioProcessing* audio = VoEAudioProcessing::GetInterface(voe_); + ASSERT_TRUE(audio != NULL); + VoENetwork* network = VoENetwork::GetInterface(voe_); + ASSERT_TRUE(network != NULL); + + ASSERT_EQ(0, base_->Init()); + channel_ = base_->CreateChannel(); + ASSERT_NE(-1, channel_); + + channel_transport_.reset( + new test::VoiceChannelTransport(network, channel_)); + ASSERT_EQ(0, channel_transport_->SetSendDestination("127.0.0.1", tx_port)); + ASSERT_EQ(0, channel_transport_->SetLocalReceiver(rx_port)); + + ASSERT_EQ(0, hardware_->SetRecordingDevice(capture_idx_)); + ASSERT_EQ(0, hardware_->SetPlayoutDevice(render_idx_)); + + CodecInst codec_params = {0}; + bool codec_found = false; + for (int i = 0; i < codec_->NumOfCodecs(); i++) { + ASSERT_EQ(0, codec_->GetCodec(i, codec_params)); + if (FLAGS_pt == codec_params.pltype) { + codec_found = true; + break; + } + } + ASSERT_TRUE(codec_found); + ASSERT_EQ(0, codec_->SetSendCodec(channel_, codec_params)); + + ASSERT_EQ(0, audio->EnableHighPassFilter(FLAGS_highpass)); + ASSERT_EQ(0, audio->SetNsStatus(FLAGS_ns)); + ASSERT_EQ(0, audio->SetEcStatus(FLAGS_aec)); + + ASSERT_EQ(0, manager_->Enable(internal)); + ASSERT_EQ(0, audio->SetAgcStatus(!internal)); + + audio->Release(); + network->Release(); + } + + void TearDown() { + Stop(); + channel_transport_.reset(NULL); + ASSERT_EQ(0, base_->DeleteChannel(channel_)); + ASSERT_EQ(0, base_->Terminate()); + // Don't test; the manager hasn't released its interfaces. + hardware_->Release(); + base_->Release(); + codec_->Release(); + delete manager_; + ASSERT_TRUE(VoiceEngine::Delete(voe_)); + } + + void PrintDevices() { + int num_devices = 0; + char device_name[128] = {0}; + char guid[128] = {0}; + ASSERT_EQ(0, hardware_->GetNumOfRecordingDevices(num_devices)); + printf("Capture devices:\n"); + for (int i = 0; i < num_devices; i++) { + ASSERT_EQ(0, hardware_->GetRecordingDeviceName(i, device_name, guid)); + printf("%d: %s\n", i, device_name); + } + ASSERT_EQ(0, hardware_->GetNumOfPlayoutDevices(num_devices)); + printf("Render devices:\n"); + for (int i = 0; i < num_devices; i++) { + ASSERT_EQ(0, hardware_->GetPlayoutDeviceName(i, device_name, guid)); + printf("%d: %s\n", i, device_name); + } + } + + void PrintCodecs() { + CodecInst params = {0}; + printf("Codecs:\n"); + for (int i = 0; i < codec_->NumOfCodecs(); i++) { + ASSERT_EQ(0, codec_->GetCodec(i, params)); + printf("%d %s/%d/%d\n", params.pltype, params.plname, params.plfreq, + params.channels); + } + } + + void StartSending() { + ASSERT_EQ(0, base_->StartSend(channel_)); + } + + void StartPlaying(Pan pan, const std::string& filename) { + VoEVolumeControl* volume = VoEVolumeControl::GetInterface(voe_); + VoEFile* file = VoEFile::GetInterface(voe_); + ASSERT_TRUE(volume != NULL); + ASSERT_TRUE(file != NULL); + if (pan == PanLeft) { + volume->SetOutputVolumePan(channel_, 1, 0); + } else if (pan == PanRight) { + volume->SetOutputVolumePan(channel_, 0, 1); + } + if (filename != "") { + printf("playing file\n"); + ASSERT_EQ(0, file->StartPlayingFileLocally(channel_, filename.c_str(), + true, kFileFormatPcm16kHzFile, 1.0, 0, 0)); + } + ASSERT_EQ(0, base_->StartReceive(channel_)); + ASSERT_EQ(0, base_->StartPlayout(channel_)); + volume->Release(); + file->Release(); + } + + void Stop() { + ASSERT_EQ(0, base_->StopSend(channel_)); + ASSERT_EQ(0, base_->StopPlayout(channel_)); + } + + private: + VoiceEngine* voe_; + VoEBase* base_; + VoEHardware* hardware_; + VoECodec* codec_; + AgcManager* manager_; + int channel_; + int capture_idx_; + int render_idx_; + rtc::scoped_ptr channel_transport_; +}; + +void RunHarness() { + rtc::scoped_ptr voe1(new AgcVoiceEngine( + FLAGS_internal, 2000, 2000, FLAGS_capture1, FLAGS_render1)); + rtc::scoped_ptr voe2; + if (FLAGS_parallel) { + voe2.reset(new AgcVoiceEngine(!FLAGS_internal, 3000, 3000, FLAGS_capture2, + FLAGS_render2)); + voe1->StartPlaying(AgcVoiceEngine::PanLeft, ""); + voe1->StartSending(); + voe2->StartPlaying(AgcVoiceEngine::PanRight, ""); + voe2->StartSending(); + } else if (FLAGS_aec) { + voe1.reset(new AgcVoiceEngine(FLAGS_internal, 2000, 4242, FLAGS_capture1, + FLAGS_render1)); + voe2.reset(new AgcVoiceEngine(!FLAGS_internal, 4242, 2000, FLAGS_capture2, + FLAGS_render2)); + voe1->StartPlaying(AgcVoiceEngine::NoPan, FLAGS_filename); + voe1->StartSending(); + voe2->StartPlaying(AgcVoiceEngine::NoPan, ""); + } else { + voe1->StartPlaying(AgcVoiceEngine::NoPan, ""); + voe1->StartSending(); + } + + // Run forever... + SleepMs(0x7fffffff); +} + +void PrintDevices() { + AgcVoiceEngine device_voe(false, 4242, 4242, 0, 0); + device_voe.PrintDevices(); +} + +void PrintCodecs() { + AgcVoiceEngine codec_voe(false, 4242, 4242, 0, 0); + codec_voe.PrintCodecs(); +} + +} // namespace +} // namespace webrtc + +int main(int argc, char** argv) { + google::SetUsageMessage(webrtc::kUsage); + google::ParseCommandLineFlags(&argc, &argv, true); + webrtc::test::TraceToStderr trace_to_stderr; + + if (FLAGS_parallel && FLAGS_aec) { + printf("-parallel and -aec are not compatible\n"); + return 1; + } + if (FLAGS_devices) { + webrtc::PrintDevices(); + } + if (FLAGS_codecs) { + webrtc::PrintCodecs(); + } + if (!FLAGS_devices && !FLAGS_codecs) { + webrtc::RunHarness(); + } + return 0; +} diff --git a/media/webrtc/trunk/webrtc/tools/agc/agc_manager.cc b/media/webrtc/trunk/webrtc/tools/agc/agc_manager.cc new file mode 100644 index 0000000000..83c0d0075b --- /dev/null +++ b/media/webrtc/trunk/webrtc/tools/agc/agc_manager.cc @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/tools/agc/agc_manager.h" + +#include + +#include "webrtc/modules/audio_processing/agc/agc.h" +#include "webrtc/modules/audio_processing/include/audio_processing.h" +#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" +#include "webrtc/system_wrappers/interface/logging.h" +#include "webrtc/voice_engine/include/voe_external_media.h" +#include "webrtc/voice_engine/include/voe_volume_control.h" + +namespace webrtc { + +class AgcManagerVolume : public VolumeCallbacks { + public: + // AgcManagerVolume acquires ownership of |volume|. + explicit AgcManagerVolume(VoEVolumeControl* volume) + : volume_(volume) { + } + + ~AgcManagerVolume() { + if (volume_) { + volume_->Release(); + } + } + + virtual void SetMicVolume(int volume) { + if (volume_->SetMicVolume(volume) != 0) { + LOG_FERR1(LS_WARNING, SetMicVolume, volume); + } + } + + int GetMicVolume() { + unsigned int volume = 0; + if (volume_->GetMicVolume(volume) != 0) { + LOG_FERR0(LS_WARNING, GetMicVolume); + return -1; + } + return volume; + } + + private: + VoEVolumeControl* volume_; +}; + +class MediaCallback : public VoEMediaProcess { + public: + MediaCallback(AgcManagerDirect* direct, AudioProcessing* audioproc, + CriticalSectionWrapper* crit) + : direct_(direct), + audioproc_(audioproc), + crit_(crit), + frame_() { + } + + protected: + virtual void Process(const int channel, const ProcessingTypes type, + int16_t audio[], const int samples_per_channel, + const int sample_rate_hz, const bool is_stereo) { + CriticalSectionScoped cs(crit_); + if (direct_->capture_muted()) { + return; + } + + // Extract the first channel. + const int kMaxSampleRateHz = 48000; + const int kMaxSamplesPerChannel = kMaxSampleRateHz / 100; + assert(samples_per_channel < kMaxSamplesPerChannel && + sample_rate_hz < kMaxSampleRateHz); + int16_t mono[kMaxSamplesPerChannel]; + int16_t* mono_ptr = audio; + if (is_stereo) { + for (int n = 0; n < samples_per_channel; n++) { + mono[n] = audio[n * 2]; + } + mono_ptr = mono; + } + + direct_->Process(mono_ptr, samples_per_channel, sample_rate_hz); + + // TODO(ajm): It's unfortunate we have to memcpy to this frame here, but + // it's needed for use with AudioProcessing. + frame_.num_channels_ = is_stereo ? 2 : 1; + frame_.samples_per_channel_ = samples_per_channel; + frame_.sample_rate_hz_ = sample_rate_hz; + const int length_samples = frame_.num_channels_ * samples_per_channel; + memcpy(frame_.data_, audio, length_samples * sizeof(int16_t)); + + // Apply compression to the audio. + if (audioproc_->ProcessStream(&frame_) != 0) { + LOG_FERR0(LS_ERROR, ProcessStream); + } + + // Copy the compressed audio back to voice engine's array. + memcpy(audio, frame_.data_, length_samples * sizeof(int16_t)); + } + + private: + AgcManagerDirect* direct_; + AudioProcessing* audioproc_; + CriticalSectionWrapper* crit_; + AudioFrame frame_; +}; + +class PreprocCallback : public VoEMediaProcess { + public: + PreprocCallback(AgcManagerDirect* direct, CriticalSectionWrapper* crit) + : direct_(direct), + crit_(crit) { + } + + protected: + virtual void Process(const int channel, const ProcessingTypes type, + int16_t audio[], const int samples_per_channel, + const int sample_rate_hz, const bool is_stereo) { + CriticalSectionScoped cs(crit_); + if (direct_->capture_muted()) { + return; + } + direct_->AnalyzePreProcess(audio, is_stereo ? 2 : 1, samples_per_channel); + } + + private: + AgcManagerDirect* direct_; + CriticalSectionWrapper* crit_; +}; + +AgcManager::AgcManager(VoiceEngine* voe) + : media_(VoEExternalMedia::GetInterface(voe)), + volume_callbacks_(new AgcManagerVolume(VoEVolumeControl::GetInterface( + voe))), + crit_(CriticalSectionWrapper::CreateCriticalSection()), + enabled_(false), + initialized_(false) { + Config config; + config.Set(new ExperimentalAgc(false)); + audioproc_.reset(AudioProcessing::Create(config)); + direct_.reset(new AgcManagerDirect(audioproc_->gain_control(), + volume_callbacks_.get())); + media_callback_.reset(new MediaCallback(direct_.get(), + audioproc_.get(), + crit_.get())); + preproc_callback_.reset(new PreprocCallback(direct_.get(), crit_.get())); +} + +AgcManager::AgcManager(VoEExternalMedia* media, VoEVolumeControl* volume, + Agc* agc, AudioProcessing* audioproc) + : media_(media), + volume_callbacks_(new AgcManagerVolume(volume)), + crit_(CriticalSectionWrapper::CreateCriticalSection()), + audioproc_(audioproc), + direct_(new AgcManagerDirect(agc, + audioproc_->gain_control(), + volume_callbacks_.get())), + media_callback_(new MediaCallback(direct_.get(), + audioproc_.get(), + crit_.get())), + preproc_callback_(new PreprocCallback(direct_.get(), crit_.get())), + enabled_(false), + initialized_(false) { +} + +AgcManager::AgcManager() + : media_(NULL), + enabled_(false), + initialized_(false) { +} + +AgcManager::~AgcManager() { + if (media_) { + if (enabled_) { + DeregisterCallbacks(); + } + media_->Release(); + } +} + +int AgcManager::Enable(bool enable) { + if (enable == enabled_) { + return 0; + } + if (!initialized_) { + CriticalSectionScoped cs(crit_.get()); + if (audioproc_->gain_control()->Enable(true) != 0) { + LOG_FERR1(LS_ERROR, gain_control()->Enable, true); + return -1; + } + if (direct_->Initialize() != 0) { + assert(false); + return -1; + } + initialized_ = true; + } + + if (enable) { + if (media_->RegisterExternalMediaProcessing(0, kRecordingAllChannelsMixed, + *media_callback_) != 0) { + LOG(LS_ERROR) << "Failed to register postproc callback"; + return -1; + } + if (media_->RegisterExternalMediaProcessing(0, kRecordingPreprocessing, + *preproc_callback_) != 0) { + LOG(LS_ERROR) << "Failed to register preproc callback"; + return -1; + } + } else { + if (DeregisterCallbacks() != 0) + return -1; + } + enabled_ = enable; + return 0; +} + +void AgcManager::CaptureDeviceChanged() { + CriticalSectionScoped cs(crit_.get()); + direct_->Initialize(); +} + +void AgcManager::SetCaptureMuted(bool muted) { + CriticalSectionScoped cs(crit_.get()); + direct_->SetCaptureMuted(muted); +} + +int AgcManager::DeregisterCallbacks() { + // DeRegister shares a lock with the Process() callback. This call will block + // until the callback is finished and it's safe to continue teardown. + int err = 0; + if (media_->DeRegisterExternalMediaProcessing(0, + kRecordingAllChannelsMixed) != 0) { + LOG(LS_ERROR) << "Failed to deregister postproc callback"; + err = -1; + } + if (media_->DeRegisterExternalMediaProcessing(0, + kRecordingPreprocessing) != 0) { + LOG(LS_ERROR) << "Failed to deregister preproc callback"; + err = -1; + } + return err; +} + +} // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/tools/agc/agc_manager.h b/media/webrtc/trunk/webrtc/tools/agc/agc_manager.h new file mode 100644 index 0000000000..4f79f102d6 --- /dev/null +++ b/media/webrtc/trunk/webrtc/tools/agc/agc_manager.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_TOOLS_AGC_AGC_MANAGER_H_ +#define WEBRTC_TOOLS_AGC_AGC_MANAGER_H_ + +#include "webrtc/base/scoped_ptr.h" +#include "webrtc/modules/audio_processing/agc/agc_manager_direct.h" + +namespace webrtc { + +class Agc; +class AudioProcessing; +class CriticalSectionWrapper; +class MediaCallback; +class PreprocCallback; +class VoEExternalMedia; +class VoEVolumeControl; +class VoiceEngine; +class VolumeCallbacks; + +// Handles the interaction between VoiceEngine and the internal AGC. It hooks +// into the capture stream through VoiceEngine's external media interface and +// sends the audio to the AGC for analysis. It forwards requests for a capture +// volume change from the AGC to the VoiceEngine volume interface. +class AgcManager { + public: + explicit AgcManager(VoiceEngine* voe); + // Dependency injection for testing. Don't delete |agc| or |audioproc| as the + // memory is owned by the manager. If |media| or |volume| are non-fake + // reference counted classes, don't release them as this is handled by the + // manager. + AgcManager(VoEExternalMedia* media, VoEVolumeControl* volume, Agc* agc, + AudioProcessing* audioproc); + virtual ~AgcManager(); + + // When enabled, registers external media processing callbacks with + // VoiceEngine to hook into the capture stream. Disabling deregisters the + // callbacks. + virtual int Enable(bool enable); + virtual bool enabled() const { return enabled_; } + + // Call when the capture device has changed. This will trigger a retrieval of + // the initial capture volume on the next audio frame. + virtual void CaptureDeviceChanged(); + + // Call when the capture stream has been muted/unmuted. This causes the + // manager to disregard all incoming audio; chances are good it's background + // noise to which we'd like to avoid adapting. + virtual void SetCaptureMuted(bool muted); + virtual bool capture_muted() const { return direct_->capture_muted(); } + + protected: + // Provide a default constructor for testing. + AgcManager(); + + private: + int DeregisterCallbacks(); + int CheckVolumeAndReset(); + + VoEExternalMedia* media_; + rtc::scoped_ptr volume_callbacks_; + rtc::scoped_ptr crit_; + rtc::scoped_ptr audioproc_; + rtc::scoped_ptr direct_; + rtc::scoped_ptr media_callback_; + rtc::scoped_ptr preproc_callback_; + bool enabled_; + bool initialized_; +}; + +} // namespace webrtc + +#endif // WEBRTC_TOOLS_AGC_AGC_MANAGER_H_ diff --git a/media/webrtc/trunk/webrtc/tools/agc/agc_manager_integrationtest.cc b/media/webrtc/trunk/webrtc/tools/agc/agc_manager_integrationtest.cc new file mode 100644 index 0000000000..4179e8c1c2 --- /dev/null +++ b/media/webrtc/trunk/webrtc/tools/agc/agc_manager_integrationtest.cc @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/tools/agc/agc_manager.h" + +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/scoped_ptr.h" +#include "webrtc/modules/audio_processing/agc/mock_agc.h" +#include "webrtc/modules/audio_processing/include/audio_processing.h" +#include "webrtc/system_wrappers/interface/sleep.h" +#include "webrtc/test/channel_transport/include/channel_transport.h" +#include "webrtc/test/testsupport/gtest_disable.h" +#include "webrtc/voice_engine/include/voe_base.h" +#include "webrtc/voice_engine/include/voe_external_media.h" +#include "webrtc/voice_engine/include/voe_network.h" +#include "webrtc/voice_engine/include/voe_volume_control.h" + +using ::testing::_; +using ::testing::AtLeast; +using ::testing::Mock; +using ::testing::Return; + +namespace webrtc { + +class AgcManagerTest : public ::testing::Test { + protected: + AgcManagerTest() + : voe_(VoiceEngine::Create()), + base_(VoEBase::GetInterface(voe_)), + agc_(new MockAgc()), + manager_(new AgcManager(VoEExternalMedia::GetInterface(voe_), + VoEVolumeControl::GetInterface(voe_), + agc_, + AudioProcessing::Create())), + channel_(-1) { + } + + virtual void SetUp() { + ASSERT_TRUE(voe_ != NULL); + ASSERT_TRUE(base_ != NULL); + ASSERT_EQ(0, base_->Init()); + channel_ = base_->CreateChannel(); + ASSERT_NE(-1, channel_); + + VoENetwork* network = VoENetwork::GetInterface(voe_); + ASSERT_TRUE(network != NULL); + channel_transport_.reset( + new test::VoiceChannelTransport(network, channel_)); + ASSERT_EQ(0, channel_transport_->SetSendDestination("127.0.0.1", 1234)); + network->Release(); + } + + virtual void TearDown() { + channel_transport_.reset(NULL); + ASSERT_EQ(0, base_->DeleteChannel(channel_)); + ASSERT_EQ(0, base_->Terminate()); + delete manager_; + // Test that the manager has released all VoE interfaces. The last + // reference is released in VoiceEngine::Delete. + EXPECT_EQ(1, base_->Release()); + ASSERT_TRUE(VoiceEngine::Delete(voe_)); + } + + VoiceEngine* voe_; + VoEBase* base_; + MockAgc* agc_; + rtc::scoped_ptr channel_transport_; + // We use a pointer for the manager, so we can tear it down and test + // base_->Release() in the destructor. + AgcManager* manager_; + int channel_; +}; + +TEST_F(AgcManagerTest, DISABLED_ON_ANDROID(EnableSucceeds)) { + EXPECT_EQ(0, manager_->Enable(true)); + EXPECT_TRUE(manager_->enabled()); + EXPECT_EQ(0, manager_->Enable(false)); + EXPECT_FALSE(manager_->enabled()); +} + +TEST_F(AgcManagerTest, DISABLED_ON_ANDROID(ProcessIsNotCalledByDefault)) { + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)).Times(0); + EXPECT_CALL(*agc_, Process(_, _, _)).Times(0); + EXPECT_CALL(*agc_, GetRmsErrorDb(_)).Times(0); + ASSERT_EQ(0, base_->StartSend(channel_)); + SleepMs(100); + ASSERT_EQ(0, base_->StopSend(channel_)); +} + +TEST_F(AgcManagerTest, DISABLED_ProcessIsCalledOnlyWhenEnabled) { + EXPECT_CALL(*agc_, Reset()); + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .Times(AtLeast(1)) + .WillRepeatedly(Return(0)); + EXPECT_CALL(*agc_, Process(_, _, _)) + .Times(AtLeast(1)) + .WillRepeatedly(Return(0)); + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .Times(AtLeast(1)) + .WillRepeatedly(Return(false)); + EXPECT_EQ(0, manager_->Enable(true)); + ASSERT_EQ(0, base_->StartSend(channel_)); + SleepMs(100); + EXPECT_EQ(0, manager_->Enable(false)); + SleepMs(100); + Mock::VerifyAndClearExpectations(agc_); + + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)).Times(0); + EXPECT_CALL(*agc_, Process(_, _, _)).Times(0); + EXPECT_CALL(*agc_, GetRmsErrorDb(_)).Times(0); + SleepMs(100); + ASSERT_EQ(0, base_->StopSend(channel_)); +} + +} // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/tools/agc/agc_manager_unittest.cc b/media/webrtc/trunk/webrtc/tools/agc/agc_manager_unittest.cc new file mode 100644 index 0000000000..fca8decc85 --- /dev/null +++ b/media/webrtc/trunk/webrtc/tools/agc/agc_manager_unittest.cc @@ -0,0 +1,736 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/tools/agc/agc_manager.h" + +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/common_types.h" +#include "webrtc/modules/audio_processing/agc/mock_agc.h" +#include "webrtc/modules/audio_processing/include/mock_audio_processing.h" +#include "webrtc/system_wrappers/interface/trace.h" +#include "webrtc/voice_engine/include/mock/fake_voe_external_media.h" +#include "webrtc/voice_engine/include/mock/mock_voe_volume_control.h" +#include "webrtc/test/testsupport/trace_to_stderr.h" + +using ::testing::_; +using ::testing::DoAll; +using ::testing::Eq; +using ::testing::Mock; +using ::testing::Return; +using ::testing::SetArgPointee; +using ::testing::SetArgReferee; + +namespace webrtc { +namespace { + +const int kSampleRateHz = 32000; +const int kNumChannels = 1; +const int kSamplesPerChannel = kSampleRateHz / 100; +const float kAboveClippedThreshold = 0.2f; + +} // namespace + +class AgcManagerUnitTest : public ::testing::Test { + protected: + AgcManagerUnitTest() + : media_(), + volume_(), + agc_(new MockAgc), + audioproc_(new MockAudioProcessing), + gctrl_(audioproc_->gain_control()), + manager_(&media_, &volume_, agc_, audioproc_) { + EXPECT_CALL(*gctrl_, Enable(true)); + ExpectInitialize(); + manager_.Enable(true); + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(Return(false)); + // TODO(bjornv): Find a better solution that adds an initial volume here + // instead of applying SetVolumeAndProcess(128u) in each test, but at the + // same time can test a too low initial value. + } + + void SetInitialVolume(unsigned int volume) { + ExpectInitialize(); + manager_.CaptureDeviceChanged(); + ExpectCheckVolumeAndReset(volume); + EXPECT_CALL(*agc_, GetRmsErrorDb(_)).WillOnce(Return(false)); + PostProcCallback(1); + } + + void SetVolumeAndProcess(unsigned int volume) { + // Volume is checked on first process call. + ExpectCheckVolumeAndReset(volume); + PostProcCallback(1); + } + + void ExpectCheckVolumeAndReset(unsigned int volume) { + EXPECT_CALL(volume_, GetMicVolume(_)) + .WillOnce(DoAll(SetArgReferee<0>(volume), Return(0))); + EXPECT_CALL(*agc_, Reset()); + } + + void ExpectVolumeChange(unsigned int current_volume, + unsigned int new_volume) { + EXPECT_CALL(volume_, GetMicVolume(_)) + .WillOnce(DoAll(SetArgReferee<0>(current_volume), Return(0))); + EXPECT_CALL(volume_, SetMicVolume(Eq(new_volume))).WillOnce(Return(0)); + } + + void ExpectInitialize() { + EXPECT_CALL(*gctrl_, set_mode(GainControl::kFixedDigital)); + EXPECT_CALL(*gctrl_, set_target_level_dbfs(2)); + EXPECT_CALL(*gctrl_, set_compression_gain_db(7)); + EXPECT_CALL(*gctrl_, enable_limiter(true)); + } + + void PreProcCallback(int num_calls) { + for (int i = 0; i < num_calls; ++i) { + media_.CallProcess(kRecordingPreprocessing, NULL, kSamplesPerChannel, + kSampleRateHz, kNumChannels); + } + } + + void PostProcCallback(int num_calls) { + for (int i = 0; i < num_calls; ++i) { + EXPECT_CALL(*agc_, Process(_, _, _)).WillOnce(Return(0)); + EXPECT_CALL(*audioproc_, ProcessStream(_)).WillOnce(Return(0)); + media_.CallProcess(kRecordingAllChannelsMixed, NULL, kSamplesPerChannel, + kSampleRateHz, kNumChannels); + } + } + + ~AgcManagerUnitTest() { + EXPECT_CALL(volume_, Release()).WillOnce(Return(0)); + } + + FakeVoEExternalMedia media_; + MockVoEVolumeControl volume_; + MockAgc* agc_; + MockAudioProcessing* audioproc_; + MockGainControl* gctrl_; + AgcManager manager_; + test::TraceToStderr trace_to_stderr; +}; + +TEST_F(AgcManagerUnitTest, MicVolumeResponseToRmsError) { + SetVolumeAndProcess(128u); + // Compressor default; no residual error. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(5), Return(true))); + PostProcCallback(1); + + // Inside the compressor's window; no change of volume. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(10), Return(true))); + PostProcCallback(1); + + // Above the compressor's window; volume should be increased. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))); + ExpectVolumeChange(128u, 130u); + PostProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(20), Return(true))); + ExpectVolumeChange(130u, 168u); + PostProcCallback(1); + + // Inside the compressor's window; no change of volume. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(5), Return(true))); + PostProcCallback(1); + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(0), Return(true))); + PostProcCallback(1); + + // Below the compressor's window; volume should be decreased. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); + ExpectVolumeChange(168u, 167u); + PostProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); + ExpectVolumeChange(167u, 163u); + PostProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-9), Return(true))); + ExpectVolumeChange(163u, 129u); + PostProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, MicVolumeIsLimited) { + SetVolumeAndProcess(128u); + // Maximum upwards change is limited. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); + ExpectVolumeChange(128u, 183u); + PostProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); + ExpectVolumeChange(183u, 243u); + PostProcCallback(1); + + // Won't go higher than the maximum. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); + ExpectVolumeChange(243u, 255u); + PostProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); + ExpectVolumeChange(255u, 254u); + PostProcCallback(1); + + // Maximum downwards change is limited. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); + ExpectVolumeChange(254u, 194u); + PostProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); + ExpectVolumeChange(194u, 137u); + PostProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); + ExpectVolumeChange(137u, 88u); + PostProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); + ExpectVolumeChange(88u, 54u); + PostProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); + ExpectVolumeChange(54u, 33u); + PostProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); + ExpectVolumeChange(33u, 18u); + PostProcCallback(1); + + // Won't go lower than the minimum. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); + ExpectVolumeChange(18u, 12u); + PostProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, CompressorStepsTowardsTarget) { + SetVolumeAndProcess(128u); + // Compressor default; no call to set_compression_gain_db. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(5), Return(true))) + .WillRepeatedly(Return(false)); + EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0); + PostProcCallback(20); + + // Moves slowly upwards. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(9), Return(true))) + .WillRepeatedly(Return(false)); + EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0); + PostProcCallback(19); + EXPECT_CALL(*gctrl_, set_compression_gain_db(8)).WillOnce(Return(0)); + PostProcCallback(1); + + EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0); + PostProcCallback(19); + EXPECT_CALL(*gctrl_, set_compression_gain_db(9)).WillOnce(Return(0)); + PostProcCallback(1); + + EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0); + PostProcCallback(20); + + // Moves slowly downward, then reverses before reaching the original target. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(5), Return(true))) + .WillRepeatedly(Return(false)); + EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0); + PostProcCallback(19); + EXPECT_CALL(*gctrl_, set_compression_gain_db(8)).WillOnce(Return(0)); + PostProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(9), Return(true))) + .WillRepeatedly(Return(false)); + EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0); + PostProcCallback(19); + EXPECT_CALL(*gctrl_, set_compression_gain_db(9)).WillOnce(Return(0)); + PostProcCallback(1); + + EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0); + PostProcCallback(20); +} + +TEST_F(AgcManagerUnitTest, CompressorErrorIsDeemphasized) { + SetVolumeAndProcess(128u); + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(10), Return(true))) + .WillRepeatedly(Return(false)); + PostProcCallback(19); + EXPECT_CALL(*gctrl_, set_compression_gain_db(8)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(9)).WillOnce(Return(0)); + PostProcCallback(1); + EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0); + PostProcCallback(20); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(0), Return(true))) + .WillRepeatedly(Return(false)); + PostProcCallback(19); + EXPECT_CALL(*gctrl_, set_compression_gain_db(8)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(7)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(6)).WillOnce(Return(0)); + PostProcCallback(1); + EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0); + PostProcCallback(20); +} + +TEST_F(AgcManagerUnitTest, CompressorReachesMaximum) { + SetVolumeAndProcess(128u); + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(10), Return(true))) + .WillOnce(DoAll(SetArgPointee<0>(10), Return(true))) + .WillOnce(DoAll(SetArgPointee<0>(10), Return(true))) + .WillOnce(DoAll(SetArgPointee<0>(10), Return(true))) + .WillRepeatedly(Return(false)); + PostProcCallback(19); + EXPECT_CALL(*gctrl_, set_compression_gain_db(8)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(9)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(10)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(11)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(12)).WillOnce(Return(0)); + PostProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, CompressorReachesMinimum) { + SetVolumeAndProcess(128u); + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(0), Return(true))) + .WillOnce(DoAll(SetArgPointee<0>(0), Return(true))) + .WillOnce(DoAll(SetArgPointee<0>(0), Return(true))) + .WillOnce(DoAll(SetArgPointee<0>(0), Return(true))) + .WillRepeatedly(Return(false)); + PostProcCallback(19); + EXPECT_CALL(*gctrl_, set_compression_gain_db(6)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(5)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(4)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(3)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(2)).WillOnce(Return(0)); + PostProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, NoActionWhileMuted) { + SetVolumeAndProcess(128u); + manager_.SetCaptureMuted(true); + media_.CallProcess(kRecordingAllChannelsMixed, NULL, kSamplesPerChannel, + kSampleRateHz, kNumChannels); +} + +TEST_F(AgcManagerUnitTest, UnmutingChecksVolumeWithoutRaising) { + SetVolumeAndProcess(128u); + manager_.SetCaptureMuted(true); + manager_.SetCaptureMuted(false); + ExpectCheckVolumeAndReset(127u); + // SetMicVolume should not be called. + EXPECT_CALL(volume_, SetMicVolume(_)).Times(0); + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(Return(false)); + PostProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, UnmutingRaisesTooLowVolume) { + SetVolumeAndProcess(128u); + manager_.SetCaptureMuted(true); + manager_.SetCaptureMuted(false); + ExpectCheckVolumeAndReset(11u); + EXPECT_CALL(volume_, SetMicVolume(Eq(12u))).WillOnce(Return(0)); + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(Return(false)); + PostProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, ChangingDevicesChecksVolume) { + SetVolumeAndProcess(128u); + ExpectInitialize(); + manager_.CaptureDeviceChanged(); + ExpectCheckVolumeAndReset(128u); + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(Return(false)); + PostProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, LowInitialVolumeIsRaised) { + ExpectCheckVolumeAndReset(11u); + // Should set MicVolume to kMinInitMicLevel = 85. + EXPECT_CALL(volume_, SetMicVolume(Eq(85u))).WillOnce(Return(0)); + PostProcCallback(1); + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(Return(false)); + PostProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, ManualLevelChangeResultsInNoSetMicCall) { + SetVolumeAndProcess(128u); + // Change outside of compressor's range, which would normally trigger a call + // to SetMicVolume. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))); + // GetMicVolume returns a value outside of the quantization slack, indicating + // a manual volume change. + EXPECT_CALL(volume_, GetMicVolume(_)) + .WillOnce(DoAll(SetArgReferee<0>(154u), Return(0))); + // SetMicVolume should not be called. + EXPECT_CALL(volume_, SetMicVolume(_)).Times(0); + EXPECT_CALL(*agc_, Reset()).Times(1); + PostProcCallback(1); + + // Do the same thing, except downwards now. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); + EXPECT_CALL(volume_, GetMicVolume(_)) + .WillOnce(DoAll(SetArgReferee<0>(100u), Return(0))); + EXPECT_CALL(volume_, SetMicVolume(_)).Times(0); + EXPECT_CALL(*agc_, Reset()).Times(1); + PostProcCallback(1); + + // And finally verify the AGC continues working without a manual change. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); + ExpectVolumeChange(100u, 99u); + PostProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, RecoveryAfterManualLevelChangeFromMax) { + SetVolumeAndProcess(128u); + // Force the mic up to max volume. Takes a few steps due to the residual + // gain limitation. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true))); + ExpectVolumeChange(128u, 183u); + PostProcCallback(1); + ExpectVolumeChange(183u, 243u); + PostProcCallback(1); + ExpectVolumeChange(243u, 255u); + PostProcCallback(1); + + // Manual change does not result in SetMicVolume call. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); + EXPECT_CALL(volume_, GetMicVolume(_)) + .WillOnce(DoAll(SetArgReferee<0>(50u), Return(0))); + EXPECT_CALL(volume_, SetMicVolume(_)).Times(0); + EXPECT_CALL(*agc_, Reset()).Times(1); + PostProcCallback(1); + + // Continues working as usual afterwards. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(20), Return(true))); + ExpectVolumeChange(50u, 69u); + PostProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, RecoveryAfterManualLevelChangeBelowMin) { + SetVolumeAndProcess(128u); + // Manual change below min. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); + // Don't set to zero, which will cause AGC to take no action. + EXPECT_CALL(volume_, GetMicVolume(_)) + .WillOnce(DoAll(SetArgReferee<0>(1u), Return(0))); + EXPECT_CALL(volume_, SetMicVolume(_)).Times(0); + EXPECT_CALL(*agc_, Reset()).Times(1); + PostProcCallback(1); + + // Continues working as usual afterwards. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))); + ExpectVolumeChange(1u, 2u); + PostProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); + ExpectVolumeChange(2u, 11u); + PostProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(20), Return(true))); + ExpectVolumeChange(11u, 18u); + PostProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, NoClippingHasNoImpact) { + SetVolumeAndProcess(128u); + EXPECT_CALL(volume_, GetMicVolume(_)).Times(0); + EXPECT_CALL(volume_, SetMicVolume(_)).Times(0); + EXPECT_CALL(*agc_, Reset()).Times(0); + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)).WillRepeatedly(Return(0)); + PreProcCallback(100); +} + +TEST_F(AgcManagerUnitTest, ClippingUnderThresholdHasNoImpact) { + SetVolumeAndProcess(128u); + EXPECT_CALL(volume_, GetMicVolume(_)).Times(0); + EXPECT_CALL(volume_, SetMicVolume(_)).Times(0); + EXPECT_CALL(*agc_, Reset()).Times(0); + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)).WillOnce(Return(0.099)); + PreProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, ClippingLowersVolume) { + SetVolumeAndProcess(128u); + SetInitialVolume(255u); + + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)).WillOnce(Return(0.101)); + EXPECT_CALL(*agc_, Reset()).Times(1); + ExpectVolumeChange(255u, 240u); + PreProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, WaitingPeriodBetweenClippingChecks) { + SetVolumeAndProcess(128u); + SetInitialVolume(255u); + + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .WillOnce(Return(kAboveClippedThreshold)); + EXPECT_CALL(*agc_, Reset()).Times(1); + ExpectVolumeChange(255u, 240u); + PreProcCallback(1); + + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .WillRepeatedly(Return(kAboveClippedThreshold)); + EXPECT_CALL(volume_, GetMicVolume(_)).Times(0); + EXPECT_CALL(volume_, SetMicVolume(_)).Times(0); + EXPECT_CALL(*agc_, Reset()).Times(0); + PreProcCallback(300); + + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .WillOnce(Return(kAboveClippedThreshold)); + EXPECT_CALL(*agc_, Reset()).Times(1); + ExpectVolumeChange(240u, 225u); + PreProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, ClippingLoweringIsLimited) { + SetVolumeAndProcess(128u); + SetInitialVolume(180u); + + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .WillOnce(Return(kAboveClippedThreshold)); + EXPECT_CALL(*agc_, Reset()).Times(1); + ExpectVolumeChange(180u, 170u); + PreProcCallback(1); + + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .WillRepeatedly(Return(kAboveClippedThreshold)); + EXPECT_CALL(volume_, GetMicVolume(_)).Times(0); + EXPECT_CALL(volume_, SetMicVolume(_)).Times(0); + EXPECT_CALL(*agc_, Reset()).Times(0); + PreProcCallback(1000); +} + +TEST_F(AgcManagerUnitTest, ClippingMaxIsRespectedWhenEqualToLevel) { + SetVolumeAndProcess(128u); + SetInitialVolume(255u); + + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .WillOnce(Return(kAboveClippedThreshold)); + EXPECT_CALL(*agc_, Reset()).Times(1); + ExpectVolumeChange(255u, 240u); + PreProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true))); + EXPECT_CALL(volume_, GetMicVolume(_)) + .WillRepeatedly(DoAll(SetArgReferee<0>(240u), Return(0))); + EXPECT_CALL(volume_, SetMicVolume(_)).Times(0); + PostProcCallback(10); +} + +TEST_F(AgcManagerUnitTest, ClippingMaxIsRespectedWhenHigherThanLevel) { + SetVolumeAndProcess(128u); + SetInitialVolume(200u); + + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .WillOnce(Return(kAboveClippedThreshold)); + EXPECT_CALL(*agc_, Reset()).Times(1); + ExpectVolumeChange(200u, 185u); + PreProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillRepeatedly(DoAll(SetArgPointee<0>(40), Return(true))); + ExpectVolumeChange(185u, 240u); + PostProcCallback(1); + EXPECT_CALL(volume_, GetMicVolume(_)) + .WillRepeatedly(DoAll(SetArgReferee<0>(240u), Return(0))); + EXPECT_CALL(volume_, SetMicVolume(_)).Times(0); + PostProcCallback(10); +} + +TEST_F(AgcManagerUnitTest, MaxCompressionIsIncreasedAfterClipping) { + SetVolumeAndProcess(128u); + SetInitialVolume(210u); + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .WillOnce(Return(kAboveClippedThreshold)); + EXPECT_CALL(*agc_, Reset()).Times(1); + ExpectVolumeChange(210u, 195u); + PreProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))) + .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))) + .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))) + .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))) + .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))) + .WillRepeatedly(Return(false)); + PostProcCallback(19); + EXPECT_CALL(*gctrl_, set_compression_gain_db(8)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(9)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(10)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(11)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(12)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(13)).WillOnce(Return(0)); + PostProcCallback(1); + + // Continue clipping until we hit the maximum surplus compression. + PreProcCallback(300); + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .WillOnce(Return(kAboveClippedThreshold)); + EXPECT_CALL(*agc_, Reset()).Times(1); + ExpectVolumeChange(195u, 180u); + PreProcCallback(1); + + PreProcCallback(300); + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .WillOnce(Return(kAboveClippedThreshold)); + EXPECT_CALL(*agc_, Reset()).Times(1); + ExpectVolumeChange(180u, 170u); + PreProcCallback(1); + + // Current level is now at the minimum, but the maximum allowed level still + // has more to decrease. + PreProcCallback(300); + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .WillOnce(Return(kAboveClippedThreshold)); + PreProcCallback(1); + + PreProcCallback(300); + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .WillOnce(Return(kAboveClippedThreshold)); + PreProcCallback(1); + + PreProcCallback(300); + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .WillOnce(Return(kAboveClippedThreshold)); + PreProcCallback(1); + + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(16), Return(true))) + .WillOnce(DoAll(SetArgPointee<0>(16), Return(true))) + .WillOnce(DoAll(SetArgPointee<0>(16), Return(true))) + .WillOnce(DoAll(SetArgPointee<0>(16), Return(true))) + .WillRepeatedly(Return(false)); + PostProcCallback(19); + EXPECT_CALL(*gctrl_, set_compression_gain_db(14)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(15)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(16)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(17)).WillOnce(Return(0)); + PostProcCallback(20); + EXPECT_CALL(*gctrl_, set_compression_gain_db(18)).WillOnce(Return(0)); + PostProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, UserCanRaiseVolumeAfterClipping) { + SetVolumeAndProcess(128u); + SetInitialVolume(225u); + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .WillOnce(Return(kAboveClippedThreshold)); + EXPECT_CALL(*agc_, Reset()).Times(1); + ExpectVolumeChange(225u, 210u); + PreProcCallback(1); + + // High enough error to trigger a volume check. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(14), Return(true))); + // User changed the volume. + EXPECT_CALL(volume_, GetMicVolume(_)) + .WillOnce(DoAll(SetArgReferee<0>(250u), Return(0))); + EXPECT_CALL(volume_, SetMicVolume(_)).Times(0); + EXPECT_CALL(*agc_, Reset()).Times(1); + PostProcCallback(1); + + // Move down... + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(-10), Return(true))); + ExpectVolumeChange(250u, 210u); + PostProcCallback(1); + // And back up to the new max established by the user. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(40), Return(true))); + ExpectVolumeChange(210u, 250u); + PostProcCallback(1); + // Will not move above new maximum. + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); + EXPECT_CALL(volume_, GetMicVolume(_)) + .WillRepeatedly(DoAll(SetArgReferee<0>(250u), Return(0))); + EXPECT_CALL(volume_, SetMicVolume(_)).Times(0); + PostProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, ClippingDoesNotPullLowVolumeBackUp) { + SetVolumeAndProcess(128u); + SetInitialVolume(80u); + EXPECT_CALL(*agc_, AnalyzePreproc(_, _)) + .WillOnce(Return(kAboveClippedThreshold)); + EXPECT_CALL(volume_, GetMicVolume(_)).Times(0); + EXPECT_CALL(volume_, SetMicVolume(_)).Times(0); + EXPECT_CALL(*agc_, Reset()).Times(0); + PreProcCallback(1); +} + +TEST_F(AgcManagerUnitTest, TakesNoActionOnZeroMicVolume) { + SetVolumeAndProcess(128u); + EXPECT_CALL(*agc_, GetRmsErrorDb(_)) + .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true))); + EXPECT_CALL(volume_, GetMicVolume(_)) + .WillRepeatedly(DoAll(SetArgReferee<0>(0), Return(0))); + EXPECT_CALL(volume_, SetMicVolume(_)).Times(0); + PostProcCallback(10); +} + +} // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/tools/agc/agc_test.cc b/media/webrtc/trunk/webrtc/tools/agc/agc_test.cc new file mode 100644 index 0000000000..29769488c1 --- /dev/null +++ b/media/webrtc/trunk/webrtc/tools/agc/agc_test.cc @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include +#include + +#include + +#include "gflags/gflags.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/audio_processing/agc/agc.h" +#include "webrtc/modules/audio_processing/agc/utility.h" +#include "webrtc/modules/audio_processing/include/audio_processing.h" +#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/system_wrappers/interface/logging.h" +#include "webrtc/test/testsupport/trace_to_stderr.h" +#include "webrtc/tools/agc/agc_manager.h" +#include "webrtc/tools/agc/test_utils.h" +#include "webrtc/voice_engine/include/mock/fake_voe_external_media.h" +#include "webrtc/voice_engine/include/mock/mock_voe_volume_control.h" + +DEFINE_string(in, "in.pcm", "input filename"); +DEFINE_string(out, "out.pcm", "output filename"); +DEFINE_int32(rate, 16000, "sample rate in Hz"); +DEFINE_int32(channels, 1, "number of channels"); +DEFINE_int32(level, -18, "target level in RMS dBFs [-100, 0]"); +DEFINE_bool(limiter, true, "enable a limiter for the compression stage"); +DEFINE_int32(cmp_level, 2, "target level in dBFs for the compression stage"); +DEFINE_int32(mic_gain, 80, "range of gain provided by the virtual mic in dB"); +DEFINE_int32(gain_offset, 0, + "an amount (in dB) to add to every entry in the gain map"); +DEFINE_string(gain_file, "", + "filename providing a mic gain mapping. The file should be text containing " + "a (floating-point) gain entry in dBFs per line corresponding to levels " + "from 0 to 255."); + +using ::testing::_; +using ::testing::ByRef; +using ::testing::DoAll; +using ::testing::Mock; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::SetArgReferee; + +namespace webrtc { +namespace { + +const char kUsage[] = "\nProcess an audio file to simulate an analog agc."; + +void ReadGainMapFromFile(FILE* file, int offset, int gain_map[256]) { + for (int i = 0; i < 256; ++i) { + float gain = 0; + ASSERT_EQ(1, fscanf(file, "%f", &gain)); + gain_map[i] = std::floor(gain + 0.5); + } + + // Adjust from dBFs to gain in dB. We assume that level 127 provides 0 dB + // gain. This corresponds to the interpretation in MicLevel2Gain(). + const int midpoint = gain_map[127]; + printf("Gain map\n"); + for (int i = 0; i < 256; ++i) { + gain_map[i] += offset - midpoint; + if (i % 5 == 0) { + printf("%d: %d dB\n", i, gain_map[i]); + } + } +} + +void CalculateGainMap(int gain_range_db, int offset, int gain_map[256]) { + printf("Gain map\n"); + for (int i = 0; i < 256; ++i) { + gain_map[i] = std::floor(MicLevel2Gain(gain_range_db, i) + 0.5) + offset; + if (i % 5 == 0) { + printf("%d: %d dB\n", i, gain_map[i]); + } + } +} + +void RunAgc() { + test::TraceToStderr trace_to_stderr(true); + FILE* in_file = fopen(FLAGS_in.c_str(), "rb"); + ASSERT_TRUE(in_file != NULL); + FILE* out_file = fopen(FLAGS_out.c_str(), "wb"); + ASSERT_TRUE(out_file != NULL); + + int gain_map[256]; + if (FLAGS_gain_file != "") { + FILE* gain_file = fopen(FLAGS_gain_file.c_str(), "rt"); + ASSERT_TRUE(gain_file != NULL); + ReadGainMapFromFile(gain_file, FLAGS_gain_offset, gain_map); + fclose(gain_file); + } else { + CalculateGainMap(FLAGS_mic_gain, FLAGS_gain_offset, gain_map); + } + + FakeVoEExternalMedia media; + MockVoEVolumeControl volume; + Agc* agc = new Agc; + AudioProcessing* audioproc = AudioProcessing::Create(); + ASSERT_TRUE(audioproc != NULL); + AgcManager manager(&media, &volume, agc, audioproc); + + int mic_level = 128; + int last_mic_level = mic_level; + EXPECT_CALL(volume, GetMicVolume(_)) + .WillRepeatedly(DoAll(SetArgReferee<0>(ByRef(mic_level)), Return(0))); + EXPECT_CALL(volume, SetMicVolume(_)) + .WillRepeatedly(DoAll(SaveArg<0>(&mic_level), Return(0))); + + manager.Enable(true); + ASSERT_EQ(0, agc->set_target_level_dbfs(FLAGS_level)); + const AudioProcessing::Error kNoErr = AudioProcessing::kNoError; + GainControl* gctrl = audioproc->gain_control(); + ASSERT_EQ(kNoErr, gctrl->set_target_level_dbfs(FLAGS_cmp_level)); + ASSERT_EQ(kNoErr, gctrl->enable_limiter(FLAGS_limiter)); + + AudioFrame frame; + frame.num_channels_ = FLAGS_channels; + frame.sample_rate_hz_ = FLAGS_rate; + frame.samples_per_channel_ = FLAGS_rate / 100; + const size_t frame_length = frame.samples_per_channel_ * FLAGS_channels; + size_t sample_count = 0; + while (fread(frame.data_, sizeof(int16_t), frame_length, in_file) == + frame_length) { + SimulateMic(gain_map, mic_level, last_mic_level, &frame); + last_mic_level = mic_level; + media.CallProcess(kRecordingAllChannelsMixed, frame.data_, + frame.samples_per_channel_, FLAGS_rate, FLAGS_channels); + ASSERT_EQ(frame_length, + fwrite(frame.data_, sizeof(int16_t), frame_length, out_file)); + sample_count += frame_length; + trace_to_stderr.SetTimeSeconds(static_cast(sample_count) / + FLAGS_channels / FLAGS_rate); + } + fclose(in_file); + fclose(out_file); + EXPECT_CALL(volume, Release()); +} + +} // namespace +} // namespace webrtc + +int main(int argc, char* argv[]) { + google::SetUsageMessage(webrtc::kUsage); + google::ParseCommandLineFlags(&argc, &argv, true); + webrtc::RunAgc(); + return 0; +} diff --git a/media/webrtc/trunk/webrtc/tools/agc/fake_agc.h b/media/webrtc/trunk/webrtc/tools/agc/fake_agc.h new file mode 100644 index 0000000000..6b39cd7c3b --- /dev/null +++ b/media/webrtc/trunk/webrtc/tools/agc/fake_agc.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_TOOLS_AGC_FAKE_AGC_H_ +#define WEBRTC_TOOLS_AGC_FAKE_AGC_H_ + +#include "webrtc/modules/audio_processing/agc/agc.h" + +namespace webrtc { + +class FakeAgc : public Agc { + public: + FakeAgc() + : counter_(0), + volume_(kMaxVolume / 2) { + } + + virtual int Process(const AudioFrame& audio_frame) { + const int kUpdateIntervalFrames = 10; + const int kMaxVolume = 255; + if (counter_ % kUpdateIntervalFrames == 0) { + volume_ = (++volume_) % kMaxVolume; + } + counter_++; + return 0; + } + + virtual int FakeAgc::MicVolume() { + return volume_; + } + + private: + int counter_; + int volume_; +}; + +} // namespace webrtc + +#endif // WEBRTC_TOOLS_AGC_FAKE_AGC_H_ diff --git a/media/webrtc/trunk/webrtc/tools/agc/test_utils.cc b/media/webrtc/trunk/webrtc/tools/agc/test_utils.cc new file mode 100644 index 0000000000..3a26cb9ac7 --- /dev/null +++ b/media/webrtc/trunk/webrtc/tools/agc/test_utils.cc @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/tools/agc/test_utils.h" + +#include + +#include + +#include "webrtc/modules/interface/module_common_types.h" + +namespace webrtc { + +float MicLevel2Gain(int gain_range_db, int level) { + return (level - 127.0f) / 128.0f * gain_range_db / 2; +} + +float Db2Linear(float db) { + return powf(10.0f, db / 20.0f); +} + +void ApplyGainLinear(float gain, float last_gain, AudioFrame* frame) { + const int frame_length = frame->samples_per_channel_ * frame->num_channels_; + // Smooth the transition between gain levels across the frame. + float smoothed_gain = last_gain; + float gain_step = (gain - last_gain) / (frame_length - 1); + for (int i = 0; i < frame_length; ++i) { + smoothed_gain += gain_step; + float sample = std::floor(frame->data_[i] * smoothed_gain + 0.5); + sample = std::max(std::min(32767.0f, sample), -32768.0f); + frame->data_[i] = static_cast(sample); + } +} + +void ApplyGain(float gain_db, float last_gain_db, AudioFrame* frame) { + ApplyGainLinear(Db2Linear(gain_db), Db2Linear(last_gain_db), frame); +} + +void SimulateMic(int gain_range_db, int mic_level, int last_mic_level, + AudioFrame* frame) { + assert(mic_level >= 0 && mic_level <= 255); + assert(last_mic_level >= 0 && last_mic_level <= 255); + ApplyGain(MicLevel2Gain(gain_range_db, mic_level), + MicLevel2Gain(gain_range_db, last_mic_level), + frame); +} + +void SimulateMic(int gain_map[255], int mic_level, int last_mic_level, + AudioFrame* frame) { + assert(mic_level >= 0 && mic_level <= 255); + assert(last_mic_level >= 0 && last_mic_level <= 255); + ApplyGain(gain_map[mic_level], gain_map[last_mic_level], frame); +} + +} // namespace webrtc + diff --git a/media/webrtc/trunk/webrtc/tools/agc/test_utils.h b/media/webrtc/trunk/webrtc/tools/agc/test_utils.h new file mode 100644 index 0000000000..2aca9996f9 --- /dev/null +++ b/media/webrtc/trunk/webrtc/tools/agc/test_utils.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_TOOLS_AGC_TEST_UTILS_H_ +#define WEBRTC_TOOLS_AGC_TEST_UTILS_H_ +namespace webrtc { + +class AudioFrame; + +float MicLevel2Gain(int gain_range_db, int level); +float Db2Linear(float db); +void ApplyGainLinear(float gain, float last_gain, AudioFrame* frame); +void ApplyGain(float gain_db, float last_gain_db, AudioFrame* frame); +void SimulateMic(int gain_range_db, int mic_level, int last_mic_level, + AudioFrame* frame); +void SimulateMic(int gain_map[255], int mic_level, int last_mic_level, + AudioFrame* frame); + +} // namespace webrtc + +#endif // WEBRTC_TOOLS_AGC_TEST_UTILS_H_ diff --git a/media/webrtc/trunk/webrtc/tools/converter/converter.h b/media/webrtc/trunk/webrtc/tools/converter/converter.h index ce21c95db9..a23d5a14d4 100644 --- a/media/webrtc/trunk/webrtc/tools/converter/converter.h +++ b/media/webrtc/trunk/webrtc/tools/converter/converter.h @@ -13,8 +13,8 @@ #include -#include "third_party/libyuv/include/libyuv/compare.h" -#include "third_party/libyuv/include/libyuv/convert.h" +#include "libyuv/compare.h" // NOLINT +#include "libyuv/convert.h" // NOLINT namespace webrtc { namespace test { diff --git a/media/webrtc/trunk/webrtc/tools/e2e_quality/audio/audio_e2e_harness.cc b/media/webrtc/trunk/webrtc/tools/e2e_quality/audio/audio_e2e_harness.cc index 39e9974aa7..1eb8925537 100644 --- a/media/webrtc/trunk/webrtc/tools/e2e_quality/audio/audio_e2e_harness.cc +++ b/media/webrtc/trunk/webrtc/tools/e2e_quality/audio/audio_e2e_harness.cc @@ -15,7 +15,7 @@ #include "gflags/gflags.h" #include "testing/gtest/include/gtest/gtest.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/test/channel_transport/include/channel_transport.h" #include "webrtc/voice_engine/include/voe_audio_processing.h" #include "webrtc/voice_engine/include/voe_base.h" @@ -48,7 +48,7 @@ void RunHarness() { int channel = base->CreateChannel(); ASSERT_NE(-1, channel); - scoped_ptr voice_channel_transport( + rtc::scoped_ptr voice_channel_transport( new VoiceChannelTransport(network, channel)); ASSERT_EQ(0, voice_channel_transport->SetSendDestination("127.0.0.1", 1234)); diff --git a/media/webrtc/trunk/webrtc/tools/e2e_quality/audio/perf/__init__.py b/media/webrtc/trunk/webrtc/tools/e2e_quality/audio/perf/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/media/webrtc/trunk/webrtc/tools/e2e_quality/audio/perf/perf_utils.py b/media/webrtc/trunk/webrtc/tools/e2e_quality/audio/perf/perf_utils.py new file mode 100644 index 0000000000..77eda1e7a3 --- /dev/null +++ b/media/webrtc/trunk/webrtc/tools/e2e_quality/audio/perf/perf_utils.py @@ -0,0 +1,31 @@ +# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Copied from /src/chrome/test/pyautolib/pyauto_utils.py in Chromium. + +import sys + +def PrintPerfResult(graph_name, series_name, data_point, units, + show_on_waterfall=False): + """Prints a line to stdout that is specially formatted for the perf bots. + + Args: + graph_name: String name for the graph on which to plot the data. + series_name: String name for the series (line on the graph) associated with + the data. This is also the string displayed on the waterfall + if |show_on_waterfall| is True. + data_point: Numeric data value to plot on the graph for the current build. + This can be a single value or an array of values. If an array, + the graph will plot the average of the values, along with error + bars. + units: The string unit of measurement for the given |data_point|. + show_on_waterfall: Whether or not to display this result directly on the + buildbot waterfall itself (in the buildbot step running + this test on the waterfall page, not the stdio page). + """ + waterfall_indicator = ['', '*'][show_on_waterfall] + print '%sRESULT %s: %s= %s %s' % ( + waterfall_indicator, graph_name, series_name, + str(data_point).replace(' ', ''), units) + sys.stdout.flush() \ No newline at end of file diff --git a/media/webrtc/trunk/webrtc/tools/force_mic_volume_max/force_mic_volume_max.cc b/media/webrtc/trunk/webrtc/tools/force_mic_volume_max/force_mic_volume_max.cc index 11fb18aa3e..570fa0ad24 100644 --- a/media/webrtc/trunk/webrtc/tools/force_mic_volume_max/force_mic_volume_max.cc +++ b/media/webrtc/trunk/webrtc/tools/force_mic_volume_max/force_mic_volume_max.cc @@ -12,7 +12,7 @@ #include -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/test/channel_transport/include/channel_transport.h" #include "webrtc/voice_engine/include/voe_audio_processing.h" #include "webrtc/voice_engine/include/voe_base.h" diff --git a/media/webrtc/trunk/webrtc/tools/frame_analyzer/video_quality_analysis.cc b/media/webrtc/trunk/webrtc/tools/frame_analyzer/video_quality_analysis.cc index c2a5e4991f..f5608c8343 100644 --- a/media/webrtc/trunk/webrtc/tools/frame_analyzer/video_quality_analysis.cc +++ b/media/webrtc/trunk/webrtc/tools/frame_analyzer/video_quality_analysis.cc @@ -356,7 +356,7 @@ void PrintAnalysisResults(FILE* output, const std::string& label, ++iter) { fprintf(output, "%f,", iter->ssim_value); } - fprintf(output, "%f]\n", iter->ssim_value); + fprintf(output, "%f] score\n", iter->ssim_value); } } diff --git a/media/webrtc/trunk/webrtc/tools/frame_analyzer/video_quality_analysis.h b/media/webrtc/trunk/webrtc/tools/frame_analyzer/video_quality_analysis.h index 31064a28f8..4704a8cde9 100644 --- a/media/webrtc/trunk/webrtc/tools/frame_analyzer/video_quality_analysis.h +++ b/media/webrtc/trunk/webrtc/tools/frame_analyzer/video_quality_analysis.h @@ -14,8 +14,8 @@ #include #include -#include "third_party/libyuv/include/libyuv/compare.h" -#include "third_party/libyuv/include/libyuv/convert.h" +#include "libyuv/compare.h" // NOLINT +#include "libyuv/convert.h" // NOLINT namespace webrtc { namespace test { diff --git a/media/webrtc/trunk/webrtc/tools/frame_editing/frame_editing_lib.cc b/media/webrtc/trunk/webrtc/tools/frame_editing/frame_editing_lib.cc index 93a548fe56..79c6033a30 100644 --- a/media/webrtc/trunk/webrtc/tools/frame_editing/frame_editing_lib.cc +++ b/media/webrtc/trunk/webrtc/tools/frame_editing/frame_editing_lib.cc @@ -13,8 +13,8 @@ #include +#include "webrtc/base/scoped_ptr.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/typedefs.h" using std::string; @@ -36,9 +36,9 @@ int EditFrames(const string& in_path, int width, int height, } // Frame size of I420. - int frame_length = CalcBufferSize(kI420, width, height); + size_t frame_length = CalcBufferSize(kI420, width, height); - webrtc::scoped_ptr temp_buffer(new uint8_t[frame_length]); + rtc::scoped_ptr temp_buffer(new uint8_t[frame_length]); FILE* out_fid = fopen(out_path.c_str(), "wb"); @@ -50,7 +50,7 @@ int EditFrames(const string& in_path, int width, int height, int num_frames_read = 0; int num_frames_read_between = 0; - int num_bytes_read; + size_t num_bytes_read; while ((num_bytes_read = fread(temp_buffer.get(), 1, frame_length, in_fid)) == frame_length) { diff --git a/media/webrtc/trunk/webrtc/tools/frame_editing/frame_editing_unittest.cc b/media/webrtc/trunk/webrtc/tools/frame_editing/frame_editing_unittest.cc index 69468e18ce..31991b7175 100644 --- a/media/webrtc/trunk/webrtc/tools/frame_editing/frame_editing_unittest.cc +++ b/media/webrtc/trunk/webrtc/tools/frame_editing/frame_editing_unittest.cc @@ -14,8 +14,8 @@ #include #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/test/testsupport/fileutils.h" #include "webrtc/tools/frame_editing/frame_editing_lib.h" @@ -24,7 +24,7 @@ namespace test { const int kWidth = 352; const int kHeight = 288; -const int kFrameSize = CalcBufferSize(kI420, kWidth, kHeight); +const size_t kFrameSize = CalcBufferSize(kI420, kWidth, kHeight); class FrameEditingTest : public ::testing::Test { protected: @@ -54,9 +54,10 @@ class FrameEditingTest : public ::testing::Test { remove(test_video_.c_str()); } // Compares the frames in both streams to the end of one of the streams. - void CompareToTheEnd(FILE* test_video_fid, FILE* ref_video_fid, - scoped_ptr* ref_buffer, - scoped_ptr* test_buffer) { + void CompareToTheEnd(FILE* test_video_fid, + FILE* ref_video_fid, + rtc::scoped_ptr* ref_buffer, + rtc::scoped_ptr* test_buffer) { while (!feof(test_video_fid) && !feof(ref_video_fid)) { num_bytes_read_ = fread(ref_buffer->get(), 1, kFrameSize, ref_video_fid); if (!feof(ref_video_fid)) { @@ -79,9 +80,9 @@ class FrameEditingTest : public ::testing::Test { std::string test_video_; FILE* original_fid_; FILE* edited_fid_; - int num_bytes_read_; - scoped_ptr original_buffer_; - scoped_ptr edited_buffer_; + size_t num_bytes_read_; + rtc::scoped_ptr original_buffer_; + rtc::scoped_ptr edited_buffer_; int num_frames_read_; }; diff --git a/media/webrtc/trunk/webrtc/tools/simple_command_line_parser_unittest.cc b/media/webrtc/trunk/webrtc/tools/simple_command_line_parser_unittest.cc index f016b17d99..48640df172 100644 --- a/media/webrtc/trunk/webrtc/tools/simple_command_line_parser_unittest.cc +++ b/media/webrtc/trunk/webrtc/tools/simple_command_line_parser_unittest.cc @@ -16,7 +16,7 @@ namespace test { class CommandLineParserTest : public ::testing::Test { protected: - virtual void SetUp() { + void SetUp() override { parser_ = new CommandLineParser(); test_flags_length_ = 3; @@ -29,7 +29,7 @@ class CommandLineParserTest : public ::testing::Test { strncpy(test_flags_[1], "--foo", flag_size); strncpy(test_flags_[2], "--bar=1", flag_size); } - virtual void TearDown() { + void TearDown() override { for (int i = 0; i < test_flags_length_; ++i) { delete[] test_flags_[i]; } diff --git a/media/webrtc/trunk/webrtc/tools/tools.gyp b/media/webrtc/trunk/webrtc/tools/tools.gyp index 102ba8ec30..e2a54212ec 100644 --- a/media/webrtc/trunk/webrtc/tools/tools.gyp +++ b/media/webrtc/trunk/webrtc/tools/tools.gyp @@ -15,10 +15,10 @@ 'target_name': 'video_quality_analysis', 'type': 'static_library', 'dependencies': [ - '<(DEPTH)/third_party/libyuv/libyuv.gyp:libyuv', + '<(webrtc_root)/common_video/common_video.gyp:common_video', ], 'export_dependent_settings': [ - '<(DEPTH)/third_party/libyuv/libyuv.gyp:libyuv', + '<(webrtc_root)/common_video/common_video.gyp:common_video', ], 'sources': [ 'frame_analyzer/video_quality_analysis.h', @@ -51,8 +51,8 @@ 'target_name': 'rgba_to_i420_converter', 'type': 'executable', 'dependencies': [ + '<(webrtc_root)/common_video/common_video.gyp:common_video', '<(webrtc_root)/tools/internal_tools.gyp:command_line_parser', - '<(DEPTH)/third_party/libyuv/libyuv.gyp:libyuv', ], 'sources': [ 'converter/converter.h', @@ -91,7 +91,7 @@ 'type': 'executable', 'dependencies': [ '<(webrtc_root)/voice_engine/voice_engine.gyp:voice_engine', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers_default', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers_default', ], 'sources': [ 'force_mic_volume_max/force_mic_volume_max.cc', @@ -101,13 +101,77 @@ 'conditions': [ ['include_tests==1', { 'targets' : [ + { + 'target_name': 'agc_manager', + 'type': 'static_library', + 'dependencies': [ + '<(webrtc_root)/common_audio/common_audio.gyp:common_audio', + '<(webrtc_root)/modules/modules.gyp:audio_processing', + '<(webrtc_root)/voice_engine/voice_engine.gyp:voice_engine', + ], + 'sources': [ + 'agc/agc_manager.cc', + 'agc/agc_manager.h', + ], + }, + { + 'target_name': 'agc_test_utils', + 'type': 'static_library', + 'sources': [ + 'agc/test_utils.cc', + 'agc/test_utils.h', + ], + }, + { + 'target_name': 'agc_harness', + 'type': 'executable', + 'dependencies': [ + '<(DEPTH)/testing/gtest.gyp:gtest', + '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers_default', + '<(webrtc_root)/test/test.gyp:channel_transport', + '<(webrtc_root)/test/test.gyp:test_support', + 'agc_manager', + ], + 'sources': [ + 'agc/agc_harness.cc', + ], + }, # agc_harness + { + 'target_name': 'agc_proc', + 'type': 'executable', + 'dependencies': [ + '<(DEPTH)/testing/gmock.gyp:gmock', + '<(DEPTH)/testing/gtest.gyp:gtest', + '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', + '<(webrtc_root)/test/test.gyp:test_support', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers_default', + 'agc_manager', + 'agc_test_utils', + ], + 'sources': [ + 'agc/agc_test.cc', + ], + }, # agc_proc + { + 'target_name': 'activity_metric', + 'type': 'executable', + 'dependencies': [ + '<(DEPTH)/testing/gtest.gyp:gtest', + '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', + 'agc_manager', + ], + 'sources': [ + 'agc/activity_metric.cc', + ], + }, # activity_metric { 'target_name': 'audio_e2e_harness', 'type': 'executable', 'dependencies': [ '<(webrtc_root)/test/test.gyp:channel_transport', '<(webrtc_root)/voice_engine/voice_engine.gyp:voice_engine', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers_default', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers_default', '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', ], diff --git a/media/webrtc/trunk/webrtc/tools/tools_unittests.isolate b/media/webrtc/trunk/webrtc/tools/tools_unittests.isolate index bf1fd0199a..ebe4714f7e 100644 --- a/media/webrtc/trunk/webrtc/tools/tools_unittests.isolate +++ b/media/webrtc/trunk/webrtc/tools/tools_unittests.isolate @@ -7,11 +7,10 @@ # be found in the AUTHORS file in the root of the source tree. { 'conditions': [ - ['OS=="android"', { + ['OS=="linux" or OS=="mac" or OS=="win" or OS=="android"', { 'variables': { 'files': [ - '<(DEPTH)/data/', - '<(DEPTH)/resources/', + '<(DEPTH)/resources/foreman_cif.yuv', ], }, }], @@ -23,7 +22,6 @@ ], 'files': [ '<(DEPTH)/DEPS', - '<(DEPTH)/resources/foreman_cif.yuv', '<(DEPTH)/testing/test_env.py', '<(PRODUCT_DIR)/tools_unittests<(EXECUTABLE_SUFFIX)', ], diff --git a/media/webrtc/trunk/webrtc/typedefs.h b/media/webrtc/trunk/webrtc/typedefs.h index 11f6b1ce5e..99ea82a994 100644 --- a/media/webrtc/trunk/webrtc/typedefs.h +++ b/media/webrtc/trunk/webrtc/typedefs.h @@ -155,28 +155,6 @@ typedef unsigned int uint32_t; typedef unsigned __int64 uint64_t; #endif -// Borrowed from Chromium's base/compiler_specific.h. -// Annotate a virtual method indicating it must be overriding a virtual -// method in the parent class. -// Use like: -// virtual void foo() OVERRIDE; -#if defined(_MSC_VER) -#define OVERRIDE override -#elif defined(__clang__) -// Clang defaults to C++03 and warns about using override. Squelch that. -// Intentionally no push/pop here so all users of OVERRIDE ignore the warning -// too. This is like passing -Wno-c++11-extensions, except that GCC won't die -// (because it won't see this pragma). -#pragma clang diagnostic ignored "-Wc++11-extensions" -#define OVERRIDE override -#elif defined(__GNUC__) && __cplusplus >= 201103 && \ - (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700 -// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled. -#define OVERRIDE override -#else -#define OVERRIDE -#endif - // Annotate a function indicating the caller must examine the return value. // Use like: // int foo() WARN_UNUSED_RESULT; @@ -191,13 +169,23 @@ typedef unsigned __int64 uint64_t; #endif // WARN_UNUSED_RESULT // Put after a variable that might not be used, to prevent compiler warnings: -// int result UNUSED = DoSomething(); +// int result ATTRIBUTE_UNUSED = DoSomething(); // assert(result == 17); -#ifndef UNUSED -#ifdef __GNUC__ -#define UNUSED __attribute__((unused)) +#ifndef ATTRIBUTE_UNUSED +#if defined(__GNUC__) || defined(__clang__) +#define ATTRIBUTE_UNUSED __attribute__((unused)) #else -#define UNUSED +#define ATTRIBUTE_UNUSED +#endif +#endif + +// Macro to be used for switch-case fallthrough (required for enabling +// -Wimplicit-fallthrough warning on Clang). +#ifndef FALLTHROUGH +#if defined(__clang__) +#define FALLTHROUGH() [[clang::fallthrough]] +#else +#define FALLTHROUGH() do { } while (0) #endif #endif diff --git a/media/webrtc/trunk/webrtc/video/BUILD.gn b/media/webrtc/trunk/webrtc/video/BUILD.gn index df9b20d5fc..ee55105798 100644 --- a/media/webrtc/trunk/webrtc/video/BUILD.gn +++ b/media/webrtc/trunk/webrtc/video/BUILD.gn @@ -34,6 +34,9 @@ source_set("video") { configs -= [ "//build/config/clang:find_bad_constructs" ] } - deps = [ "../video_engine:video_engine_core" ] + deps = [ + "..:webrtc_common", + "../video_engine:video_engine_core", + ] } diff --git a/media/webrtc/trunk/webrtc/video/bitrate_estimator_tests.cc b/media/webrtc/trunk/webrtc/video/bitrate_estimator_tests.cc index 29fb7300c0..c968b71b6b 100644 --- a/media/webrtc/trunk/webrtc/video/bitrate_estimator_tests.cc +++ b/media/webrtc/trunk/webrtc/video/bitrate_estimator_tests.cc @@ -13,11 +13,12 @@ #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/checks.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/call.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/event_wrapper.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/trace.h" #include "webrtc/test/call_test.h" #include "webrtc/test/direct_transport.h" @@ -48,7 +49,7 @@ class TraceObserver { } ~TraceObserver() { - Trace::SetTraceCallback(NULL); + Trace::SetTraceCallback(nullptr); Trace::ReturnTrace(); } @@ -67,9 +68,7 @@ class TraceObserver { : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), done_(EventWrapper::Create()) {} - virtual void Print(TraceLevel level, - const char* message, - int length) OVERRIDE { + void Print(TraceLevel level, const char* message, int length) override { CriticalSectionScoped lock(crit_sect_.get()); std::string msg(message); if (msg.find("BitrateEstimator") != std::string::npos) { @@ -103,10 +102,10 @@ class TraceObserver { private: typedef std::list Strings; - const scoped_ptr crit_sect_; + const rtc::scoped_ptr crit_sect_; Strings received_log_lines_ GUARDED_BY(crit_sect_); Strings expected_log_lines_ GUARDED_BY(crit_sect_); - scoped_ptr done_; + rtc::scoped_ptr done_; }; Callback callback_; @@ -145,7 +144,7 @@ class BitrateEstimatorTest : public test::CallTest { send_config_ = VideoSendStream::Config(); send_config_.rtp.ssrcs.push_back(kSendSsrcs[0]); // Encoders will be set separately per stream. - send_config_.encoder_settings.encoder = NULL; + send_config_.encoder_settings.encoder = nullptr; send_config_.encoder_settings.payload_name = "FAKE"; send_config_.encoder_settings.payload_type = kFakeSendPayloadType; encoder_config_.streams = test::CreateVideoStreams(1); @@ -183,8 +182,8 @@ class BitrateEstimatorTest : public test::CallTest { explicit Stream(BitrateEstimatorTest* test) : test_(test), is_sending_receiving_(false), - send_stream_(NULL), - receive_stream_(NULL), + send_stream_(nullptr), + receive_stream_(nullptr), frame_generator_capturer_(), fake_encoder_(Clock::GetRealTimeClock()), fake_decoder_() { @@ -192,7 +191,7 @@ class BitrateEstimatorTest : public test::CallTest { test_->send_config_.encoder_settings.encoder = &fake_encoder_; send_stream_ = test_->sender_call_->CreateVideoSendStream( test_->send_config_, test_->encoder_config_); - assert(test_->encoder_config_.streams.size() == 1); + DCHECK_EQ(1u, test_->encoder_config_.streams.size()); frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create( send_stream_->Input(), test_->encoder_config_.streams[0].width, @@ -217,11 +216,11 @@ class BitrateEstimatorTest : public test::CallTest { } ~Stream() { - frame_generator_capturer_.reset(NULL); + frame_generator_capturer_.reset(nullptr); test_->sender_call_->DestroyVideoSendStream(send_stream_); - send_stream_ = NULL; + send_stream_ = nullptr; test_->receiver_call_->DestroyVideoReceiveStream(receive_stream_); - receive_stream_ = NULL; + receive_stream_ = nullptr; } void StopSending() { @@ -238,7 +237,7 @@ class BitrateEstimatorTest : public test::CallTest { bool is_sending_receiving_; VideoSendStream* send_stream_; VideoReceiveStream* receive_stream_; - scoped_ptr frame_generator_capturer_; + rtc::scoped_ptr frame_generator_capturer_; test::FakeEncoder fake_encoder_; test::FakeDecoder fake_decoder_; }; @@ -246,8 +245,8 @@ class BitrateEstimatorTest : public test::CallTest { TraceObserver receiver_trace_; test::DirectTransport send_transport_; test::DirectTransport receive_transport_; - scoped_ptr sender_call_; - scoped_ptr receiver_call_; + rtc::scoped_ptr sender_call_; + rtc::scoped_ptr receiver_call_; VideoReceiveStream::Config receive_config_; std::vector streams_; }; diff --git a/media/webrtc/trunk/webrtc/video/call.cc b/media/webrtc/trunk/webrtc/video/call.cc index 2b4f76f4c5..d9dc334c00 100644 --- a/media/webrtc/trunk/webrtc/video/call.cc +++ b/media/webrtc/trunk/webrtc/video/call.cc @@ -8,23 +8,27 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include #include #include #include +#include "webrtc/base/checks.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/call.h" #include "webrtc/common.h" #include "webrtc/config.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" #include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h" +#include "webrtc/modules/video_render/include/video_render.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" +#include "webrtc/system_wrappers/interface/logging.h" #include "webrtc/system_wrappers/interface/rw_lock_wrapper.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/trace.h" +#include "webrtc/system_wrappers/interface/trace_event.h" #include "webrtc/video/video_receive_stream.h" #include "webrtc/video/video_send_stream.h" #include "webrtc/video_engine/include/vie_base.h" @@ -37,10 +41,12 @@ namespace webrtc { const char* RtpExtension::kTOffset = "urn:ietf:params:rtp-hdrext:toffset"; const char* RtpExtension::kAbsSendTime = "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time"; +const char* RtpExtension::kVideoRotation = "urn:3gpp:video-orientation"; bool RtpExtension::IsSupported(const std::string& name) { return name == webrtc::RtpExtension::kTOffset || - name == webrtc::RtpExtension::kAbsSendTime; + name == webrtc::RtpExtension::kAbsSendTime || + name == webrtc::RtpExtension::kVideoRotation; } VideoEncoder* VideoEncoder::Create(VideoEncoder::EncoderType codec_type) { @@ -50,8 +56,8 @@ VideoEncoder* VideoEncoder::Create(VideoEncoder::EncoderType codec_type) { case kVp9: return VP9Encoder::Create(); } - assert(false); - return NULL; + RTC_NOTREACHED(); + return nullptr; } VideoDecoder* VideoDecoder::Create(VideoDecoder::DecoderType codec_type) { @@ -61,8 +67,8 @@ VideoDecoder* VideoDecoder::Create(VideoDecoder::DecoderType codec_type) { case kVp9: return VP9Decoder::Create(); } - assert(false); - return NULL; + RTC_NOTREACHED(); + return nullptr; } const int Call::Config::kDefaultStartBitrateBps = 300000; @@ -74,23 +80,23 @@ class CpuOveruseObserverProxy : public webrtc::CpuOveruseObserver { explicit CpuOveruseObserverProxy(LoadObserver* overuse_callback) : crit_(CriticalSectionWrapper::CreateCriticalSection()), overuse_callback_(overuse_callback) { - assert(overuse_callback != NULL); + DCHECK(overuse_callback != nullptr); } virtual ~CpuOveruseObserverProxy() {} - virtual void OveruseDetected() OVERRIDE { + void OveruseDetected() override { CriticalSectionScoped lock(crit_.get()); overuse_callback_->OnLoadUpdate(LoadObserver::kOveruse); } - virtual void NormalUsage() OVERRIDE { + void NormalUsage() override { CriticalSectionScoped lock(crit_.get()); overuse_callback_->OnLoadUpdate(LoadObserver::kUnderuse); } private: - const scoped_ptr crit_; + const rtc::scoped_ptr crit_; LoadObserver* overuse_callback_ GUARDED_BY(crit_); }; @@ -99,27 +105,27 @@ class Call : public webrtc::Call, public PacketReceiver { Call(webrtc::VideoEngine* video_engine, const Call::Config& config); virtual ~Call(); - virtual PacketReceiver* Receiver() OVERRIDE; + PacketReceiver* Receiver() override; - virtual VideoSendStream* CreateVideoSendStream( + VideoSendStream* CreateVideoSendStream( const VideoSendStream::Config& config, - const VideoEncoderConfig& encoder_config) OVERRIDE; + const VideoEncoderConfig& encoder_config) override; - virtual void DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) - OVERRIDE; + void DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) override; - virtual VideoReceiveStream* CreateVideoReceiveStream( - const VideoReceiveStream::Config& config) OVERRIDE; + VideoReceiveStream* CreateVideoReceiveStream( + const VideoReceiveStream::Config& config) override; - virtual void DestroyVideoReceiveStream( - webrtc::VideoReceiveStream* receive_stream) OVERRIDE; + void DestroyVideoReceiveStream( + webrtc::VideoReceiveStream* receive_stream) override; - virtual Stats GetStats() const OVERRIDE; + Stats GetStats() const override; - virtual DeliveryStatus DeliverPacket(const uint8_t* packet, - size_t length) OVERRIDE; + DeliveryStatus DeliverPacket(const uint8_t* packet, size_t length) override; - virtual void SignalNetworkState(NetworkState state) OVERRIDE; + void SetBitrateConfig( + const webrtc::Call::Config::BitrateConfig& bitrate_config) override; + void SignalNetworkState(NetworkState state) override; private: DeliveryStatus DeliverRtcp(const uint8_t* packet, size_t length); @@ -130,35 +136,39 @@ class Call : public webrtc::Call, public PacketReceiver { // Needs to be held while write-locking |receive_crit_| or |send_crit_|. This // ensures that we have a consistent network state signalled to all senders // and receivers. - scoped_ptr network_enabled_crit_; + rtc::scoped_ptr network_enabled_crit_; bool network_enabled_ GUARDED_BY(network_enabled_crit_); - scoped_ptr receive_crit_; + rtc::scoped_ptr receive_crit_; std::map receive_ssrcs_ GUARDED_BY(receive_crit_); - scoped_ptr send_crit_; + rtc::scoped_ptr send_crit_; std::map send_ssrcs_ GUARDED_BY(send_crit_); - scoped_ptr overuse_observer_proxy_; + rtc::scoped_ptr overuse_observer_proxy_; VideoSendStream::RtpStateMap suspended_send_ssrcs_; VideoEngine* video_engine_; ViERTP_RTCP* rtp_rtcp_; ViECodec* codec_; + ViERender* render_; ViEBase* base_; + ViENetwork* network_; int base_channel_id_; + rtc::scoped_ptr external_render_; + DISALLOW_COPY_AND_ASSIGN(Call); }; } // namespace internal Call* Call::Create(const Call::Config& config) { - VideoEngine* video_engine = config.webrtc_config != NULL + VideoEngine* video_engine = config.webrtc_config != nullptr ? VideoEngine::Create(*config.webrtc_config) : VideoEngine::Create(); - assert(video_engine != NULL); + DCHECK(video_engine != nullptr); return new internal::Call(video_engine, config); } @@ -172,36 +182,65 @@ Call::Call(webrtc::VideoEngine* video_engine, const Call::Config& config) receive_crit_(RWLockWrapper::CreateRWLock()), send_crit_(RWLockWrapper::CreateRWLock()), video_engine_(video_engine), - base_channel_id_(-1) { - assert(video_engine != NULL); - assert(config.send_transport != NULL); + base_channel_id_(-1), + external_render_( + VideoRender::CreateVideoRender(42, nullptr, false, kRenderExternal)) { + DCHECK(video_engine != nullptr); + DCHECK(config.send_transport != nullptr); + + DCHECK_GE(config.bitrate_config.min_bitrate_bps, 0); + DCHECK_GE(config.bitrate_config.start_bitrate_bps, + config.bitrate_config.min_bitrate_bps); + if (config.bitrate_config.max_bitrate_bps != -1) { + DCHECK_GE(config.bitrate_config.max_bitrate_bps, + config.bitrate_config.start_bitrate_bps); + } if (config.overuse_callback) { overuse_observer_proxy_.reset( new CpuOveruseObserverProxy(config.overuse_callback)); } + render_ = ViERender::GetInterface(video_engine_); + DCHECK(render_ != nullptr); + + render_->RegisterVideoRenderModule(*external_render_.get()); + rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine_); - assert(rtp_rtcp_ != NULL); + DCHECK(rtp_rtcp_ != nullptr); codec_ = ViECodec::GetInterface(video_engine_); - assert(codec_ != NULL); + DCHECK(codec_ != nullptr); + + network_ = ViENetwork::GetInterface(video_engine_); // As a workaround for non-existing calls in the old API, create a base // channel used as default channel when creating send and receive streams. base_ = ViEBase::GetInterface(video_engine_); - assert(base_ != NULL); + DCHECK(base_ != nullptr); base_->CreateChannel(base_channel_id_); - assert(base_channel_id_ != -1); + DCHECK(base_channel_id_ != -1); + + network_->SetBitrateConfig(base_channel_id_, + config_.bitrate_config.min_bitrate_bps, + config_.bitrate_config.start_bitrate_bps, + config_.bitrate_config.max_bitrate_bps); } Call::~Call() { + CHECK_EQ(0u, send_ssrcs_.size()); + CHECK_EQ(0u, receive_ssrcs_.size()); base_->DeleteChannel(base_channel_id_); + + render_->DeRegisterVideoRenderModule(*external_render_.get()); + base_->Release(); + network_->Release(); codec_->Release(); + render_->Release(); rtp_rtcp_->Release(); - webrtc::VideoEngine::Delete(video_engine_); + CHECK(webrtc::VideoEngine::Delete(video_engine_)); } PacketReceiver* Call::Receiver() { return this; } @@ -209,26 +248,22 @@ PacketReceiver* Call::Receiver() { return this; } VideoSendStream* Call::CreateVideoSendStream( const VideoSendStream::Config& config, const VideoEncoderConfig& encoder_config) { - assert(config.rtp.ssrcs.size() > 0); + TRACE_EVENT0("webrtc", "Call::CreateVideoSendStream"); + LOG(LS_INFO) << "CreateVideoSendStream: " << config.ToString(); + DCHECK(!config.rtp.ssrcs.empty()); // TODO(mflodman): Base the start bitrate on a current bandwidth estimate, if // the call has already started. - VideoSendStream* send_stream = - new VideoSendStream(config_.send_transport, - overuse_observer_proxy_.get(), - video_engine_, - config, - encoder_config, - suspended_send_ssrcs_, - base_channel_id_, - config_.stream_start_bitrate_bps); + VideoSendStream* send_stream = new VideoSendStream( + config_.send_transport, overuse_observer_proxy_.get(), video_engine_, + config, encoder_config, suspended_send_ssrcs_, base_channel_id_); // This needs to be taken before send_crit_ as both locks need to be held // while changing network state. CriticalSectionScoped lock(network_enabled_crit_.get()); WriteLockScoped write_lock(*send_crit_); for (size_t i = 0; i < config.rtp.ssrcs.size(); ++i) { - assert(send_ssrcs_.find(config.rtp.ssrcs[i]) == send_ssrcs_.end()); + DCHECK(send_ssrcs_.find(config.rtp.ssrcs[i]) == send_ssrcs_.end()); send_ssrcs_[config.rtp.ssrcs[i]] = send_stream; } if (!network_enabled_) @@ -237,11 +272,12 @@ VideoSendStream* Call::CreateVideoSendStream( } void Call::DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) { - assert(send_stream != NULL); + TRACE_EVENT0("webrtc", "Call::DestroyVideoSendStream"); + DCHECK(send_stream != nullptr); send_stream->Stop(); - VideoSendStream* send_stream_impl = NULL; + VideoSendStream* send_stream_impl = nullptr; { WriteLockScoped write_lock(*send_crit_); std::map::iterator it = send_ssrcs_.begin(); @@ -254,6 +290,7 @@ void Call::DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) { } } } + CHECK(send_stream_impl != nullptr); VideoSendStream::RtpStateMap rtp_state = send_stream_impl->GetRtpStates(); @@ -263,12 +300,13 @@ void Call::DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) { suspended_send_ssrcs_[it->first] = it->second; } - assert(send_stream_impl != NULL); delete send_stream_impl; } VideoReceiveStream* Call::CreateVideoReceiveStream( const VideoReceiveStream::Config& config) { + TRACE_EVENT0("webrtc", "Call::CreateVideoReceiveStream"); + LOG(LS_INFO) << "CreateVideoReceiveStream: " << config.ToString(); VideoReceiveStream* receive_stream = new VideoReceiveStream(video_engine_, config, @@ -280,7 +318,7 @@ VideoReceiveStream* Call::CreateVideoReceiveStream( // while changing network state. CriticalSectionScoped lock(network_enabled_crit_.get()); WriteLockScoped write_lock(*receive_crit_); - assert(receive_ssrcs_.find(config.rtp.remote_ssrc) == receive_ssrcs_.end()); + DCHECK(receive_ssrcs_.find(config.rtp.remote_ssrc) == receive_ssrcs_.end()); receive_ssrcs_[config.rtp.remote_ssrc] = receive_stream; // TODO(pbos): Configure different RTX payloads per receive payload. VideoReceiveStream::Config::Rtp::RtxMap::const_iterator it = @@ -295,9 +333,10 @@ VideoReceiveStream* Call::CreateVideoReceiveStream( void Call::DestroyVideoReceiveStream( webrtc::VideoReceiveStream* receive_stream) { - assert(receive_stream != NULL); + TRACE_EVENT0("webrtc", "Call::DestroyVideoReceiveStream"); + DCHECK(receive_stream != nullptr); - VideoReceiveStream* receive_stream_impl = NULL; + VideoReceiveStream* receive_stream_impl = nullptr; { WriteLockScoped write_lock(*receive_crit_); // Remove all ssrcs pointing to a receive stream. As RTX retransmits on a @@ -306,8 +345,8 @@ void Call::DestroyVideoReceiveStream( receive_ssrcs_.begin(); while (it != receive_ssrcs_.end()) { if (it->second == static_cast(receive_stream)) { - assert(receive_stream_impl == NULL || - receive_stream_impl == it->second); + if (receive_stream_impl != nullptr) + DCHECK(receive_stream_impl == it->second); receive_stream_impl = it->second; receive_ssrcs_.erase(it++); } else { @@ -315,8 +354,7 @@ void Call::DestroyVideoReceiveStream( } } } - - assert(receive_stream_impl != NULL); + CHECK(receive_stream_impl != nullptr); delete receive_stream_impl; } @@ -337,11 +375,36 @@ Call::Stats Call::GetStats() const { ++it) { stats.pacer_delay_ms = std::max(it->second->GetPacerQueuingDelayMs(), stats.pacer_delay_ms); + int rtt_ms = it->second->GetRtt(); + if (rtt_ms > 0) + stats.rtt_ms = rtt_ms; } } return stats; } +void Call::SetBitrateConfig( + const webrtc::Call::Config::BitrateConfig& bitrate_config) { + TRACE_EVENT0("webrtc", "Call::SetBitrateConfig"); + DCHECK_GE(bitrate_config.min_bitrate_bps, 0); + if (bitrate_config.max_bitrate_bps != -1) + DCHECK_GT(bitrate_config.max_bitrate_bps, 0); + if (config_.bitrate_config.min_bitrate_bps == + bitrate_config.min_bitrate_bps && + (bitrate_config.start_bitrate_bps <= 0 || + config_.bitrate_config.start_bitrate_bps == + bitrate_config.start_bitrate_bps) && + config_.bitrate_config.max_bitrate_bps == + bitrate_config.max_bitrate_bps) { + // Nothing new to set, early abort to avoid encoder reconfigurations. + return; + } + config_.bitrate_config = bitrate_config; + network_->SetBitrateConfig(base_channel_id_, bitrate_config.min_bitrate_bps, + bitrate_config.start_bitrate_bps, + bitrate_config.max_bitrate_bps); +} + void Call::SignalNetworkState(NetworkState state) { // Take crit for entire function, it needs to be held while updating streams // to guarantee a consistent state across streams. @@ -404,8 +467,7 @@ PacketReceiver::DeliveryStatus Call::DeliverRtp(const uint8_t* packet, if (length < 12) return DELIVERY_PACKET_ERROR; - const uint8_t* ptr = &packet[8]; - uint32_t ssrc = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3]; + uint32_t ssrc = ByteReader::ReadBigEndian(&packet[8]); ReadLockScoped read_lock(*receive_crit_); std::map::iterator it = diff --git a/media/webrtc/trunk/webrtc/video/call_perf_tests.cc b/media/webrtc/trunk/webrtc/video/call_perf_tests.cc index 9194b088dc..182a83edce 100644 --- a/media/webrtc/trunk/webrtc/video/call_perf_tests.cc +++ b/media/webrtc/trunk/webrtc/video/call_perf_tests.cc @@ -7,14 +7,14 @@ * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ -#include - #include #include #include #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/checks.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/call.h" #include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h" @@ -22,7 +22,6 @@ #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/rtp_to_ntp.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/test/call_test.h" #include "webrtc/test/direct_transport.h" #include "webrtc/test/encoder_settings.h" @@ -47,6 +46,8 @@ class CallPerfTest : public test::CallTest { protected: void TestAudioVideoSync(bool fec); + void TestCpuOveruse(LoadObserver::Load tested_load, int encode_delay_ms); + void TestMinTransmitBitrate(bool pad_to_min_bitrate); void TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config, @@ -61,7 +62,7 @@ class SyncRtcpObserver : public test::RtpRtcpObserver { : test::RtpRtcpObserver(CallPerfTest::kLongTimeoutMs, config), crit_(CriticalSectionWrapper::CreateCriticalSection()) {} - virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtcp(const uint8_t* packet, size_t length) override { RTCPUtility::RTCPParserV2 parser(packet, length, true); EXPECT_TRUE(parser.IsValid()); @@ -113,7 +114,7 @@ class SyncRtcpObserver : public test::RtpRtcpObserver { ntp_rtp_pairs_.push_front(ntp_rtp_pair); } - const scoped_ptr crit_; + const rtc::scoped_ptr crit_; RtcpList ntp_rtp_pairs_ GUARDED_BY(crit_); }; @@ -135,8 +136,8 @@ class VideoRtcpAndSyncObserver : public SyncRtcpObserver, public VideoRenderer { creation_time_ms_(clock_->TimeInMilliseconds()), first_time_in_sync_(-1) {} - virtual void RenderFrame(const I420VideoFrame& video_frame, - int time_to_render_ms) OVERRIDE { + void RenderFrame(const I420VideoFrame& video_frame, + int time_to_render_ms) override { int64_t now_ms = clock_->TimeInMilliseconds(); uint32_t playout_timestamp = 0; if (voe_sync_->GetPlayoutTimestamp(voe_channel_, playout_timestamp) != 0) @@ -178,6 +179,8 @@ class VideoRtcpAndSyncObserver : public SyncRtcpObserver, public VideoRenderer { } } + bool IsTextureSupported() const override { return false; } + private: Clock* const clock_; int voe_channel_; @@ -194,15 +197,14 @@ void CallPerfTest::TestAudioVideoSync(bool fec) { : channel_(channel), voe_network_(voe_network), parser_(RtpHeaderParser::Create()) {} - virtual DeliveryStatus DeliverPacket(const uint8_t* packet, - size_t length) OVERRIDE { + DeliveryStatus DeliverPacket(const uint8_t* packet, + size_t length) override { int ret; - if (parser_->IsRtcp(packet, static_cast(length))) { - ret = voe_network_->ReceivedRTCPPacket( - channel_, packet, static_cast(length)); + if (parser_->IsRtcp(packet, length)) { + ret = voe_network_->ReceivedRTCPPacket(channel_, packet, length); } else { - ret = voe_network_->ReceivedRTPPacket( - channel_, packet, static_cast(length), PacketTime()); + ret = voe_network_->ReceivedRTPPacket(channel_, packet, length, + PacketTime()); } return ret == 0 ? DELIVERY_OK : DELIVERY_PACKET_ERROR; } @@ -210,7 +212,7 @@ void CallPerfTest::TestAudioVideoSync(bool fec) { private: int channel_; VoENetwork* voe_network_; - scoped_ptr parser_; + rtc::scoped_ptr parser_; }; VoiceEngine* voice_engine = VoiceEngine::Create(); @@ -223,7 +225,7 @@ void CallPerfTest::TestAudioVideoSync(bool fec) { ASSERT_STRNE("", audio_filename.c_str()); test::FakeAudioDevice fake_audio_device(Clock::GetRealTimeClock(), audio_filename); - EXPECT_EQ(0, voe_base->Init(&fake_audio_device, NULL)); + EXPECT_EQ(0, voe_base->Init(&fake_audio_device, nullptr)); int channel = voe_base->CreateChannel(); FakeNetworkPipe::Config net_config; @@ -327,13 +329,13 @@ void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config, start_time_ms_(start_time_ms), run_time_ms_(run_time_ms), creation_time_ms_(clock_->TimeInMilliseconds()), - capturer_(NULL), + capturer_(nullptr), rtp_start_timestamp_set_(false), rtp_start_timestamp_(0) {} private: - virtual void RenderFrame(const I420VideoFrame& video_frame, - int time_to_render_ms) OVERRIDE { + void RenderFrame(const I420VideoFrame& video_frame, + int time_to_render_ms) override { if (video_frame.ntp_time_ms() <= 0) { // Haven't got enough RTCP SR in order to calculate the capture ntp // time. @@ -371,6 +373,8 @@ void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config, EXPECT_TRUE(std::abs(time_offset_ms) < threshold_ms_); } + bool IsTextureSupported() const override { return false; } + virtual Action OnSendRtp(const uint8_t* packet, size_t length) { RTPHeader header; EXPECT_TRUE(parser_->Parse(packet, length, &header)); @@ -391,21 +395,20 @@ void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config, return SEND_PACKET; } - virtual void OnFrameGeneratorCapturerCreated( - test::FrameGeneratorCapturer* frame_generator_capturer) OVERRIDE { + void OnFrameGeneratorCapturerCreated( + test::FrameGeneratorCapturer* frame_generator_capturer) override { capturer_ = frame_generator_capturer; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { (*receive_configs)[0].renderer = this; // Enable the receiver side rtt calculation. (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for " "estimated capture NTP time to be " "within bounds."; @@ -449,31 +452,54 @@ TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkJitter) { TestCaptureNtpTime(net_config, kThresholdMs, kStartTimeMs, kRunTimeMs); } -TEST_F(CallPerfTest, RegisterCpuOveruseObserver) { - // Verifies that either a normal or overuse callback is triggered. +void CallPerfTest::TestCpuOveruse(LoadObserver::Load tested_load, + int encode_delay_ms) { class LoadObserver : public test::SendTest, public webrtc::LoadObserver { public: - LoadObserver() : SendTest(kLongTimeoutMs) {} + LoadObserver(LoadObserver::Load tested_load, int encode_delay_ms) + : SendTest(kLongTimeoutMs), + tested_load_(tested_load), + encoder_(Clock::GetRealTimeClock(), encode_delay_ms) {} - virtual void OnLoadUpdate(Load load) OVERRIDE { - observation_complete_->Set(); + void OnLoadUpdate(Load load) override { + if (load == tested_load_) + observation_complete_->Set(); } - virtual Call::Config GetSenderCallConfig() OVERRIDE { + Call::Config GetSenderCallConfig() override { Call::Config config(SendTransport()); config.overuse_callback = this; return config; } - virtual void PerformTest() OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { + send_config->encoder_settings.encoder = &encoder_; + } + + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out before receiving an overuse callback."; } - } test; + + LoadObserver::Load tested_load_; + test::DelayedEncoder encoder_; + } test(tested_load, encode_delay_ms); RunBaseTest(&test); } +TEST_F(CallPerfTest, ReceivesCpuUnderuse) { + const int kEncodeDelayMs = 2; + TestCpuOveruse(LoadObserver::kUnderuse, kEncodeDelayMs); +} + +TEST_F(CallPerfTest, ReceivesCpuOveruse) { + const int kEncodeDelayMs = 35; + TestCpuOveruse(LoadObserver::kOveruse, kEncodeDelayMs); +} + void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) { static const int kMaxEncodeBitrateKbps = 30; static const int kMinTransmitBitrateBps = 150000; @@ -484,24 +510,23 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) { public: explicit BitrateObserver(bool using_min_transmit_bitrate) : EndToEndTest(kLongTimeoutMs), - send_stream_(NULL), - send_transport_receiver_(NULL), + send_stream_(nullptr), + send_transport_receiver_(nullptr), pad_to_min_bitrate_(using_min_transmit_bitrate), num_bitrate_observations_in_range_(0) {} private: - virtual void SetReceivers(PacketReceiver* send_transport_receiver, - PacketReceiver* receive_transport_receiver) - OVERRIDE { + void SetReceivers(PacketReceiver* send_transport_receiver, + PacketReceiver* receive_transport_receiver) override { send_transport_receiver_ = send_transport_receiver; test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver); } - virtual DeliveryStatus DeliverPacket(const uint8_t* packet, - size_t length) OVERRIDE { + DeliveryStatus DeliverPacket(const uint8_t* packet, + size_t length) override { VideoSendStream::Stats stats = send_stream_->GetStats(); if (stats.substreams.size() > 0) { - assert(stats.substreams.size() == 1); + DCHECK_EQ(1u, stats.substreams.size()); int bitrate_kbps = stats.substreams.begin()->second.total_bitrate_bps / 1000; if (bitrate_kbps > 0) { @@ -533,24 +558,23 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) { return send_transport_receiver_->DeliverPacket(packet, length); } - virtual void OnStreamsCreated( + void OnStreamsCreated( VideoSendStream* send_stream, - const std::vector& receive_streams) OVERRIDE { + const std::vector& receive_streams) override { send_stream_ = send_stream; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { if (pad_to_min_bitrate_) { encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps; } else { - assert(encoder_config->min_transmit_bitrate_bps == 0); + DCHECK_EQ(0, encoder_config->min_transmit_bitrate_bps); } } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timeout while waiting for send-bitrate stats."; } @@ -584,9 +608,9 @@ TEST_F(CallPerfTest, KeepsHighBitrateWhenReconfiguringSender) { time_to_reconfigure_(webrtc::EventWrapper::Create()), encoder_inits_(0) {} - virtual int32_t InitEncode(const VideoCodec* config, - int32_t number_of_cores, - uint32_t max_payload_size) OVERRIDE { + int32_t InitEncode(const VideoCodec* config, + int32_t number_of_cores, + size_t max_payload_size) override { if (encoder_inits_ == 0) { EXPECT_EQ(kInitialBitrateKbps, config->startBitrate) << "Encoder not initialized at expected bitrate."; @@ -603,8 +627,8 @@ TEST_F(CallPerfTest, KeepsHighBitrateWhenReconfiguringSender) { return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size); } - virtual int32_t SetRates(uint32_t new_target_bitrate_kbps, - uint32_t framerate) OVERRIDE { + int32_t SetRates(uint32_t new_target_bitrate_kbps, + uint32_t framerate) override { last_set_bitrate_ = new_target_bitrate_kbps; if (encoder_inits_ == 1 && new_target_bitrate_kbps > kReconfigureThresholdKbps) { @@ -613,16 +637,15 @@ TEST_F(CallPerfTest, KeepsHighBitrateWhenReconfiguringSender) { return FakeEncoder::SetRates(new_target_bitrate_kbps, framerate); } - Call::Config GetSenderCallConfig() OVERRIDE { + Call::Config GetSenderCallConfig() override { Call::Config config = EndToEndTest::GetSenderCallConfig(); - config.stream_start_bitrate_bps = kInitialBitrateKbps * 1000; + config.bitrate_config.start_bitrate_bps = kInitialBitrateKbps * 1000; return config; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->encoder_settings.encoder = this; encoder_config->streams[0].min_bitrate_bps = 50000; encoder_config->streams[0].target_bitrate_bps = @@ -631,13 +654,13 @@ TEST_F(CallPerfTest, KeepsHighBitrateWhenReconfiguringSender) { encoder_config_ = *encoder_config; } - virtual void OnStreamsCreated( + void OnStreamsCreated( VideoSendStream* send_stream, - const std::vector& receive_streams) OVERRIDE { + const std::vector& receive_streams) override { send_stream_ = send_stream; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { ASSERT_EQ(kEventSignaled, time_to_reconfigure_->Wait(kDefaultTimeoutMs)) << "Timed out before receiving an initial high bitrate."; encoder_config_.streams[0].width *= 2; @@ -649,7 +672,7 @@ TEST_F(CallPerfTest, KeepsHighBitrateWhenReconfiguringSender) { } private: - scoped_ptr time_to_reconfigure_; + rtc::scoped_ptr time_to_reconfigure_; int encoder_inits_; uint32_t last_set_bitrate_; VideoSendStream* send_stream_; diff --git a/media/webrtc/trunk/webrtc/video/encoded_frame_callback_adapter.cc b/media/webrtc/trunk/webrtc/video/encoded_frame_callback_adapter.cc index f5eca7ce44..1261ad5123 100644 --- a/media/webrtc/trunk/webrtc/video/encoded_frame_callback_adapter.cc +++ b/media/webrtc/trunk/webrtc/video/encoded_frame_callback_adapter.cc @@ -10,6 +10,7 @@ #include "webrtc/video/encoded_frame_callback_adapter.h" +#include "webrtc/base/checks.h" #include "webrtc/modules/video_coding/main/source/encoded_frame.h" namespace webrtc { @@ -22,10 +23,10 @@ EncodedFrameCallbackAdapter::EncodedFrameCallbackAdapter( EncodedFrameCallbackAdapter::~EncodedFrameCallbackAdapter() {} int32_t EncodedFrameCallbackAdapter::Encoded( - EncodedImage& encodedImage, + const EncodedImage& encodedImage, const CodecSpecificInfo* codecSpecificInfo, const RTPFragmentationHeader* fragmentation) { - assert(observer_ != NULL); + DCHECK(observer_ != nullptr); FrameType frame_type = VCMEncodedFrame::ConvertFrameType(encodedImage._frameType); const EncodedFrame frame(encodedImage._buffer, diff --git a/media/webrtc/trunk/webrtc/video/encoded_frame_callback_adapter.h b/media/webrtc/trunk/webrtc/video/encoded_frame_callback_adapter.h index d3814797ad..b39a8e2167 100644 --- a/media/webrtc/trunk/webrtc/video/encoded_frame_callback_adapter.h +++ b/media/webrtc/trunk/webrtc/video/encoded_frame_callback_adapter.h @@ -22,7 +22,7 @@ class EncodedFrameCallbackAdapter : public EncodedImageCallback { explicit EncodedFrameCallbackAdapter(EncodedFrameObserver* observer); virtual ~EncodedFrameCallbackAdapter(); - virtual int32_t Encoded(EncodedImage& encodedImage, + virtual int32_t Encoded(const EncodedImage& encodedImage, const CodecSpecificInfo* codecSpecificInfo, const RTPFragmentationHeader* fragmentation); diff --git a/media/webrtc/trunk/webrtc/video/end_to_end_tests.cc b/media/webrtc/trunk/webrtc/video/end_to_end_tests.cc index 2b3c00f5f5..956e8219fa 100644 --- a/media/webrtc/trunk/webrtc/video/end_to_end_tests.cc +++ b/media/webrtc/trunk/webrtc/video/end_to_end_tests.cc @@ -7,8 +7,6 @@ * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ -#include - #include #include #include @@ -16,6 +14,8 @@ #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/checks.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/call.h" #include "webrtc/frame_callback.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" @@ -24,7 +24,7 @@ #include "webrtc/modules/video_coding/main/interface/video_coding_defines.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/event_wrapper.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/system_wrappers/interface/metrics.h" #include "webrtc/system_wrappers/interface/sleep.h" #include "webrtc/test/call_test.h" #include "webrtc/test/direct_transport.h" @@ -34,7 +34,9 @@ #include "webrtc/test/fake_encoder.h" #include "webrtc/test/frame_generator.h" #include "webrtc/test/frame_generator_capturer.h" +#include "webrtc/test/histogram.h" #include "webrtc/test/null_transport.h" +#include "webrtc/test/rtcp_packet_parser.h" #include "webrtc/test/rtp_rtcp_observer.h" #include "webrtc/test/testsupport/fileutils.h" #include "webrtc/test/testsupport/gtest_disable.h" @@ -51,19 +53,19 @@ class EndToEndTest : public test::CallTest { EndToEndTest() {} virtual ~EndToEndTest() { - EXPECT_EQ(NULL, send_stream_); + EXPECT_EQ(nullptr, send_stream_); EXPECT_TRUE(receive_streams_.empty()); } protected: class UnusedTransport : public newapi::Transport { private: - virtual bool SendRtp(const uint8_t* packet, size_t length) OVERRIDE { + bool SendRtp(const uint8_t* packet, size_t length) override { ADD_FAILURE() << "Unexpected RTP sent."; return false; } - virtual bool SendRtcp(const uint8_t* packet, size_t length) OVERRIDE { + bool SendRtcp(const uint8_t* packet, size_t length) override { ADD_FAILURE() << "Unexpected RTCP sent."; return false; } @@ -75,6 +77,7 @@ class EndToEndTest : public test::CallTest { void TestXrReceiverReferenceTimeReport(bool enable_rrtr); void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first); void TestRtpStatePreservation(bool use_rtx); + void TestReceivedFecPacketsNotNacked(const FakeNetworkPipe::Config& config); }; TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) { @@ -119,14 +122,16 @@ TEST_F(EndToEndTest, RendersSingleDelayedFrame) { public: Renderer() : event_(EventWrapper::Create()) {} - virtual void RenderFrame(const I420VideoFrame& video_frame, - int /*time_to_render_ms*/) OVERRIDE { + void RenderFrame(const I420VideoFrame& video_frame, + int /*time_to_render_ms*/) override { event_->Set(); } + bool IsTextureSupported() const override { return false; } + EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); } - scoped_ptr event_; + rtc::scoped_ptr event_; } renderer; class TestFrameCallback : public I420FrameCallback { @@ -136,12 +141,12 @@ TEST_F(EndToEndTest, RendersSingleDelayedFrame) { EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); } private: - virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE { + void FrameCallback(I420VideoFrame* frame) override { SleepMs(kDelayRenderCallbackMs); event_->Set(); } - scoped_ptr event_; + rtc::scoped_ptr event_; }; test::DirectTransport sender_transport, receiver_transport; @@ -164,9 +169,9 @@ TEST_F(EndToEndTest, RendersSingleDelayedFrame) { // Create frames that are smaller than the send width/height, this is done to // check that the callbacks are done after processing video. - scoped_ptr frame_generator( - test::FrameGenerator::Create(kWidth, kHeight)); - send_stream_->Input()->SwapFrame(frame_generator->NextFrame()); + rtc::scoped_ptr frame_generator( + test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight)); + send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame()); EXPECT_EQ(kEventSignaled, pre_render_callback.Wait()) << "Timed out while waiting for pre-render callback."; EXPECT_EQ(kEventSignaled, renderer.Wait()) @@ -185,14 +190,15 @@ TEST_F(EndToEndTest, TransmitsFirstFrame) { public: Renderer() : event_(EventWrapper::Create()) {} - virtual void RenderFrame(const I420VideoFrame& video_frame, - int /*time_to_render_ms*/) OVERRIDE { + void RenderFrame(const I420VideoFrame& video_frame, + int /*time_to_render_ms*/) override { event_->Set(); } + bool IsTextureSupported() const override { return false; } EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); } - scoped_ptr event_; + rtc::scoped_ptr event_; } renderer; test::DirectTransport sender_transport, receiver_transport; @@ -210,9 +216,10 @@ TEST_F(EndToEndTest, TransmitsFirstFrame) { CreateStreams(); Start(); - scoped_ptr frame_generator(test::FrameGenerator::Create( - encoder_config_.streams[0].width, encoder_config_.streams[0].height)); - send_stream_->Input()->SwapFrame(frame_generator->NextFrame()); + rtc::scoped_ptr frame_generator( + test::FrameGenerator::CreateChromaGenerator( + encoder_config_.streams[0].width, encoder_config_.streams[0].height)); + send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame()); EXPECT_EQ(kEventSignaled, renderer.Wait()) << "Timed out while waiting for the frame to render."; @@ -234,15 +241,14 @@ TEST_F(EndToEndTest, SendsAndReceivesVP9) { decoder_(VP9Decoder::Create()), frame_counter_(0) {} - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for enough frames to be decoded."; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->encoder_settings.encoder = encoder_.get(); send_config->encoder_settings.payload_name = "VP9"; send_config->encoder_settings.payload_type = VCM_VP9_PAYLOAD_TYPE; @@ -259,16 +265,18 @@ TEST_F(EndToEndTest, SendsAndReceivesVP9) { (*receive_configs)[0].decoders[0].decoder = decoder_.get(); } - virtual void RenderFrame(const I420VideoFrame& video_frame, - int time_to_render_ms) OVERRIDE { + void RenderFrame(const I420VideoFrame& video_frame, + int time_to_render_ms) override { const int kRequiredFrames = 500; if (++frame_counter_ == kRequiredFrames) observation_complete_->Set(); } + bool IsTextureSupported() const override { return false; } + private: - scoped_ptr encoder_; - scoped_ptr decoder_; + rtc::scoped_ptr encoder_; + rtc::scoped_ptr decoder_; int frame_counter_; } test; @@ -283,15 +291,16 @@ TEST_F(EndToEndTest, SendsAndReceivesH264) { fake_encoder_(Clock::GetRealTimeClock()), frame_counter_(0) {} - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for enough frames to be decoded."; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { + send_config->rtp.nack.rtp_history_ms = + (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs; send_config->encoder_settings.encoder = &fake_encoder_; send_config->encoder_settings.payload_name = "H264"; send_config->encoder_settings.payload_type = kFakeSendPayloadType; @@ -308,13 +317,15 @@ TEST_F(EndToEndTest, SendsAndReceivesH264) { (*receive_configs)[0].decoders[0].decoder = &fake_decoder_; } - virtual void RenderFrame(const I420VideoFrame& video_frame, - int time_to_render_ms) OVERRIDE { + void RenderFrame(const I420VideoFrame& video_frame, + int time_to_render_ms) override { const int kRequiredFrames = 500; if (++frame_counter_ == kRequiredFrames) observation_complete_->Set(); } + bool IsTextureSupported() const override { return false; } + private: test::FakeH264Decoder fake_decoder_; test::FakeH264Encoder fake_encoder_; @@ -329,8 +340,7 @@ TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) { public: SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {} - virtual Action OnReceiveRtcp(const uint8_t* packet, - size_t length) OVERRIDE { + Action OnReceiveRtcp(const uint8_t* packet, size_t length) override { RTCPUtility::RTCPParserV2 parser(packet, length, true); EXPECT_TRUE(parser.IsValid()); uint32_t ssrc = 0; @@ -344,7 +354,7 @@ TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) { return SEND_PACKET; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for a receiver RTCP packet to be sent."; } @@ -367,7 +377,7 @@ TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) { nacks_left_(kNumberOfNacksToObserve) {} private: - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { RTPHeader header; EXPECT_TRUE(rtp_parser_->Parse(packet, length, &header)); @@ -401,8 +411,7 @@ TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) { return SEND_PACKET; } - virtual Action OnReceiveRtcp(const uint8_t* packet, - size_t length) OVERRIDE { + Action OnReceiveRtcp(const uint8_t* packet, size_t length) override { RTCPUtility::RTCPParserV2 parser(packet, length, true); EXPECT_TRUE(parser.IsValid()); @@ -417,21 +426,20 @@ TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) { return SEND_PACKET; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out waiting for packets to be NACKed, retransmitted and " "rendered."; } - scoped_ptr rtp_parser_; + rtc::scoped_ptr rtp_parser_; std::set dropped_packets_; std::set retransmitted_packets_; uint64_t sent_rtp_packets_; @@ -442,18 +450,14 @@ TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) { RunBaseTest(&test); } -// TODO(pbos): Flaky, webrtc:3269 -TEST_F(EndToEndTest, DISABLED_CanReceiveFec) { +TEST_F(EndToEndTest, CanReceiveFec) { class FecRenderObserver : public test::EndToEndTest, public VideoRenderer { public: FecRenderObserver() - : EndToEndTest(kDefaultTimeoutMs), - state_(kFirstPacket), - protected_sequence_number_(0), - protected_frame_timestamp_(0) {} + : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {} private: - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE + Action OnSendRtp(const uint8_t* packet, size_t length) override EXCLUSIVE_LOCKS_REQUIRED(crit_) { RTPHeader header; EXPECT_TRUE(parser_->Parse(packet, length, &header)); @@ -464,6 +468,14 @@ TEST_F(EndToEndTest, DISABLED_CanReceiveFec) { if (encapsulated_payload_type != kFakeSendPayloadType) EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type); + if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) { + // Retransmitted packet, should not count. + protected_sequence_numbers_.erase(header.sequenceNumber); + EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u); + protected_timestamps_.erase(header.timestamp); + return SEND_PACKET; + } + switch (state_) { case kFirstPacket: state_ = kDropEveryOtherPacketUntilFec; @@ -478,43 +490,37 @@ TEST_F(EndToEndTest, DISABLED_CanReceiveFec) { break; case kDropNextMediaPacket: if (encapsulated_payload_type == kFakeSendPayloadType) { - protected_sequence_number_ = header.sequenceNumber; - protected_frame_timestamp_ = header.timestamp; - state_ = kProtectedPacketDropped; + protected_sequence_numbers_.insert(header.sequenceNumber); + protected_timestamps_.insert(header.timestamp); + state_ = kDropEveryOtherPacketUntilFec; return DROP_PACKET; } break; - case kProtectedPacketDropped: - EXPECT_NE(header.sequenceNumber, protected_sequence_number_) - << "Protected packet retransmitted. Should not happen with FEC."; - break; } return SEND_PACKET; } - virtual void RenderFrame(const I420VideoFrame& video_frame, - int time_to_render_ms) OVERRIDE { + void RenderFrame(const I420VideoFrame& video_frame, + int time_to_render_ms) override { CriticalSectionScoped lock(crit_.get()); - // Rendering frame with timestamp associated with dropped packet -> FEC + // Rendering frame with timestamp of packet that was dropped -> FEC // protection worked. - if (state_ == kProtectedPacketDropped && - video_frame.timestamp() == protected_frame_timestamp_) { + if (protected_timestamps_.count(video_frame.timestamp()) != 0) observation_complete_->Set(); - } } + bool IsTextureSupported() const override { return false; } + enum { kFirstPacket, kDropEveryOtherPacketUntilFec, kDropNextMediaPacket, - kProtectedPacketDropped, } state_; - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { // TODO(pbos): Run this test with combined NACK/FEC enabled as well. // int rtp_history_ms = 1000; // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms; @@ -527,19 +533,142 @@ TEST_F(EndToEndTest, DISABLED_CanReceiveFec) { (*receive_configs)[0].renderer = this; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) - << "Timed out while waiting for retransmitted NACKed frames to be " - "rendered again."; + << "Timed out waiting for dropped frames frames to be rendered."; } - uint32_t protected_sequence_number_ GUARDED_BY(crit_); - uint32_t protected_frame_timestamp_ GUARDED_BY(crit_); + std::set protected_sequence_numbers_ GUARDED_BY(crit_); + std::set protected_timestamps_ GUARDED_BY(crit_); } test; RunBaseTest(&test); } +// Flacky on all platforms. See webrtc:4328. +TEST_F(EndToEndTest, DISABLED_ReceivedFecPacketsNotNacked) { + // At low RTT (< kLowRttNackMs) -> NACK only, no FEC. + // Configure some network delay. + const int kNetworkDelayMs = 50; + FakeNetworkPipe::Config config; + config.queue_delay_ms = kNetworkDelayMs; + TestReceivedFecPacketsNotNacked(config); +} + +void EndToEndTest::TestReceivedFecPacketsNotNacked( + const FakeNetworkPipe::Config& config) { + class FecNackObserver : public test::EndToEndTest { + public: + explicit FecNackObserver(const FakeNetworkPipe::Config& config) + : EndToEndTest(kDefaultTimeoutMs, config), + state_(kFirstPacket), + fec_sequence_number_(0), + has_last_sequence_number_(false), + last_sequence_number_(0) {} + + private: + Action OnSendRtp(const uint8_t* packet, size_t length) override { + RTPHeader header; + EXPECT_TRUE(parser_->Parse(packet, length, &header)); + EXPECT_EQ(kRedPayloadType, header.payloadType); + + int encapsulated_payload_type = + static_cast(packet[header.headerLength]); + if (encapsulated_payload_type != kFakeSendPayloadType) + EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type); + + if (has_last_sequence_number_ && + !IsNewerSequenceNumber(header.sequenceNumber, + last_sequence_number_)) { + // Drop retransmitted packets. + return DROP_PACKET; + } + last_sequence_number_ = header.sequenceNumber; + has_last_sequence_number_ = true; + + bool fec_packet = encapsulated_payload_type == kUlpfecPayloadType; + switch (state_) { + case kFirstPacket: + state_ = kDropEveryOtherPacketUntilFec; + break; + case kDropEveryOtherPacketUntilFec: + if (fec_packet) { + state_ = kDropAllMediaPacketsUntilFec; + } else if (header.sequenceNumber % 2 == 0) { + return DROP_PACKET; + } + break; + case kDropAllMediaPacketsUntilFec: + if (!fec_packet) + return DROP_PACKET; + fec_sequence_number_ = header.sequenceNumber; + state_ = kVerifyFecPacketNotInNackList; + break; + case kVerifyFecPacketNotInNackList: + // Continue to drop packets. Make sure no frame can be decoded. + if (fec_packet || header.sequenceNumber % 2 == 0) + return DROP_PACKET; + break; + } + return SEND_PACKET; + } + + Action OnReceiveRtcp(const uint8_t* packet, size_t length) override { + if (state_ == kVerifyFecPacketNotInNackList) { + test::RtcpPacketParser rtcp_parser; + rtcp_parser.Parse(packet, length); + std::vector nacks = rtcp_parser.nack_item()->last_nack_list(); + if (!nacks.empty() && + IsNewerSequenceNumber(nacks.back(), fec_sequence_number_)) { + EXPECT_TRUE(std::find( + nacks.begin(), nacks.end(), fec_sequence_number_) == nacks.end()); + observation_complete_->Set(); + } + } + return SEND_PACKET; + } + + // TODO(holmer): Investigate why we don't send FEC packets when the bitrate + // is 10 kbps. + Call::Config GetSenderCallConfig() override { + Call::Config config(SendTransport()); + const int kMinBitrateBps = 30000; + config.bitrate_config.min_bitrate_bps = kMinBitrateBps; + return config; + } + + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { + // Configure hybrid NACK/FEC. + send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; + send_config->rtp.fec.red_payload_type = kRedPayloadType; + send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; + (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs; + (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType; + (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; + } + + void PerformTest() override { + EXPECT_EQ(kEventSignaled, Wait()) + << "Timed out while waiting for FEC packets to be received."; + } + + enum { + kFirstPacket, + kDropEveryOtherPacketUntilFec, + kDropAllMediaPacketsUntilFec, + kVerifyFecPacketNotInNackList, + } state_; + + uint16_t fec_sequence_number_; + bool has_last_sequence_number_; + uint16_t last_sequence_number_; + } test(config); + + RunBaseTest(&test); +} + // This test drops second RTP packet with a marker bit set, makes sure it's // retransmitted and renders. Retransmission SSRCs are also checked. void EndToEndTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) { @@ -557,7 +686,7 @@ void EndToEndTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) { frame_retransmitted_(false) {} private: - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { RTPHeader header; EXPECT_TRUE(parser_->Parse(packet, length, &header)); @@ -581,7 +710,7 @@ void EndToEndTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) { return SEND_PACKET; } - virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE { + void FrameCallback(I420VideoFrame* frame) override { CriticalSectionScoped lock(crit_.get()); if (frame->timestamp() == retransmitted_timestamp_) { EXPECT_TRUE(frame_retransmitted_); @@ -589,10 +718,9 @@ void EndToEndTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) { } } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; (*receive_configs)[0].pre_render_callback = this; (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs; @@ -606,7 +734,7 @@ void EndToEndTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) { } } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for retransmission to render."; } @@ -637,16 +765,18 @@ TEST_F(EndToEndTest, UsesFrameCallbacks) { public: Renderer() : event_(EventWrapper::Create()) {} - virtual void RenderFrame(const I420VideoFrame& video_frame, - int /*time_to_render_ms*/) OVERRIDE { + void RenderFrame(const I420VideoFrame& video_frame, + int /*time_to_render_ms*/) override { EXPECT_EQ(0, *video_frame.buffer(kYPlane)) << "Rendered frame should have zero luma which is applied by the " "pre-render callback."; event_->Set(); } + bool IsTextureSupported() const override { return false; } + EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); } - scoped_ptr event_; + rtc::scoped_ptr event_; } renderer; class TestFrameCallback : public I420FrameCallback { @@ -677,7 +807,7 @@ TEST_F(EndToEndTest, UsesFrameCallbacks) { event_->Set(); } - scoped_ptr event_; + rtc::scoped_ptr event_; int expected_luma_byte_; int next_luma_byte_; }; @@ -694,7 +824,7 @@ TEST_F(EndToEndTest, UsesFrameCallbacks) { receiver_transport.SetReceiver(sender_call_->Receiver()); CreateSendConfig(1); - scoped_ptr encoder( + rtc::scoped_ptr encoder( VideoEncoder::Create(VideoEncoder::kVp8)); send_config_.encoder_settings.encoder = encoder.get(); send_config_.encoder_settings.payload_name = "VP8"; @@ -712,9 +842,9 @@ TEST_F(EndToEndTest, UsesFrameCallbacks) { // Create frames that are smaller than the send width/height, this is done to // check that the callbacks are done after processing video. - scoped_ptr frame_generator( - test::FrameGenerator::Create(kWidth / 2, kHeight / 2)); - send_stream_->Input()->SwapFrame(frame_generator->NextFrame()); + rtc::scoped_ptr frame_generator( + test::FrameGenerator::CreateChromaGenerator(kWidth / 2, kHeight / 2)); + send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame()); EXPECT_EQ(kEventSignaled, pre_encode_callback.Wait()) << "Timed out while waiting for pre-encode callback."; @@ -745,7 +875,7 @@ void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) { received_pli_(false) {} private: - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { RTPHeader header; EXPECT_TRUE(parser_->Parse(packet, length, &header)); @@ -762,8 +892,7 @@ void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) { return SEND_PACKET; } - virtual Action OnReceiveRtcp(const uint8_t* packet, - size_t length) OVERRIDE { + Action OnReceiveRtcp(const uint8_t* packet, size_t length) override { RTCPUtility::RTCPParserV2 parser(packet, length, true); EXPECT_TRUE(parser.IsValid()); @@ -781,8 +910,8 @@ void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) { return SEND_PACKET; } - virtual void RenderFrame(const I420VideoFrame& video_frame, - int time_to_render_ms) OVERRIDE { + void RenderFrame(const I420VideoFrame& video_frame, + int time_to_render_ms) override { CriticalSectionScoped lock(crit_.get()); if (received_pli_ && video_frame.timestamp() > highest_dropped_timestamp_) { @@ -792,16 +921,17 @@ void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) { frames_to_drop_ = kPacketsToDrop; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + bool IsTextureSupported() const override { return false; } + + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->rtp.nack.rtp_history_ms = rtp_history_ms_; (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_; (*receive_configs)[0].renderer = this; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out waiting for PLI to be " "received and a frame to be " "rendered afterwards."; @@ -837,8 +967,8 @@ TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) { } private: - virtual DeliveryStatus DeliverPacket(const uint8_t* packet, - size_t length) OVERRIDE { + DeliveryStatus DeliverPacket(const uint8_t* packet, + size_t length) override { if (RtpHeaderParser::IsRtcp(packet, length)) { return receiver_->DeliverPacket(packet, length); } else { @@ -851,7 +981,7 @@ TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) { } PacketReceiver* receiver_; - scoped_ptr delivered_packet_; + rtc::scoped_ptr delivered_packet_; }; test::DirectTransport send_transport, receive_transport; @@ -894,15 +1024,14 @@ void EndToEndTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) { sent_rtcp_(0) {} private: - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { if (++sent_rtp_ % 3 == 0) return DROP_PACKET; return SEND_PACKET; } - virtual Action OnReceiveRtcp(const uint8_t* packet, - size_t length) OVERRIDE { + Action OnReceiveRtcp(const uint8_t* packet, size_t length) override { ++sent_rtcp_; RTCPUtility::RTCPParserV2 parser(packet, length, true); EXPECT_TRUE(parser.IsValid()); @@ -939,16 +1068,15 @@ void EndToEndTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) { return SEND_PACKET; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs; (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << (rtcp_mode_ == newapi::kRtcpCompound ? "Timed out before observing enough compound packets." @@ -988,21 +1116,23 @@ TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) { height_(height), done_(EventWrapper::Create()) {} - virtual void RenderFrame(const I420VideoFrame& video_frame, - int time_to_render_ms) OVERRIDE { + void RenderFrame(const I420VideoFrame& video_frame, + int time_to_render_ms) override { EXPECT_EQ(width_, video_frame.width()); EXPECT_EQ(height_, video_frame.height()); (*capturer_)->Stop(); done_->Set(); } + bool IsTextureSupported() const override { return false; } + EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); } private: test::FrameGeneratorCapturer** capturer_; int width_; int height_; - scoped_ptr done_; + rtc::scoped_ptr done_; }; struct { @@ -1012,8 +1142,9 @@ TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) { } codec_settings[kNumStreams] = {{1, 640, 480}, {2, 320, 240}, {3, 240, 160}}; test::DirectTransport sender_transport, receiver_transport; - scoped_ptr sender_call(Call::Create(Call::Config(&sender_transport))); - scoped_ptr receiver_call( + rtc::scoped_ptr sender_call( + Call::Create(Call::Config(&sender_transport))); + rtc::scoped_ptr receiver_call( Call::Create(Call::Config(&receiver_transport))); sender_transport.SetReceiver(receiver_call->Receiver()); receiver_transport.SetReceiver(sender_call->Receiver()); @@ -1024,7 +1155,7 @@ TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) { VideoOutputObserver* observers[kNumStreams]; test::FrameGeneratorCapturer* frame_generators[kNumStreams]; - scoped_ptr encoders[kNumStreams]; + rtc::scoped_ptr encoders[kNumStreams]; for (size_t i = 0; i < kNumStreams; ++i) encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8)); @@ -1115,10 +1246,10 @@ TEST_F(EndToEndTest, ObserversEncodedFrames) { } private: - scoped_ptr buffer_; + rtc::scoped_ptr buffer_; size_t length_; FrameType frame_type_; - scoped_ptr called_; + rtc::scoped_ptr called_; }; EncodedFrameTestObserver post_encode_observer; @@ -1140,9 +1271,10 @@ TEST_F(EndToEndTest, ObserversEncodedFrames) { CreateStreams(); Start(); - scoped_ptr frame_generator(test::FrameGenerator::Create( - encoder_config_.streams[0].width, encoder_config_.streams[0].height)); - send_stream_->Input()->SwapFrame(frame_generator->NextFrame()); + rtc::scoped_ptr frame_generator( + test::FrameGenerator::CreateChromaGenerator( + encoder_config_.streams[0].width, encoder_config_.streams[0].height)); + send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame()); EXPECT_EQ(kEventSignaled, post_encode_observer.Wait()) << "Timed out while waiting for send-side encoded-frame callback."; @@ -1165,8 +1297,7 @@ TEST_F(EndToEndTest, ReceiveStreamSendsRemb) { public: RembObserver() : EndToEndTest(kDefaultTimeoutMs) {} - virtual Action OnReceiveRtcp(const uint8_t* packet, - size_t length) OVERRIDE { + Action OnReceiveRtcp(const uint8_t* packet, size_t length) override { RTCPUtility::RTCPParserV2 parser(packet, length, true); EXPECT_TRUE(parser.IsValid()); @@ -1191,7 +1322,7 @@ TEST_F(EndToEndTest, ReceiveStreamSendsRemb) { observation_complete_->Set(); return SEND_PACKET; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for a " "receiver RTCP REMB packet to be " "sent."; @@ -1206,36 +1337,35 @@ TEST_F(EndToEndTest, VerifyBandwidthStats) { public: RtcpObserver() : EndToEndTest(kDefaultTimeoutMs), - sender_call_(NULL), - receiver_call_(NULL), + sender_call_(nullptr), + receiver_call_(nullptr), has_seen_pacer_delay_(false) {} - virtual DeliveryStatus DeliverPacket(const uint8_t* packet, - size_t length) OVERRIDE { + DeliveryStatus DeliverPacket(const uint8_t* packet, + size_t length) override { Call::Stats sender_stats = sender_call_->GetStats(); Call::Stats receiver_stats = receiver_call_->GetStats(); if (!has_seen_pacer_delay_) has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0; if (sender_stats.send_bandwidth_bps > 0 && - receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) + receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) { observation_complete_->Set(); + } return receiver_call_->Receiver()->DeliverPacket(packet, length); } - virtual void OnCallsCreated(Call* sender_call, - Call* receiver_call) OVERRIDE { + void OnCallsCreated(Call* sender_call, Call* receiver_call) override { sender_call_ = sender_call; receiver_call_ = receiver_call; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for " "non-zero bandwidth stats."; } - virtual void SetReceivers( - PacketReceiver* send_transport_receiver, - PacketReceiver* receive_transport_receiver) OVERRIDE { + void SetReceivers(PacketReceiver* send_transport_receiver, + PacketReceiver* receive_transport_receiver) override { test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver); } @@ -1248,6 +1378,115 @@ TEST_F(EndToEndTest, VerifyBandwidthStats) { RunBaseTest(&test); } +TEST_F(EndToEndTest, VerifyNackStats) { + static const int kPacketNumberToDrop = 200; + class NackObserver : public test::EndToEndTest { + public: + NackObserver() + : EndToEndTest(kLongTimeoutMs), + sent_rtp_packets_(0), + dropped_rtp_packet_(0), + dropped_rtp_packet_requested_(false), + send_stream_(nullptr), + start_runtime_ms_(-1) {} + + private: + Action OnSendRtp(const uint8_t* packet, size_t length) override { + if (++sent_rtp_packets_ == kPacketNumberToDrop) { + rtc::scoped_ptr parser(RtpHeaderParser::Create()); + RTPHeader header; + EXPECT_TRUE(parser->Parse(packet, length, &header)); + dropped_rtp_packet_ = header.sequenceNumber; + return DROP_PACKET; + } + VerifyStats(); + return SEND_PACKET; + } + + Action OnReceiveRtcp(const uint8_t* packet, size_t length) override { + test::RtcpPacketParser rtcp_parser; + rtcp_parser.Parse(packet, length); + std::vector nacks = rtcp_parser.nack_item()->last_nack_list(); + if (!nacks.empty() && std::find( + nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) { + dropped_rtp_packet_requested_ = true; + } + return SEND_PACKET; + } + + void VerifyStats() { + if (!dropped_rtp_packet_requested_) + return; + int send_stream_nack_packets = 0; + int receive_stream_nack_packets = 0; + VideoSendStream::Stats stats = send_stream_->GetStats(); + for (std::map::const_iterator it = + stats.substreams.begin(); it != stats.substreams.end(); ++it) { + const VideoSendStream::StreamStats& stream_stats = it->second; + send_stream_nack_packets += + stream_stats.rtcp_packet_type_counts.nack_packets; + } + for (size_t i = 0; i < receive_streams_.size(); ++i) { + VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats(); + receive_stream_nack_packets += + stats.rtcp_packet_type_counts.nack_packets; + } + if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) { + // NACK packet sent on receive stream and received on sent stream. + if (MinMetricRunTimePassed()) + observation_complete_->Set(); + } + } + + bool MinMetricRunTimePassed() { + int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds(); + if (start_runtime_ms_ == -1) { + start_runtime_ms_ = now; + return false; + } + int64_t elapsed_sec = (now - start_runtime_ms_) / 1000; + return elapsed_sec > metrics::kMinRunTimeInSeconds; + } + + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { + send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; + (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs; + } + + void OnStreamsCreated( + VideoSendStream* send_stream, + const std::vector& receive_streams) override { + send_stream_ = send_stream; + receive_streams_ = receive_streams; + } + + void PerformTest() override { + EXPECT_EQ(kEventSignaled, Wait()) + << "Timed out waiting for packet to be NACKed."; + } + + uint64_t sent_rtp_packets_; + uint16_t dropped_rtp_packet_; + bool dropped_rtp_packet_requested_; + std::vector receive_streams_; + VideoSendStream* send_stream_; + int64_t start_runtime_ms_; + } test; + + RunBaseTest(&test); + + EXPECT_NE(-1, test::LastHistogramSample( + "WebRTC.Video.UniqueNackRequestsSentInPercent")); + EXPECT_NE(-1, test::LastHistogramSample( + "WebRTC.Video.UniqueNackRequestsReceivedInPercent")); + EXPECT_GT(test::LastHistogramSample( + "WebRTC.Video.NackPacketsSentPerMinute"), 0); + EXPECT_GT(test::LastHistogramSample( + "WebRTC.Video.NackPacketsReceivedPerMinute"), 0); +} + void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) { static const int kNumRtcpReportPacketsToObserve = 5; class RtcpXrObserver : public test::EndToEndTest { @@ -1262,8 +1501,7 @@ void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) { private: // Receive stream should send RR packets (and RRTR packets if enabled). - virtual Action OnReceiveRtcp(const uint8_t* packet, - size_t length) OVERRIDE { + Action OnReceiveRtcp(const uint8_t* packet, size_t length) override { RTCPUtility::RTCPParserV2 parser(packet, length, true); EXPECT_TRUE(parser.IsValid()); @@ -1310,16 +1548,15 @@ void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) { return SEND_PACKET; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { (*receive_configs)[0].rtp.rtcp_mode = newapi::kRtcpReducedSize; (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = enable_rrtr_; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for RTCP SR/RR packets to be sent."; } @@ -1351,7 +1588,7 @@ void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs, } private: - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { RTPHeader header; EXPECT_TRUE(parser_->Parse(packet, length, &header)); @@ -1376,12 +1613,11 @@ void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs, return SEND_PACKET; } - virtual size_t GetNumStreams() const OVERRIDE { return num_ssrcs_; } + size_t GetNumStreams() const override { return num_ssrcs_; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { if (num_ssrcs_ > 1) { // Set low simulcast bitrates to not have to wait for bandwidth ramp-up. for (size_t i = 0; i < encoder_config->streams.size(); ++i) { @@ -1396,13 +1632,13 @@ void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs, encoder_config->streams.resize(1); } - virtual void OnStreamsCreated( + void OnStreamsCreated( VideoSendStream* send_stream, - const std::vector& receive_streams) OVERRIDE { + const std::vector& receive_streams) override { send_stream_ = send_stream; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for " << (send_single_ssrc_first_ ? "first SSRC." : "SSRCs."); @@ -1432,40 +1668,95 @@ void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs, RunBaseTest(&test); } +TEST_F(EndToEndTest, ReportsSetEncoderRates) { + class EncoderRateStatsTest : public test::EndToEndTest, + public test::FakeEncoder { + public: + EncoderRateStatsTest() + : EndToEndTest(kDefaultTimeoutMs), + FakeEncoder(Clock::GetRealTimeClock()) {} + + void OnStreamsCreated( + VideoSendStream* send_stream, + const std::vector& receive_streams) override { + send_stream_ = send_stream; + } + + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { + send_config->encoder_settings.encoder = this; + } + + int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override { + // Make sure not to trigger on any default zero bitrates. + if (new_target_bitrate == 0) + return 0; + CriticalSectionScoped lock(crit_.get()); + bitrate_kbps_ = new_target_bitrate; + observation_complete_->Set(); + return 0; + } + + void PerformTest() override { + ASSERT_EQ(kEventSignaled, Wait()) + << "Timed out while waiting for encoder SetRates() call."; + // Wait for GetStats to report a corresponding bitrate. + for (unsigned int i = 0; i < kDefaultTimeoutMs; ++i) { + VideoSendStream::Stats stats = send_stream_->GetStats(); + { + CriticalSectionScoped lock(crit_.get()); + if ((stats.target_media_bitrate_bps + 500) / 1000 == + static_cast(bitrate_kbps_)) { + return; + } + } + SleepMs(1); + } + FAIL() + << "Timed out waiting for stats reporting the currently set bitrate."; + } + + private: + VideoSendStream* send_stream_; + uint32_t bitrate_kbps_ GUARDED_BY(crit_); + } test; + + RunBaseTest(&test); +} + TEST_F(EndToEndTest, GetStats) { + static const int kStartBitrateBps = 3000000; class StatsObserver : public test::EndToEndTest, public I420FrameCallback { public: - StatsObserver() - : EndToEndTest(kLongTimeoutMs), - receive_stream_(NULL), - send_stream_(NULL), - expected_receive_ssrc_(), + explicit StatsObserver(const FakeNetworkPipe::Config& config) + : EndToEndTest(kLongTimeoutMs, config), + send_stream_(nullptr), expected_send_ssrcs_(), check_stats_event_(EventWrapper::Create()) {} private: - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { check_stats_event_->Set(); return SEND_PACKET; } - virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtcp(const uint8_t* packet, size_t length) override { check_stats_event_->Set(); return SEND_PACKET; } - virtual Action OnReceiveRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnReceiveRtp(const uint8_t* packet, size_t length) override { check_stats_event_->Set(); return SEND_PACKET; } - virtual Action OnReceiveRtcp(const uint8_t* packet, - size_t length) OVERRIDE { + Action OnReceiveRtcp(const uint8_t* packet, size_t length) override { check_stats_event_->Set(); return SEND_PACKET; } - virtual void FrameCallback(I420VideoFrame* video_frame) OVERRIDE { + void FrameCallback(I420VideoFrame* video_frame) override { // Ensure that we have at least 5ms send side delay. int64_t render_time = video_frame->render_time_ms(); if (render_time > 0) @@ -1473,55 +1764,73 @@ TEST_F(EndToEndTest, GetStats) { } bool CheckReceiveStats() { - assert(receive_stream_ != NULL); - VideoReceiveStream::Stats stats = receive_stream_->GetStats(); - EXPECT_EQ(expected_receive_ssrc_, stats.ssrc); + for (size_t i = 0; i < receive_streams_.size(); ++i) { + VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats(); + EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc); - // Make sure all fields have been populated. + // Make sure all fields have been populated. + // TODO(pbos): Use CompoundKey if/when we ever know that all stats are + // always filled for all receivers. + receive_stats_filled_["IncomingRate"] |= + stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0; - receive_stats_filled_["IncomingRate"] |= - stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0; + receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0; - receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0; + receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0; - receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0; + receive_stats_filled_["StatisticsUpdated"] |= + stats.rtcp_stats.cumulative_lost != 0 || + stats.rtcp_stats.extended_max_sequence_number != 0 || + stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0; - receive_stats_filled_["StatisticsUpdated"] |= - stats.rtcp_stats.cumulative_lost != 0 || - stats.rtcp_stats.extended_max_sequence_number != 0 || - stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0; + receive_stats_filled_["DataCountersUpdated"] |= + stats.rtp_stats.transmitted.payload_bytes != 0 || + stats.rtp_stats.fec.packets != 0 || + stats.rtp_stats.transmitted.header_bytes != 0 || + stats.rtp_stats.transmitted.packets != 0 || + stats.rtp_stats.transmitted.padding_bytes != 0 || + stats.rtp_stats.retransmitted.packets != 0; - receive_stats_filled_["DataCountersUpdated"] |= - stats.rtp_stats.bytes != 0 || stats.rtp_stats.fec_packets != 0 || - stats.rtp_stats.header_bytes != 0 || stats.rtp_stats.packets != 0 || - stats.rtp_stats.padding_bytes != 0 || - stats.rtp_stats.retransmitted_packets != 0; + receive_stats_filled_["CodecStats"] |= + stats.target_delay_ms != 0 || stats.discarded_packets != 0; - receive_stats_filled_["CodecStats"] |= - stats.avg_delay_ms != 0 || stats.discarded_packets != 0 || - stats.key_frames != 0 || stats.delta_frames != 0; + receive_stats_filled_["FrameCounts"] |= + stats.frame_counts.key_frames != 0 || + stats.frame_counts.delta_frames != 0; + + receive_stats_filled_["CName"] |= stats.c_name != ""; + + receive_stats_filled_["RtcpPacketTypeCount"] |= + stats.rtcp_packet_type_counts.fir_packets != 0 || + stats.rtcp_packet_type_counts.nack_packets != 0 || + stats.rtcp_packet_type_counts.pli_packets != 0 || + stats.rtcp_packet_type_counts.nack_requests != 0 || + stats.rtcp_packet_type_counts.unique_nack_requests != 0; + } return AllStatsFilled(receive_stats_filled_); } bool CheckSendStats() { - assert(send_stream_ != NULL); + DCHECK(send_stream_ != nullptr); VideoSendStream::Stats stats = send_stream_->GetStats(); send_stats_filled_["NumStreams"] |= stats.substreams.size() == expected_send_ssrcs_.size(); - for (std::map::const_iterator it = + send_stats_filled_["CpuOveruseMetrics"] |= + stats.avg_encode_time_ms != 0 || stats.encode_usage_percent != 0; + + for (std::map::const_iterator it = stats.substreams.begin(); - it != stats.substreams.end(); - ++it) { + it != stats.substreams.end(); ++it) { EXPECT_TRUE(expected_send_ssrcs_.find(it->first) != expected_send_ssrcs_.end()); - send_stats_filled_[CompoundKey("IncomingRate", it->first)] |= + send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |= stats.input_frame_rate != 0; - const SsrcStats& stream_stats = it->second; + const VideoSendStream::StreamStats& stream_stats = it->second; send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |= stream_stats.rtcp_stats.cumulative_lost != 0 || @@ -1529,23 +1838,33 @@ TEST_F(EndToEndTest, GetStats) { stream_stats.rtcp_stats.fraction_lost != 0; send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |= - stream_stats.rtp_stats.fec_packets != 0 || - stream_stats.rtp_stats.padding_bytes != 0 || - stream_stats.rtp_stats.retransmitted_packets != 0 || - stream_stats.rtp_stats.packets != 0; + stream_stats.rtp_stats.fec.packets != 0 || + stream_stats.rtp_stats.transmitted.padding_bytes != 0 || + stream_stats.rtp_stats.retransmitted.packets != 0 || + stream_stats.rtp_stats.transmitted.packets != 0; send_stats_filled_[CompoundKey("BitrateStatisticsObserver", it->first)] |= stream_stats.total_bitrate_bps != 0; send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |= - stream_stats.delta_frames != 0 || stream_stats.key_frames != 0; + stream_stats.frame_counts.delta_frames != 0 || + stream_stats.frame_counts.key_frames != 0; send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |= stats.encode_frame_rate != 0; send_stats_filled_[CompoundKey("Delay", it->first)] |= stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0; + + // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs + // report dropped packets. + send_stats_filled_["RtcpPacketTypeCount"] |= + stream_stats.rtcp_packet_type_counts.fir_packets != 0 || + stream_stats.rtcp_packet_type_counts.nack_packets != 0 || + stream_stats.rtcp_packet_type_counts.pli_packets != 0 || + stream_stats.rtcp_packet_type_counts.nack_requests != 0 || + stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0; } return AllStatsFilled(send_stats_filled_); @@ -1567,29 +1886,36 @@ TEST_F(EndToEndTest, GetStats) { return true; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + Call::Config GetSenderCallConfig() override { + Call::Config config = EndToEndTest::GetSenderCallConfig(); + config.bitrate_config.start_bitrate_bps = kStartBitrateBps; + return config; + } + + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->pre_encode_callback = this; // Used to inject delay. - send_config->rtp.c_name = "SomeCName"; + expected_cname_ = send_config->rtp.c_name = "SomeCName"; - expected_receive_ssrc_ = (*receive_configs)[0].rtp.local_ssrc; const std::vector& ssrcs = send_config->rtp.ssrcs; - for (size_t i = 0; i < ssrcs.size(); ++i) + for (size_t i = 0; i < ssrcs.size(); ++i) { expected_send_ssrcs_.insert(ssrcs[i]); - - expected_cname_ = send_config->rtp.c_name; + expected_receive_ssrcs_.push_back( + (*receive_configs)[i].rtp.remote_ssrc); + } } - virtual void OnStreamsCreated( + size_t GetNumStreams() const override { return kNumSsrcs; } + + void OnStreamsCreated( VideoSendStream* send_stream, - const std::vector& receive_streams) OVERRIDE { + const std::vector& receive_streams) override { send_stream_ = send_stream; - receive_stream_ = receive_streams[0]; + receive_streams_ = receive_streams; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { Clock* clock = Clock::GetRealTimeClock(); int64_t now = clock->TimeInMilliseconds(); int64_t stop_time = now + test::CallTest::kLongTimeoutMs; @@ -1631,19 +1957,23 @@ TEST_F(EndToEndTest, GetStats) { } } - VideoReceiveStream* receive_stream_; + std::vector receive_streams_; std::map receive_stats_filled_; VideoSendStream* send_stream_; std::map send_stats_filled_; - uint32_t expected_receive_ssrc_; + std::vector expected_receive_ssrcs_; std::set expected_send_ssrcs_; std::string expected_cname_; - scoped_ptr check_stats_event_; - } test; + rtc::scoped_ptr check_stats_event_; + }; + FakeNetworkPipe::Config network_config; + network_config.loss_percent = 5; + + StatsObserver test(network_config); RunBaseTest(&test); } @@ -1661,20 +1991,20 @@ TEST_F(EndToEndTest, TestReceivedRtpPacketStats) { public: ReceivedRtpStatsObserver() : EndToEndTest(kDefaultTimeoutMs), - receive_stream_(NULL), + receive_stream_(nullptr), sent_rtp_(0) {} private: - virtual void OnStreamsCreated( + void OnStreamsCreated( VideoSendStream* send_stream, - const std::vector& receive_streams) OVERRIDE { + const std::vector& receive_streams) override { receive_stream_ = receive_streams[0]; } - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { if (sent_rtp_ >= kNumRtpPacketsToSend) { VideoReceiveStream::Stats stats = receive_stream_->GetStats(); - if (kNumRtpPacketsToSend == stats.rtp_stats.packets) { + if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) { observation_complete_->Set(); } return DROP_PACKET; @@ -1683,7 +2013,7 @@ TEST_F(EndToEndTest, TestReceivedRtpPacketStats) { return SEND_PACKET; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while verifying number of received RTP packets."; } @@ -1716,18 +2046,16 @@ TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) { } private: - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { RTPHeader header; EXPECT_TRUE(parser_->Parse(packet, length, &header)); if (!registered_rtx_ssrc_[header.ssrc]) return SEND_PACKET; - EXPECT_LE(static_cast(header.headerLength + header.paddingLength), - length); + EXPECT_LE(header.headerLength + header.paddingLength, length); const bool packet_is_redundant_payload = - static_cast(header.headerLength + header.paddingLength) < - length; + header.headerLength + header.paddingLength < length; if (!packet_is_redundant_payload) return SEND_PACKET; @@ -1741,12 +2069,11 @@ TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) { return SEND_PACKET; } - virtual size_t GetNumStreams() const OVERRIDE { return kNumSsrcs; } + size_t GetNumStreams() const override { return kNumSsrcs; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { // Set low simulcast bitrates to not have to wait for bandwidth ramp-up. for (size_t i = 0; i < encoder_config->streams.size(); ++i) { encoder_config->streams[i].min_bitrate_bps = 10000; @@ -1755,7 +2082,6 @@ TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) { } send_config->rtp.rtx.payload_type = kSendRtxPayloadType; - send_config->rtp.rtx.pad_with_redundant_payloads = true; for (size_t i = 0; i < kNumSsrcs; ++i) send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]); @@ -1765,7 +2091,7 @@ TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) { encoder_config->min_transmit_bitrate_bps = 100000; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for redundant payloads on all SSRCs."; } @@ -1802,15 +2128,14 @@ void EndToEndTest::TestRtpStatePreservation(bool use_rtx) { } private: - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { RTPHeader header; EXPECT_TRUE(parser_->Parse(packet, length, &header)); const uint32_t ssrc = header.ssrc; const uint16_t sequence_number = header.sequenceNumber; const uint32_t timestamp = header.timestamp; const bool only_padding = - static_cast(header.headerLength + header.paddingLength) == - length; + header.headerLength + header.paddingLength == length; EXPECT_TRUE(configured_ssrcs_[ssrc]) << "Received SSRC that wasn't configured: " << ssrc; @@ -1867,14 +2192,14 @@ void EndToEndTest::TestRtpStatePreservation(bool use_rtx) { std::map last_observed_timestamp_; std::map configured_ssrcs_; - scoped_ptr crit_; + rtc::scoped_ptr crit_; size_t ssrcs_to_observe_ GUARDED_BY(crit_); std::map ssrc_observed_ GUARDED_BY(crit_); } observer(use_rtx); CreateCalls(Call::Config(observer.SendTransport()), Call::Config(observer.ReceiveTransport())); - observer.SetReceivers(sender_call_->Receiver(), NULL); + observer.SetReceivers(sender_call_->Receiver(), nullptr); CreateSendConfig(kNumSsrcs); @@ -1981,124 +2306,85 @@ TEST_F(EndToEndTest, RespectsNetworkState) { FakeEncoder(Clock::GetRealTimeClock()), test_crit_(CriticalSectionWrapper::CreateCriticalSection()), encoded_frames_(EventWrapper::Create()), - sender_packets_(EventWrapper::Create()), - receiver_packets_(EventWrapper::Create()), + packet_event_(EventWrapper::Create()), sender_state_(Call::kNetworkUp), - down_sender_rtp_(0), - down_sender_rtcp_(0), - receiver_state_(Call::kNetworkUp), - down_receiver_rtcp_(0), + sender_rtp_(0), + sender_rtcp_(0), + receiver_rtcp_(0), down_frames_(0) {} - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { CriticalSectionScoped lock(test_crit_.get()); - if (sender_state_ == Call::kNetworkDown) { - ++down_sender_rtp_; - EXPECT_LE(down_sender_rtp_, kNumAcceptedDowntimeRtp) - << "RTP sent during sender-side downtime."; - if (down_sender_rtp_> kNumAcceptedDowntimeRtp) - sender_packets_->Set(); - } else { - sender_packets_->Set(); - } + ++sender_rtp_; + packet_event_->Set(); return SEND_PACKET; } - virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtcp(const uint8_t* packet, size_t length) override { CriticalSectionScoped lock(test_crit_.get()); - if (sender_state_ == Call::kNetworkDown) { - ++down_sender_rtcp_; - EXPECT_LE(down_sender_rtcp_, kNumAcceptedDowntimeRtcp) - << "RTCP sent during sender-side downtime."; - if (down_sender_rtcp_ > kNumAcceptedDowntimeRtcp) - sender_packets_->Set(); - } else { - sender_packets_->Set(); - } + ++sender_rtcp_; + packet_event_->Set(); return SEND_PACKET; } - virtual Action OnReceiveRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnReceiveRtp(const uint8_t* packet, size_t length) override { ADD_FAILURE() << "Unexpected receiver RTP, should not be sending."; return SEND_PACKET; } - virtual Action OnReceiveRtcp(const uint8_t* packet, - size_t length) OVERRIDE { + Action OnReceiveRtcp(const uint8_t* packet, size_t length) override { CriticalSectionScoped lock(test_crit_.get()); - if (receiver_state_ == Call::kNetworkDown) { - ++down_receiver_rtcp_; - EXPECT_LE(down_receiver_rtcp_, kNumAcceptedDowntimeRtcp) - << "RTCP sent during receiver-side downtime."; - if (down_receiver_rtcp_ > kNumAcceptedDowntimeRtcp) - receiver_packets_->Set(); - } else { - receiver_packets_->Set(); - } + ++receiver_rtcp_; + packet_event_->Set(); return SEND_PACKET; } - virtual void OnCallsCreated(Call* sender_call, - Call* receiver_call) OVERRIDE { + void OnCallsCreated(Call* sender_call, Call* receiver_call) override { sender_call_ = sender_call; receiver_call_ = receiver_call; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->encoder_settings.encoder = this; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, encoded_frames_->Wait(kDefaultTimeoutMs)) << "No frames received by the encoder."; - EXPECT_EQ(kEventSignaled, sender_packets_->Wait(kDefaultTimeoutMs)) - << "Timed out waiting for send-side packets."; - EXPECT_EQ(kEventSignaled, receiver_packets_->Wait(kDefaultTimeoutMs)) - << "Timed out waiting for receiver-side packets."; + // Wait for packets from both sender/receiver. + WaitForPacketsOrSilence(false, false); // Sender-side network down. sender_call_->SignalNetworkState(Call::kNetworkDown); { CriticalSectionScoped lock(test_crit_.get()); - sender_packets_->Reset(); // Earlier packets should not count. + // After network goes down we shouldn't be encoding more frames. sender_state_ = Call::kNetworkDown; } - EXPECT_EQ(kEventTimeout, sender_packets_->Wait(kSilenceTimeoutMs)) - << "Packets sent during sender-network downtime."; - EXPECT_EQ(kEventSignaled, receiver_packets_->Wait(kDefaultTimeoutMs)) - << "Timed out waiting for receiver-side packets."; + // Wait for receiver-packets and no sender packets. + WaitForPacketsOrSilence(true, false); + // Receiver-side network down. receiver_call_->SignalNetworkState(Call::kNetworkDown); - { - CriticalSectionScoped lock(test_crit_.get()); - receiver_packets_->Reset(); // Earlier packets should not count. - receiver_state_ = Call::kNetworkDown; - } - EXPECT_EQ(kEventTimeout, receiver_packets_->Wait(kSilenceTimeoutMs)) - << "Packets sent during receiver-network downtime."; + WaitForPacketsOrSilence(true, true); // Network back up again for both. { CriticalSectionScoped lock(test_crit_.get()); - sender_packets_->Reset(); // Earlier packets should not count. - receiver_packets_->Reset(); // Earlier packets should not count. - sender_state_ = receiver_state_ = Call::kNetworkUp; + // It's OK to encode frames again, as we're about to bring up the + // network. + sender_state_ = Call::kNetworkUp; } sender_call_->SignalNetworkState(Call::kNetworkUp); receiver_call_->SignalNetworkState(Call::kNetworkUp); - EXPECT_EQ(kEventSignaled, sender_packets_->Wait(kDefaultTimeoutMs)) - << "Timed out waiting for send-side packets."; - EXPECT_EQ(kEventSignaled, receiver_packets_->Wait(kDefaultTimeoutMs)) - << "Timed out waiting for receiver-side packets."; + WaitForPacketsOrSilence(false, false); } - virtual int32_t Encode(const I420VideoFrame& input_image, - const CodecSpecificInfo* codec_specific_info, - const std::vector* frame_types) - OVERRIDE { + int32_t Encode(const I420VideoFrame& input_image, + const CodecSpecificInfo* codec_specific_info, + const std::vector* frame_types) override { { CriticalSectionScoped lock(test_crit_.get()); if (sender_state_ == Call::kNetworkDown) { @@ -2116,31 +2402,114 @@ TEST_F(EndToEndTest, RespectsNetworkState) { } private: - const scoped_ptr test_crit_; - scoped_ptr encoded_frames_; - scoped_ptr sender_packets_; - scoped_ptr receiver_packets_; + void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) { + int64_t initial_time_ms = clock_->TimeInMilliseconds(); + int initial_sender_rtp; + int initial_sender_rtcp; + int initial_receiver_rtcp; + { + CriticalSectionScoped lock(test_crit_.get()); + initial_sender_rtp = sender_rtp_; + initial_sender_rtcp = sender_rtcp_; + initial_receiver_rtcp = receiver_rtcp_; + } + bool sender_done = false; + bool receiver_done = false; + while(!sender_done || !receiver_done) { + packet_event_->Wait(kSilenceTimeoutMs); + int64_t time_now_ms = clock_->TimeInMilliseconds(); + CriticalSectionScoped lock(test_crit_.get()); + if (sender_down) { + ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp) + << "RTP sent during sender-side downtime."; + ASSERT_LE(sender_rtcp_ - initial_sender_rtcp, + kNumAcceptedDowntimeRtcp) + << "RTCP sent during sender-side downtime."; + if (time_now_ms - initial_time_ms >= + static_cast(kSilenceTimeoutMs)) { + sender_done = true; + } + } else { + if (sender_rtp_ > initial_sender_rtp) + sender_done = true; + } + if (receiver_down) { + ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp, + kNumAcceptedDowntimeRtcp) + << "RTCP sent during receiver-side downtime."; + if (time_now_ms - initial_time_ms >= + static_cast(kSilenceTimeoutMs)) { + receiver_done = true; + } + } else { + if (receiver_rtcp_ > initial_receiver_rtcp) + receiver_done = true; + } + } + } + + const rtc::scoped_ptr test_crit_; + const rtc::scoped_ptr encoded_frames_; + const rtc::scoped_ptr packet_event_; Call* sender_call_; Call* receiver_call_; Call::NetworkState sender_state_ GUARDED_BY(test_crit_); - int down_sender_rtp_ GUARDED_BY(test_crit_); - int down_sender_rtcp_ GUARDED_BY(test_crit_); - Call::NetworkState receiver_state_ GUARDED_BY(test_crit_); - int down_receiver_rtcp_ GUARDED_BY(test_crit_); + int sender_rtp_ GUARDED_BY(test_crit_); + int sender_rtcp_ GUARDED_BY(test_crit_); + int receiver_rtcp_ GUARDED_BY(test_crit_); int down_frames_ GUARDED_BY(test_crit_); } test; RunBaseTest(&test); } +TEST_F(EndToEndTest, CallReportsRttForSender) { + static const int kSendDelayMs = 30; + static const int kReceiveDelayMs = 70; + + FakeNetworkPipe::Config config; + config.queue_delay_ms = kSendDelayMs; + test::DirectTransport sender_transport(config); + config.queue_delay_ms = kReceiveDelayMs; + test::DirectTransport receiver_transport(config); + + CreateCalls(Call::Config(&sender_transport), + Call::Config(&receiver_transport)); + + sender_transport.SetReceiver(receiver_call_->Receiver()); + receiver_transport.SetReceiver(sender_call_->Receiver()); + + CreateSendConfig(1); + CreateMatchingReceiveConfigs(); + + CreateStreams(); + CreateFrameGeneratorCapturer(); + Start(); + + int64_t start_time_ms = clock_->TimeInMilliseconds(); + while (true) { + Call::Stats stats = sender_call_->GetStats(); + ASSERT_GE(start_time_ms + kDefaultTimeoutMs, + clock_->TimeInMilliseconds()) + << "No RTT stats before timeout!"; + if (stats.rtt_ms != -1) { + EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs); + break; + } + SleepMs(10); + } + + Stop(); + DestroyStreams(); +} + TEST_F(EndToEndTest, NewSendStreamsRespectNetworkDown) { class UnusedEncoder : public test::FakeEncoder { public: UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {} - virtual int32_t Encode(const I420VideoFrame& input_image, - const CodecSpecificInfo* codec_specific_info, - const std::vector* frame_types) - OVERRIDE { + int32_t Encode(const I420VideoFrame& input_image, + const CodecSpecificInfo* codec_specific_info, + const std::vector* frame_types) override { ADD_FAILURE() << "Unexpected frame encode."; return test::FakeEncoder::Encode( input_image, codec_specific_info, frame_types); @@ -2191,7 +2560,7 @@ TEST_F(EndToEndTest, NewReceiveStreamsRespectNetworkDown) { // a backend. This is to test that we hand channels back properly. TEST_F(EndToEndTest, CanCreateAndDestroyManyVideoStreams) { test::NullTransport transport; - scoped_ptr call(Call::Create(Call::Config(&transport))); + rtc::scoped_ptr call(Call::Create(Call::Config(&transport))); test::FakeDecoder fake_decoder; test::FakeEncoder fake_encoder(Clock::GetRealTimeClock()); for (size_t i = 0; i < 100; ++i) { diff --git a/media/webrtc/trunk/webrtc/video/full_stack.cc b/media/webrtc/trunk/webrtc/video/full_stack.cc index 25e60eb8da..7f98f38a79 100644 --- a/media/webrtc/trunk/webrtc/video/full_stack.cc +++ b/media/webrtc/trunk/webrtc/video/full_stack.cc @@ -14,19 +14,21 @@ #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/call.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" #include "webrtc/system_wrappers/interface/clock.h" +#include "webrtc/system_wrappers/interface/cpu_info.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/event_wrapper.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/sleep.h" #include "webrtc/test/call_test.h" #include "webrtc/test/direct_transport.h" #include "webrtc/test/encoder_settings.h" #include "webrtc/test/fake_encoder.h" +#include "webrtc/test/frame_generator.h" #include "webrtc/test/frame_generator_capturer.h" #include "webrtc/test/statistics.h" #include "webrtc/test/testsupport/fileutils.h" @@ -43,11 +45,13 @@ struct FullStackTestParams { size_t width, height; int fps; } clip; + bool screenshare; int min_bitrate_bps; int target_bitrate_bps; int max_bitrate_bps; double avg_psnr_threshold; double avg_ssim_threshold; + int test_durations_secs; FakeNetworkPipe::Config link; }; @@ -69,42 +73,58 @@ class VideoAnalyzer : public PacketReceiver, int duration_frames) : input_(input), transport_(transport), - receiver_(NULL), + receiver_(nullptr), test_label_(test_label), - frames_left_(duration_frames), + frames_to_process_(duration_frames), + frames_recorded_(0), + frames_processed_(0), dropped_frames_(0), last_render_time_(0), rtp_timestamp_delta_(0), crit_(CriticalSectionWrapper::CreateCriticalSection()), - first_send_frame_(NULL), avg_psnr_threshold_(avg_psnr_threshold), avg_ssim_threshold_(avg_ssim_threshold), comparison_lock_(CriticalSectionWrapper::CreateCriticalSection()), - comparison_thread_(ThreadWrapper::CreateThread(&FrameComparisonThread, - this)), + comparison_available_event_(EventWrapper::Create()), done_(EventWrapper::Create()) { - unsigned int id; - EXPECT_TRUE(comparison_thread_->Start(id)); + // Create thread pool for CPU-expensive PSNR/SSIM calculations. + + // Try to use about as many threads as cores, but leave kMinCoresLeft alone, + // so that we don't accidentally starve "real" worker threads (codec etc). + // Also, don't allocate more than kMaxComparisonThreads, even if there are + // spare cores. + + uint32_t num_cores = CpuInfo::DetectNumberOfCores(); + DCHECK_GE(num_cores, 1u); + static const uint32_t kMinCoresLeft = 4; + static const uint32_t kMaxComparisonThreads = 8; + + if (num_cores <= kMinCoresLeft) { + num_cores = 1; + } else { + num_cores -= kMinCoresLeft; + num_cores = std::min(num_cores, kMaxComparisonThreads); + } + + for (uint32_t i = 0; i < num_cores; ++i) { + rtc::scoped_ptr thread = + ThreadWrapper::CreateThread(&FrameComparisonThread, this, "Analyzer"); + EXPECT_TRUE(thread->Start()); + comparison_thread_pool_.push_back(thread.release()); + } } ~VideoAnalyzer() { - EXPECT_TRUE(comparison_thread_->Stop()); - - while (!frames_.empty()) { - delete frames_.back(); - frames_.pop_back(); - } - while (!frame_pool_.empty()) { - delete frame_pool_.back(); - frame_pool_.pop_back(); + for (ThreadWrapper* thread : comparison_thread_pool_) { + EXPECT_TRUE(thread->Stop()); + delete thread; } } virtual void SetReceiver(PacketReceiver* receiver) { receiver_ = receiver; } - virtual DeliveryStatus DeliverPacket(const uint8_t* packet, - size_t length) OVERRIDE { - scoped_ptr parser(RtpHeaderParser::Create()); + DeliveryStatus DeliverPacket(const uint8_t* packet, size_t length) override { + rtc::scoped_ptr parser(RtpHeaderParser::Create()); RTPHeader header; parser->Parse(packet, length, &header); { @@ -116,34 +136,23 @@ class VideoAnalyzer : public PacketReceiver, return receiver_->DeliverPacket(packet, length); } - virtual void SwapFrame(I420VideoFrame* video_frame) OVERRIDE { - I420VideoFrame* copy = NULL; - { - CriticalSectionScoped lock(crit_.get()); - if (frame_pool_.size() > 0) { - copy = frame_pool_.front(); - frame_pool_.pop_front(); - } - } - if (copy == NULL) - copy = new I420VideoFrame(); - - copy->CopyFrame(*video_frame); - copy->set_timestamp(copy->render_time_ms() * 90); + void IncomingCapturedFrame(const I420VideoFrame& video_frame) override { + I420VideoFrame copy = video_frame; + copy.set_timestamp(copy.ntp_time_ms() * 90); { CriticalSectionScoped lock(crit_.get()); - if (first_send_frame_ == NULL && rtp_timestamp_delta_ == 0) + if (first_send_frame_.IsZeroSize() && rtp_timestamp_delta_ == 0) first_send_frame_ = copy; frames_.push_back(copy); } - input_->SwapFrame(video_frame); + input_->IncomingCapturedFrame(video_frame); } - virtual bool SendRtp(const uint8_t* packet, size_t length) OVERRIDE { - scoped_ptr parser(RtpHeaderParser::Create()); + bool SendRtp(const uint8_t* packet, size_t length) override { + rtc::scoped_ptr parser(RtpHeaderParser::Create()); RTPHeader header; parser->Parse(packet, length, &header); @@ -151,8 +160,8 @@ class VideoAnalyzer : public PacketReceiver, CriticalSectionScoped lock(crit_.get()); if (rtp_timestamp_delta_ == 0) { rtp_timestamp_delta_ = - header.timestamp - first_send_frame_->timestamp(); - first_send_frame_ = NULL; + header.timestamp - first_send_frame_.timestamp(); + first_send_frame_.Reset(); } send_times_[header.timestamp - rtp_timestamp_delta_] = Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); @@ -161,38 +170,59 @@ class VideoAnalyzer : public PacketReceiver, return transport_->SendRtp(packet, length); } - virtual bool SendRtcp(const uint8_t* packet, size_t length) OVERRIDE { + bool SendRtcp(const uint8_t* packet, size_t length) override { return transport_->SendRtcp(packet, length); } - virtual void RenderFrame(const I420VideoFrame& video_frame, - int time_to_render_ms) OVERRIDE { + void RenderFrame(const I420VideoFrame& video_frame, + int time_to_render_ms) override { int64_t render_time_ms = Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); uint32_t send_timestamp = video_frame.timestamp() - rtp_timestamp_delta_; CriticalSectionScoped lock(crit_.get()); - while (frames_.front()->timestamp() < send_timestamp) { - AddFrameComparison( - frames_.front(), &last_rendered_frame_, true, render_time_ms); - frame_pool_.push_back(frames_.front()); + + while (frames_.front().timestamp() < send_timestamp) { + AddFrameComparison(frames_.front(), last_rendered_frame_, true, + render_time_ms); frames_.pop_front(); } - I420VideoFrame* reference_frame = frames_.front(); + I420VideoFrame reference_frame = frames_.front(); frames_.pop_front(); - assert(reference_frame != NULL); - EXPECT_EQ(reference_frame->timestamp(), send_timestamp); - assert(reference_frame->timestamp() == send_timestamp); + assert(!reference_frame.IsZeroSize()); + EXPECT_EQ(reference_frame.timestamp(), send_timestamp); + assert(reference_frame.timestamp() == send_timestamp); - AddFrameComparison(reference_frame, &video_frame, false, render_time_ms); - frame_pool_.push_back(reference_frame); + AddFrameComparison(reference_frame, video_frame, false, render_time_ms); - last_rendered_frame_.CopyFrame(video_frame); + last_rendered_frame_ = video_frame; } + bool IsTextureSupported() const override { return false; } + void Wait() { - EXPECT_EQ(kEventSignaled, done_->Wait(FullStackTest::kLongTimeoutMs)); + // Frame comparisons can be very expensive. Wait for test to be done, but + // at time-out check if frames_processed is going up. If so, give it more + // time, otherwise fail. Hopefully this will reduce test flakiness. + + int last_frames_processed = -1; + EventTypeWrapper eventType; + while ((eventType = done_->Wait(FullStackTest::kDefaultTimeoutMs)) != + kEventSignaled) { + int frames_processed; + { + CriticalSectionScoped crit(comparison_lock_.get()); + frames_processed = frames_processed_; + } + if (last_frames_processed == -1) { + last_frames_processed = frames_processed; + continue; + } + ASSERT_GT(frames_processed, last_frames_processed) + << "Analyzer stalled while waiting for test to finish."; + last_frames_processed = frames_processed; + } } VideoSendStreamInput* input_; @@ -201,30 +231,21 @@ class VideoAnalyzer : public PacketReceiver, private: struct FrameComparison { - FrameComparison(const I420VideoFrame* reference, - const I420VideoFrame* render, + FrameComparison() + : dropped(false), send_time_ms(0), recv_time_ms(0), render_time_ms(0) {} + + FrameComparison(const I420VideoFrame& reference, + const I420VideoFrame& render, bool dropped, int64_t send_time_ms, int64_t recv_time_ms, int64_t render_time_ms) - : dropped(dropped), + : reference(reference), + render(render), + dropped(dropped), send_time_ms(send_time_ms), recv_time_ms(recv_time_ms), - render_time_ms(render_time_ms) { - this->reference.CopyFrame(*reference); - this->render.CopyFrame(*render); - } - - FrameComparison(const FrameComparison& compare) - : dropped(compare.dropped), - send_time_ms(compare.send_time_ms), - recv_time_ms(compare.recv_time_ms), - render_time_ms(compare.render_time_ms) { - this->reference.CopyFrame(compare.reference); - this->render.CopyFrame(compare.render); - } - - ~FrameComparison() {} + render_time_ms(render_time_ms) {} I420VideoFrame reference; I420VideoFrame render; @@ -234,15 +255,15 @@ class VideoAnalyzer : public PacketReceiver, int64_t render_time_ms; }; - void AddFrameComparison(const I420VideoFrame* reference, - const I420VideoFrame* render, + void AddFrameComparison(const I420VideoFrame& reference, + const I420VideoFrame& render, bool dropped, int64_t render_time_ms) EXCLUSIVE_LOCKS_REQUIRED(crit_) { - int64_t send_time_ms = send_times_[reference->timestamp()]; - send_times_.erase(reference->timestamp()); - int64_t recv_time_ms = recv_times_[reference->timestamp()]; - recv_times_.erase(reference->timestamp()); + int64_t send_time_ms = send_times_[reference.timestamp()]; + send_times_.erase(reference.timestamp()); + int64_t recv_time_ms = recv_times_[reference.timestamp()]; + recv_times_.erase(reference.timestamp()); CriticalSectionScoped crit(comparison_lock_.get()); comparisons_.push_back(FrameComparison(reference, @@ -251,6 +272,7 @@ class VideoAnalyzer : public PacketReceiver, send_time_ms, recv_time_ms, render_time_ms)); + comparison_available_event_->Set(); } static bool FrameComparisonThread(void* obj) { @@ -258,76 +280,110 @@ class VideoAnalyzer : public PacketReceiver, } bool CompareFrames() { - assert(frames_left_ > 0); + if (AllFramesRecorded()) + return false; I420VideoFrame reference; I420VideoFrame render; - bool dropped; - int64_t send_time_ms; - int64_t recv_time_ms; - int64_t render_time_ms; - - SleepMs(10); - - while (true) { - { - CriticalSectionScoped crit(comparison_lock_.get()); - if (comparisons_.empty()) - return true; - reference.SwapFrame(&comparisons_.front().reference); - render.SwapFrame(&comparisons_.front().render); - dropped = comparisons_.front().dropped; - send_time_ms = comparisons_.front().send_time_ms; - recv_time_ms = comparisons_.front().recv_time_ms; - render_time_ms = comparisons_.front().render_time_ms; - comparisons_.pop_front(); - } - - PerformFrameComparison(&reference, - &render, - dropped, - send_time_ms, - recv_time_ms, - render_time_ms); - - if (--frames_left_ == 0) { - PrintResult("psnr", psnr_, " dB"); - PrintResult("ssim", ssim_, ""); - PrintResult("sender_time", sender_time_, " ms"); - printf( - "RESULT dropped_frames: %s = %d\n", test_label_, dropped_frames_); - PrintResult("receiver_time", receiver_time_, " ms"); - PrintResult("total_delay_incl_network", end_to_end_, " ms"); - PrintResult("time_between_rendered_frames", rendered_delta_, " ms"); - EXPECT_GT(psnr_.Mean(), avg_psnr_threshold_); - EXPECT_GT(ssim_.Mean(), avg_ssim_threshold_); - done_->Set(); + FrameComparison comparison; + if (!PopComparison(&comparison)) { + // Wait until new comparison task is available, or test is done. + // If done, wake up remaining threads waiting. + comparison_available_event_->Wait(1000); + if (AllFramesRecorded()) { + comparison_available_event_->Set(); return false; } + return true; // Try again. } + + PerformFrameComparison(comparison); + + if (FrameProcessed()) { + PrintResults(); + done_->Set(); + comparison_available_event_->Set(); + return false; + } + + return true; } - void PerformFrameComparison(const I420VideoFrame* reference, - const I420VideoFrame* render, - bool dropped, - int64_t send_time_ms, - int64_t recv_time_ms, - int64_t render_time_ms) { - psnr_.AddSample(I420PSNR(reference, render)); - ssim_.AddSample(I420SSIM(reference, render)); - if (dropped) { + bool PopComparison(FrameComparison* comparison) { + CriticalSectionScoped crit(comparison_lock_.get()); + // If AllFramesRecorded() is true, it means we have already popped + // frames_to_process_ frames from comparisons_, so there is no more work + // for this thread to be done. frames_processed_ might still be lower if + // all comparisons are not done, but those frames are currently being + // worked on by other threads. + if (comparisons_.empty() || AllFramesRecorded()) + return false; + + *comparison = comparisons_.front(); + comparisons_.pop_front(); + + FrameRecorded(); + return true; + } + + // Increment counter for number of frames received for comparison. + void FrameRecorded() { + CriticalSectionScoped crit(comparison_lock_.get()); + ++frames_recorded_; + } + + // Returns true if all frames to be compared have been taken from the queue. + bool AllFramesRecorded() { + CriticalSectionScoped crit(comparison_lock_.get()); + assert(frames_recorded_ <= frames_to_process_); + return frames_recorded_ == frames_to_process_; + } + + // Increase count of number of frames processed. Returns true if this was the + // last frame to be processed. + bool FrameProcessed() { + CriticalSectionScoped crit(comparison_lock_.get()); + ++frames_processed_; + assert(frames_processed_ <= frames_to_process_); + return frames_processed_ == frames_to_process_; + } + + void PrintResults() { + CriticalSectionScoped crit(comparison_lock_.get()); + PrintResult("psnr", psnr_, " dB"); + PrintResult("ssim", ssim_, ""); + PrintResult("sender_time", sender_time_, " ms"); + printf("RESULT dropped_frames: %s = %d frames\n", test_label_, + dropped_frames_); + PrintResult("receiver_time", receiver_time_, " ms"); + PrintResult("total_delay_incl_network", end_to_end_, " ms"); + PrintResult("time_between_rendered_frames", rendered_delta_, " ms"); + EXPECT_GT(psnr_.Mean(), avg_psnr_threshold_); + EXPECT_GT(ssim_.Mean(), avg_ssim_threshold_); + } + + void PerformFrameComparison(const FrameComparison& comparison) { + // Perform expensive psnr and ssim calculations while not holding lock. + double psnr = I420PSNR(&comparison.reference, &comparison.render); + double ssim = I420SSIM(&comparison.reference, &comparison.render); + + CriticalSectionScoped crit(comparison_lock_.get()); + psnr_.AddSample(psnr); + ssim_.AddSample(ssim); + if (comparison.dropped) { ++dropped_frames_; return; } if (last_render_time_ != 0) - rendered_delta_.AddSample(render_time_ms - last_render_time_); - last_render_time_ = render_time_ms; + rendered_delta_.AddSample(comparison.render_time_ms - last_render_time_); + last_render_time_ = comparison.render_time_ms; - int64_t input_time_ms = reference->render_time_ms(); - sender_time_.AddSample(send_time_ms - input_time_ms); - receiver_time_.AddSample(render_time_ms - recv_time_ms); - end_to_end_.AddSample(render_time_ms - input_time_ms); + int64_t input_time_ms = comparison.reference.ntp_time_ms(); + sender_time_.AddSample(comparison.send_time_ms - input_time_ms); + receiver_time_.AddSample(comparison.render_time_ms - + comparison.recv_time_ms); + end_to_end_.AddSample(comparison.render_time_ms - input_time_ms); } void PrintResult(const char* result_type, @@ -348,36 +404,35 @@ class VideoAnalyzer : public PacketReceiver, test::Statistics ssim_; test::Statistics end_to_end_; test::Statistics rendered_delta_; - int frames_left_; + const int frames_to_process_; + int frames_recorded_; + int frames_processed_; int dropped_frames_; int64_t last_render_time_; uint32_t rtp_timestamp_delta_; - const scoped_ptr crit_; - std::deque frames_ GUARDED_BY(crit_); - std::deque frame_pool_ GUARDED_BY(crit_); + const rtc::scoped_ptr crit_; + std::deque frames_ GUARDED_BY(crit_); I420VideoFrame last_rendered_frame_ GUARDED_BY(crit_); std::map send_times_ GUARDED_BY(crit_); std::map recv_times_ GUARDED_BY(crit_); - I420VideoFrame* first_send_frame_ GUARDED_BY(crit_); + I420VideoFrame first_send_frame_ GUARDED_BY(crit_); const double avg_psnr_threshold_; const double avg_ssim_threshold_; - const scoped_ptr comparison_lock_; - const scoped_ptr comparison_thread_; + const rtc::scoped_ptr comparison_lock_; + std::vector comparison_thread_pool_; + const rtc::scoped_ptr comparison_available_event_; std::deque comparisons_ GUARDED_BY(comparison_lock_); - const scoped_ptr done_; + const rtc::scoped_ptr done_; }; void FullStackTest::RunTest(const FullStackTestParams& params) { test::DirectTransport send_transport(params.link); test::DirectTransport recv_transport(params.link); - VideoAnalyzer analyzer(NULL, - &send_transport, - params.test_label, - params.avg_psnr_threshold, - params.avg_ssim_threshold, - kFullStackTestDurationSecs * params.clip.fps); + VideoAnalyzer analyzer(nullptr, &send_transport, params.test_label, + params.avg_psnr_threshold, params.avg_ssim_threshold, + params.test_durations_secs * params.clip.fps); CreateCalls(Call::Config(&analyzer), Call::Config(&recv_transport)); @@ -387,12 +442,14 @@ void FullStackTest::RunTest(const FullStackTestParams& params) { CreateSendConfig(1); - scoped_ptr encoder( + rtc::scoped_ptr encoder( VideoEncoder::Create(VideoEncoder::kVp8)); send_config_.encoder_settings.encoder = encoder.get(); send_config_.encoder_settings.payload_name = "VP8"; send_config_.encoder_settings.payload_type = 124; send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs; + send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]); + send_config_.rtp.rtx.payload_type = kSendRtxPayloadType; VideoStream* stream = &encoder_config_.streams[0]; stream->width = params.clip.width; @@ -402,25 +459,56 @@ void FullStackTest::RunTest(const FullStackTestParams& params) { stream->max_bitrate_bps = params.max_bitrate_bps; stream->max_framerate = params.clip.fps; + if (params.screenshare) { + encoder_config_.content_type = VideoEncoderConfig::kScreenshare; + encoder_config_.min_transmit_bitrate_bps = 400 * 1000; + VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings(); + vp8_settings.denoisingOn = false; + vp8_settings.frameDroppingOn = false; + vp8_settings.numberOfTemporalLayers = 2; + encoder_config_.encoder_specific_settings = &vp8_settings; + + stream->temporal_layer_thresholds_bps.clear(); + stream->temporal_layer_thresholds_bps.push_back(stream->target_bitrate_bps); + } + CreateMatchingReceiveConfigs(); receive_configs_[0].renderer = &analyzer; receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs; + receive_configs_[0].rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrcs[0]; + receive_configs_[0].rtp.rtx[kSendRtxPayloadType].payload_type = + kSendRtxPayloadType; CreateStreams(); analyzer.input_ = send_stream_->Input(); - frame_generator_capturer_.reset( - test::FrameGeneratorCapturer::CreateFromYuvFile( - &analyzer, - test::ResourcePath(params.clip.name, "yuv").c_str(), - params.clip.width, - params.clip.height, - params.clip.fps, - Clock::GetRealTimeClock())); + if (params.screenshare) { + std::vector slides; + slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv")); + slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv")); + slides.push_back(test::ResourcePath("photo_1850_1110", "yuv")); + slides.push_back(test::ResourcePath("difficult_photo_1850_1110", "yuv")); - ASSERT_TRUE(frame_generator_capturer_.get() != NULL) - << "Could not create capturer for " << params.clip.name - << ".yuv. Is this resource file present?"; + rtc::scoped_ptr frame_generator( + test::FrameGenerator::CreateFromYuvFile( + slides, 1850, 1110, + 10 * params.clip.fps) // Cycle image every 10 seconds. + ); + frame_generator_capturer_.reset(new test::FrameGeneratorCapturer( + Clock::GetRealTimeClock(), &analyzer, frame_generator.release(), + params.clip.fps)); + ASSERT_TRUE(frame_generator_capturer_->Init()); + } else { + frame_generator_capturer_.reset( + test::FrameGeneratorCapturer::CreateFromYuvFile( + &analyzer, test::ResourcePath(params.clip.name, "yuv"), + params.clip.width, params.clip.height, params.clip.fps, + Clock::GetRealTimeClock())); + + ASSERT_TRUE(frame_generator_capturer_.get() != nullptr) + << "Could not create capturer for " << params.clip.name + << ".yuv. Is this resource file present?"; + } Start(); @@ -437,12 +525,13 @@ void FullStackTest::RunTest(const FullStackTestParams& params) { TEST_F(FullStackTest, ParisQcifWithoutPacketLoss) { FullStackTestParams paris_qcif = {"net_delay_0_0_plr_0", {"paris_qcif", 176, 144, 30}, + false, 300000, 300000, 300000, 36.0, - 0.96 - }; + 0.96, + kFullStackTestDurationSecs}; RunTest(paris_qcif); } @@ -450,24 +539,26 @@ TEST_F(FullStackTest, ForemanCifWithoutPacketLoss) { // TODO(pbos): Decide on psnr/ssim thresholds for foreman_cif. FullStackTestParams foreman_cif = {"foreman_cif_net_delay_0_0_plr_0", {"foreman_cif", 352, 288, 30}, + false, 700000, 700000, 700000, 0.0, - 0.0 - }; + 0.0, + kFullStackTestDurationSecs}; RunTest(foreman_cif); } TEST_F(FullStackTest, ForemanCifPlr5) { FullStackTestParams foreman_cif = {"foreman_cif_delay_50_0_plr_5", {"foreman_cif", 352, 288, 30}, + false, 30000, 500000, 2000000, 0.0, - 0.0 - }; + 0.0, + kFullStackTestDurationSecs}; foreman_cif.link.loss_percent = 5; foreman_cif.link.queue_delay_ms = 50; RunTest(foreman_cif); @@ -476,12 +567,13 @@ TEST_F(FullStackTest, ForemanCifPlr5) { TEST_F(FullStackTest, ForemanCif500kbps) { FullStackTestParams foreman_cif = {"foreman_cif_500kbps", {"foreman_cif", 352, 288, 30}, + false, 30000, 500000, 2000000, 0.0, - 0.0 - }; + 0.0, + kFullStackTestDurationSecs}; foreman_cif.link.queue_length_packets = 0; foreman_cif.link.queue_delay_ms = 0; foreman_cif.link.link_capacity_kbps = 500; @@ -491,12 +583,13 @@ TEST_F(FullStackTest, ForemanCif500kbps) { TEST_F(FullStackTest, ForemanCif500kbpsLimitedQueue) { FullStackTestParams foreman_cif = {"foreman_cif_500kbps_32pkts_queue", {"foreman_cif", 352, 288, 30}, + false, 30000, 500000, 2000000, 0.0, - 0.0 - }; + 0.0, + kFullStackTestDurationSecs}; foreman_cif.link.queue_length_packets = 32; foreman_cif.link.queue_delay_ms = 0; foreman_cif.link.link_capacity_kbps = 500; @@ -506,12 +599,13 @@ TEST_F(FullStackTest, ForemanCif500kbpsLimitedQueue) { TEST_F(FullStackTest, ForemanCif500kbps100ms) { FullStackTestParams foreman_cif = {"foreman_cif_500kbps_100ms", {"foreman_cif", 352, 288, 30}, + false, 30000, 500000, 2000000, 0.0, - 0.0 - }; + 0.0, + kFullStackTestDurationSecs}; foreman_cif.link.queue_length_packets = 0; foreman_cif.link.queue_delay_ms = 100; foreman_cif.link.link_capacity_kbps = 500; @@ -521,12 +615,13 @@ TEST_F(FullStackTest, ForemanCif500kbps100ms) { TEST_F(FullStackTest, ForemanCif500kbps100msLimitedQueue) { FullStackTestParams foreman_cif = {"foreman_cif_500kbps_100ms_32pkts_queue", {"foreman_cif", 352, 288, 30}, + false, 30000, 500000, 2000000, 0.0, - 0.0 - }; + 0.0, + kFullStackTestDurationSecs}; foreman_cif.link.queue_length_packets = 32; foreman_cif.link.queue_delay_ms = 100; foreman_cif.link.link_capacity_kbps = 500; @@ -536,15 +631,30 @@ TEST_F(FullStackTest, ForemanCif500kbps100msLimitedQueue) { TEST_F(FullStackTest, ForemanCif1000kbps100msLimitedQueue) { FullStackTestParams foreman_cif = {"foreman_cif_1000kbps_100ms_32pkts_queue", {"foreman_cif", 352, 288, 30}, + false, 30000, 2000000, 2000000, 0.0, - 0.0 - }; + 0.0, + kFullStackTestDurationSecs}; foreman_cif.link.queue_length_packets = 32; foreman_cif.link.queue_delay_ms = 100; foreman_cif.link.link_capacity_kbps = 1000; RunTest(foreman_cif); } + +TEST_F(FullStackTest, ScreenshareSlides) { + FullStackTestParams screenshare_params = { + "screenshare_slides", + {"screenshare_slides", 1850, 1110, 5}, + true, + 50000, + 100000, + 1000000, + 0.0, + 0.0, + kFullStackTestDurationSecs}; + RunTest(screenshare_params); +} } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video/loopback.cc b/media/webrtc/trunk/webrtc/video/loopback.cc index 8013833dff..9ef0ec4224 100644 --- a/media/webrtc/trunk/webrtc/video/loopback.cc +++ b/media/webrtc/trunk/webrtc/video/loopback.cc @@ -12,120 +12,70 @@ #include -#include "gflags/gflags.h" +#include "webrtc/video/loopback.h" + #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/checks.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/call.h" #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" #include "webrtc/system_wrappers/interface/clock.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/test/direct_transport.h" #include "webrtc/test/encoder_settings.h" #include "webrtc/test/fake_encoder.h" -#include "webrtc/test/field_trial.h" #include "webrtc/test/run_loop.h" -#include "webrtc/test/run_test.h" #include "webrtc/test/testsupport/trace_to_stderr.h" #include "webrtc/test/video_capturer.h" #include "webrtc/test/video_renderer.h" #include "webrtc/typedefs.h" namespace webrtc { +namespace test { static const int kAbsSendTimeExtensionId = 7; -namespace flags { - -DEFINE_int32(width, 640, "Video width."); -size_t Width() { return static_cast(FLAGS_width); } - -DEFINE_int32(height, 480, "Video height."); -size_t Height() { return static_cast(FLAGS_height); } - -DEFINE_int32(fps, 30, "Frames per second."); -int Fps() { return static_cast(FLAGS_fps); } - -DEFINE_int32(min_bitrate, 50, "Minimum video bitrate."); -size_t MinBitrate() { return static_cast(FLAGS_min_bitrate); } - -DEFINE_int32(start_bitrate, 300, "Video starting bitrate."); -size_t StartBitrate() { return static_cast(FLAGS_start_bitrate); } - -DEFINE_int32(max_bitrate, 800, "Maximum video bitrate."); -size_t MaxBitrate() { return static_cast(FLAGS_max_bitrate); } - -DEFINE_string(codec, "VP8", "Video codec to use."); -std::string Codec() { return static_cast(FLAGS_codec); } - -DEFINE_int32(loss_percent, 0, "Percentage of packets randomly lost."); -int LossPercent() { - return static_cast(FLAGS_loss_percent); -} - -DEFINE_int32(link_capacity, - 0, - "Capacity (kbps) of the fake link. 0 means infinite."); -int LinkCapacity() { - return static_cast(FLAGS_link_capacity); -} - -DEFINE_int32(queue_size, 0, "Size of the bottleneck link queue in packets."); -int QueueSize() { - return static_cast(FLAGS_queue_size); -} - -DEFINE_int32(avg_propagation_delay_ms, - 0, - "Average link propagation delay in ms."); -int AvgPropagationDelayMs() { - return static_cast(FLAGS_avg_propagation_delay_ms); -} - -DEFINE_int32(std_propagation_delay_ms, - 0, - "Link propagation delay standard deviation in ms."); -int StdPropagationDelayMs() { - return static_cast(FLAGS_std_propagation_delay_ms); -} - -DEFINE_bool(logs, false, "print logs to stderr"); - -DEFINE_string( - force_fieldtrials, - "", - "Field trials control experimental feature code which can be forced. " - "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/" - " will assign the group Enable to field trial WebRTC-FooFeature. Multiple " - "trials are separated by \"/\""); -} // namespace flags - static const uint32_t kSendSsrc = 0x654321; static const uint32_t kSendRtxSsrc = 0x654322; static const uint32_t kReceiverLocalSsrc = 0x123456; static const uint8_t kRtxPayloadType = 96; -void Loopback() { - scoped_ptr trace_to_stderr_; - if (webrtc::flags::FLAGS_logs) +Loopback::Loopback(const Config& config) + : config_(config), clock_(Clock::GetRealTimeClock()) { +} + +Loopback::~Loopback() { +} + +void Loopback::Run() { + rtc::scoped_ptr trace_to_stderr_; + if (config_.logs) trace_to_stderr_.reset(new test::TraceToStderr); - scoped_ptr local_preview(test::VideoRenderer::Create( - "Local Preview", flags::Width(), flags::Height())); - scoped_ptr loopback_video(test::VideoRenderer::Create( - "Loopback Video", flags::Width(), flags::Height())); + rtc::scoped_ptr local_preview( + test::VideoRenderer::Create("Local Preview", config_.width, + config_.height)); + rtc::scoped_ptr loopback_video( + test::VideoRenderer::Create("Loopback Video", config_.width, + config_.height)); FakeNetworkPipe::Config pipe_config; - pipe_config.loss_percent = flags::LossPercent(); - pipe_config.link_capacity_kbps = flags::LinkCapacity(); - pipe_config.queue_length_packets = flags::QueueSize(); - pipe_config.queue_delay_ms = flags::AvgPropagationDelayMs(); - pipe_config.delay_standard_deviation_ms = flags::StdPropagationDelayMs(); + pipe_config.loss_percent = config_.loss_percent; + pipe_config.link_capacity_kbps = config_.link_capacity_kbps; + pipe_config.queue_length_packets = config_.queue_size; + pipe_config.queue_delay_ms = config_.avg_propagation_delay_ms; + pipe_config.delay_standard_deviation_ms = config_.std_propagation_delay_ms; test::DirectTransport transport(pipe_config); Call::Config call_config(&transport); - call_config.stream_start_bitrate_bps = - static_cast(flags::StartBitrate()) * 1000; - scoped_ptr call(Call::Create(call_config)); + + call_config.bitrate_config.min_bitrate_bps = + static_cast(config_.min_bitrate_kbps) * 1000; + call_config.bitrate_config.start_bitrate_bps = + static_cast(config_.start_bitrate_kbps) * 1000; + call_config.bitrate_config.max_bitrate_bps = + static_cast(config_.max_bitrate_kbps) * 1000; + rtc::scoped_ptr call(Call::Create(call_config)); // Loopback, call sends to itself. transport.SetReceiver(call->Receiver()); @@ -139,41 +89,26 @@ void Loopback() { RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId)); send_config.local_renderer = local_preview.get(); - scoped_ptr encoder; - if (flags::Codec() == "VP8") { + rtc::scoped_ptr encoder; + if (config_.codec == "VP8") { encoder.reset(VideoEncoder::Create(VideoEncoder::kVp8)); - } else if (flags::Codec() == "VP9") { + } else if (config_.codec == "VP9") { encoder.reset(VideoEncoder::Create(VideoEncoder::kVp9)); } else { // Codec not supported. - assert(false && "Codec not supported!"); + RTC_NOTREACHED() << "Codec not supported!"; return; } send_config.encoder_settings.encoder = encoder.get(); - send_config.encoder_settings.payload_name = flags::Codec(); + send_config.encoder_settings.payload_name = config_.codec; send_config.encoder_settings.payload_type = 124; - VideoEncoderConfig encoder_config; - encoder_config.streams = test::CreateVideoStreams(1); - VideoStream* stream = &encoder_config.streams[0]; - stream->width = flags::Width(); - stream->height = flags::Height(); - stream->min_bitrate_bps = static_cast(flags::MinBitrate()) * 1000; - stream->target_bitrate_bps = static_cast(flags::MaxBitrate()) * 1000; - stream->max_bitrate_bps = static_cast(flags::MaxBitrate()) * 1000; - stream->max_framerate = 30; - stream->max_qp = 56; + + VideoEncoderConfig encoder_config(CreateEncoderConfig()); VideoSendStream* send_stream = call->CreateVideoSendStream(send_config, encoder_config); - Clock* test_clock = Clock::GetRealTimeClock(); - - scoped_ptr camera( - test::VideoCapturer::Create(send_stream->Input(), - flags::Width(), - flags::Height(), - flags::Fps(), - test_clock)); + rtc::scoped_ptr capturer(CreateCapturer(send_stream)); VideoReceiveStream::Config receive_config; receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0]; @@ -193,11 +128,11 @@ void Loopback() { receive_stream->Start(); send_stream->Start(); - camera->Start(); + capturer->Start(); test::PressEnterToContinue(); - camera->Stop(); + capturer->Stop(); send_stream->Stop(); receive_stream->Stop(); @@ -208,13 +143,26 @@ void Loopback() { transport.StopSending(); } -} // namespace webrtc -int main(int argc, char* argv[]) { - ::testing::InitGoogleTest(&argc, argv); - google::ParseCommandLineFlags(&argc, &argv, true); - webrtc::test::InitFieldTrialsFromString( - webrtc::flags::FLAGS_force_fieldtrials); - webrtc::test::RunTest(webrtc::Loopback); - return 0; +VideoEncoderConfig Loopback::CreateEncoderConfig() { + VideoEncoderConfig encoder_config; + encoder_config.streams = test::CreateVideoStreams(1); + VideoStream* stream = &encoder_config.streams[0]; + stream->width = config_.width; + stream->height = config_.height; + stream->min_bitrate_bps = static_cast(config_.min_bitrate_kbps) * 1000; + stream->max_bitrate_bps = static_cast(config_.max_bitrate_kbps) * 1000; + stream->target_bitrate_bps = + static_cast(config_.max_bitrate_kbps) * 1000; + stream->max_framerate = config_.fps; + stream->max_qp = 56; + return encoder_config; } + +test::VideoCapturer* Loopback::CreateCapturer(VideoSendStream* send_stream) { + return test::VideoCapturer::Create(send_stream->Input(), config_.width, + config_.height, config_.fps, clock_); +} + +} // namespace test +} // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video/loopback.h b/media/webrtc/trunk/webrtc/video/loopback.h new file mode 100644 index 0000000000..d0aa591b4c --- /dev/null +++ b/media/webrtc/trunk/webrtc/video/loopback.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include + +#include "webrtc/config.h" + +namespace webrtc { + +class VideoSendStream; +class Clock; + +namespace test { + +class VideoCapturer; + +class Loopback { + public: + struct Config { + size_t width; + size_t height; + int32_t fps; + size_t min_bitrate_kbps; + size_t start_bitrate_kbps; + size_t max_bitrate_kbps; + int32_t min_transmit_bitrate_kbps; + std::string codec; + int32_t loss_percent; + int32_t link_capacity_kbps; + int32_t queue_size; + int32_t avg_propagation_delay_ms; + int32_t std_propagation_delay_ms; + bool logs; + }; + + explicit Loopback(const Config& config); + virtual ~Loopback(); + + void Run(); + + protected: + virtual VideoEncoderConfig CreateEncoderConfig(); + virtual VideoCapturer* CreateCapturer(VideoSendStream* send_stream); + + const Config config_; + Clock* const clock_; +}; + +} // namespace test +} // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video/rampup_tests.cc b/media/webrtc/trunk/webrtc/video/rampup_tests.cc index 011ef6af57..35d3297f39 100644 --- a/media/webrtc/trunk/webrtc/video/rampup_tests.cc +++ b/media/webrtc/trunk/webrtc/video/rampup_tests.cc @@ -9,6 +9,8 @@ */ #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/checks.h" +#include "webrtc/base/common.h" #include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h" @@ -91,7 +93,7 @@ void StreamObserver::set_start_bitrate_bps(unsigned int start_bitrate_bps) { void StreamObserver::OnReceiveBitrateChanged( const std::vector& ssrcs, unsigned int bitrate) { CriticalSectionScoped lock(crit_.get()); - assert(expected_bitrate_bps_ > 0); + DCHECK_GT(expected_bitrate_bps_, 0u); if (start_bitrate_bps_ != 0) { // For tests with an explicitly set start bitrate, verify the first // bitrate estimate is close to the start bitrate and lower than the @@ -108,19 +110,18 @@ void StreamObserver::OnReceiveBitrateChanged( TriggerTestDone(); } } - rtp_rtcp_->SetREMBData( - bitrate, static_cast(ssrcs.size()), &ssrcs[0]); + rtp_rtcp_->SetREMBData(bitrate, ssrcs); rtp_rtcp_->Process(); } bool StreamObserver::SendRtp(const uint8_t* packet, size_t length) { CriticalSectionScoped lock(crit_.get()); RTPHeader header; - EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast(length), &header)); + EXPECT_TRUE(rtp_parser_->Parse(packet, length, &header)); receive_stats_->IncomingPacket(header, length, false); payload_registry_->SetIncomingPayloadType(header); remote_bitrate_estimator_->IncomingPacket( - clock_->TimeInMilliseconds(), static_cast(length - 12), header); + clock_->TimeInMilliseconds(), length - 12, header); if (remote_bitrate_estimator_->TimeUntilNextProcess() <= 0) { remote_bitrate_estimator_->Process(); } @@ -135,7 +136,7 @@ bool StreamObserver::SendRtp(const uint8_t* packet, size_t length) { ++rtx_media_packets_sent_; uint8_t restored_packet[kMaxPacketSize]; uint8_t* restored_packet_ptr = restored_packet; - int restored_length = static_cast(length); + size_t restored_length = length; payload_registry_->RestoreOriginalPacket(&restored_packet_ptr, packet, &restored_length, @@ -197,7 +198,7 @@ LowRateStreamObserver::LowRateStreamObserver( feedback_transport_(feedback_transport), receive_stats_(ReceiveStatistics::Create(clock)), crit_(CriticalSectionWrapper::CreateCriticalSection()), - send_stream_(NULL), + send_stream_(nullptr), test_state_(kFirstRampup), state_start_ms_(clock_->TimeInMilliseconds()), interval_start_ms_(state_start_ms_), @@ -212,12 +213,12 @@ LowRateStreamObserver::LowRateStreamObserver( rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config)); rtp_rtcp_->SetREMBStatus(true); rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound); - rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionTransmissionTimeOffset, - kTransmissionTimeOffsetExtensionId); + rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime, + kAbsSendTimeExtensionId); AbsoluteSendTimeRemoteBitrateEstimatorFactory rbe_factory; const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 10000; remote_bitrate_estimator_.reset( - rbe_factory.Create(this, clock, kMimdControl, + rbe_factory.Create(this, clock, kAimdControl, kRemoteBitrateEstimatorMinBitrateBps)); forward_transport_config_.link_capacity_kbps = kHighBandwidthLimitBps / 1000; @@ -226,7 +227,7 @@ LowRateStreamObserver::LowRateStreamObserver( test::DirectTransport::SetReceiver(this); } -void LowRateStreamObserver::SetSendStream(const VideoSendStream* send_stream) { +void LowRateStreamObserver::SetSendStream(VideoSendStream* send_stream) { CriticalSectionScoped lock(crit_.get()); send_stream_ = send_stream; } @@ -235,8 +236,7 @@ void LowRateStreamObserver::OnReceiveBitrateChanged( const std::vector& ssrcs, unsigned int bitrate) { CriticalSectionScoped lock(crit_.get()); - rtp_rtcp_->SetREMBData( - bitrate, static_cast(ssrcs.size()), &ssrcs[0]); + rtp_rtcp_->SetREMBData(bitrate, ssrcs); rtp_rtcp_->Process(); last_remb_bps_ = bitrate; } @@ -267,10 +267,10 @@ PacketReceiver::DeliveryStatus LowRateStreamObserver::DeliverPacket( const uint8_t* packet, size_t length) { CriticalSectionScoped lock(crit_.get()); RTPHeader header; - EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast(length), &header)); + EXPECT_TRUE(rtp_parser_->Parse(packet, length, &header)); receive_stats_->IncomingPacket(header, length, false); remote_bitrate_estimator_->IncomingPacket( - clock_->TimeInMilliseconds(), static_cast(length - 12), header); + clock_->TimeInMilliseconds(), length - 12, header); if (remote_bitrate_estimator_->TimeUntilNextProcess() <= 0) { remote_bitrate_estimator_->Process(); } @@ -299,7 +299,7 @@ std::string LowRateStreamObserver::GetModifierString() { void LowRateStreamObserver::EvolveTestState(unsigned int bitrate_bps) { int64_t now = clock_->TimeInMilliseconds(); CriticalSectionScoped lock(crit_.get()); - assert(send_stream_ != NULL); + DCHECK(send_stream_ != nullptr); switch (test_state_) { case kFirstRampup: { EXPECT_FALSE(suspended_in_stats_); @@ -381,7 +381,7 @@ void RampUpTest::RunRampUpTest(bool rtx, CreateSendConfig(num_streams); - scoped_ptr rbe_factory; + rtc::scoped_ptr rbe_factory; RateControlType control_type; if (extension_type == RtpExtension::kAbsSendTime) { control_type = kAimdControl; @@ -404,7 +404,7 @@ void RampUpTest::RunRampUpTest(bool rtx, Call::Config call_config(&stream_observer); if (start_bitrate_bps != 0) { - call_config.stream_start_bitrate_bps = start_bitrate_bps; + call_config.bitrate_config.start_bitrate_bps = start_bitrate_bps; stream_observer.set_start_bitrate_bps(start_bitrate_bps); } @@ -422,7 +422,6 @@ void RampUpTest::RunRampUpTest(bool rtx, if (rtx) { send_config_.rtp.rtx.payload_type = kSendRtxPayloadType; send_config_.rtp.rtx.ssrcs = rtx_ssrcs; - send_config_.rtp.rtx.pad_with_redundant_payloads = true; } if (num_streams == 1) { @@ -463,12 +462,11 @@ void RampUpTest::RunRampUpDownUpTest(size_t number_of_streams, bool rtx) { send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs; send_config_.rtp.extensions.push_back(RtpExtension( - RtpExtension::kTOffset, kTransmissionTimeOffsetExtensionId)); + RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId)); send_config_.suspend_below_min_bitrate = true; if (rtx) { send_config_.rtp.rtx.payload_type = kSendRtxPayloadType; send_config_.rtp.rtx.ssrcs = GenerateSsrcs(number_of_streams, 200); - send_config_.rtp.rtx.pad_with_redundant_payloads = true; } CreateStreams(); @@ -508,4 +506,20 @@ TEST_F(RampUpTest, UpDownUpOneStreamRtx) { RunRampUpDownUpTest(1, true); } TEST_F(RampUpTest, UpDownUpThreeStreamsRtx) { RunRampUpDownUpTest(3, true); } +TEST_F(RampUpTest, AbsSendTimeSingleStream) { + RunRampUpTest(false, 1, 0, RtpExtension::kAbsSendTime); +} + +TEST_F(RampUpTest, AbsSendTimeSimulcast) { + RunRampUpTest(false, 3, 0, RtpExtension::kAbsSendTime); +} + +TEST_F(RampUpTest, AbsSendTimeSimulcastWithRtx) { + RunRampUpTest(true, 3, 0, RtpExtension::kAbsSendTime); +} + +TEST_F(RampUpTest, AbsSendTimeSingleStreamWithHighStartBitrate) { + RunRampUpTest(false, 1, 0.9 * kSingleStreamTargetBps, + RtpExtension::kAbsSendTime); +} } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video/rampup_tests.h b/media/webrtc/trunk/webrtc/video/rampup_tests.h index 69399b419c..4335fc13a8 100644 --- a/media/webrtc/trunk/webrtc/video/rampup_tests.h +++ b/media/webrtc/trunk/webrtc/video/rampup_tests.h @@ -15,10 +15,10 @@ #include #include +#include "webrtc/base/scoped_ptr.h" #include "webrtc/call.h" #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" #include "webrtc/system_wrappers/interface/event_wrapper.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/test/call_test.h" #include "webrtc/video/transport_adapter.h" @@ -49,12 +49,12 @@ class StreamObserver : public newapi::Transport, public RemoteBitrateObserver { void set_start_bitrate_bps(unsigned int start_bitrate_bps); - virtual void OnReceiveBitrateChanged(const std::vector& ssrcs, - unsigned int bitrate) OVERRIDE; + void OnReceiveBitrateChanged(const std::vector& ssrcs, + unsigned int bitrate) override; - virtual bool SendRtp(const uint8_t* packet, size_t length) OVERRIDE; + bool SendRtp(const uint8_t* packet, size_t length) override; - virtual bool SendRtcp(const uint8_t* packet, size_t length) OVERRIDE; + bool SendRtcp(const uint8_t* packet, size_t length) override; EventTypeWrapper Wait(); @@ -65,15 +65,15 @@ class StreamObserver : public newapi::Transport, public RemoteBitrateObserver { void TriggerTestDone() EXCLUSIVE_LOCKS_REQUIRED(crit_); Clock* const clock_; - const scoped_ptr test_done_; - const scoped_ptr rtp_parser_; - scoped_ptr rtp_rtcp_; + const rtc::scoped_ptr test_done_; + const rtc::scoped_ptr rtp_parser_; + rtc::scoped_ptr rtp_rtcp_; internal::TransportAdapter feedback_transport_; - const scoped_ptr receive_stats_; - const scoped_ptr payload_registry_; - scoped_ptr remote_bitrate_estimator_; + const rtc::scoped_ptr receive_stats_; + const rtc::scoped_ptr payload_registry_; + rtc::scoped_ptr remote_bitrate_estimator_; - const scoped_ptr crit_; + const rtc::scoped_ptr crit_; unsigned int expected_bitrate_bps_ GUARDED_BY(crit_); unsigned int start_bitrate_bps_ GUARDED_BY(crit_); SsrcMap rtx_media_ssrcs_ GUARDED_BY(crit_); @@ -96,17 +96,16 @@ class LowRateStreamObserver : public test::DirectTransport, size_t number_of_streams, bool rtx_used); - virtual void SetSendStream(const VideoSendStream* send_stream); + virtual void SetSendStream(VideoSendStream* send_stream); virtual void OnReceiveBitrateChanged(const std::vector& ssrcs, unsigned int bitrate); - virtual bool SendRtp(const uint8_t* data, size_t length) OVERRIDE; + bool SendRtp(const uint8_t* data, size_t length) override; - virtual DeliveryStatus DeliverPacket(const uint8_t* packet, - size_t length) OVERRIDE; + DeliveryStatus DeliverPacket(const uint8_t* packet, size_t length) override; - virtual bool SendRtcp(const uint8_t* packet, size_t length) OVERRIDE; + bool SendRtcp(const uint8_t* packet, size_t length) override; // Produces a string similar to "1stream_nortx", depending on the values of // number_of_streams_ and rtx_used_; @@ -127,15 +126,15 @@ class LowRateStreamObserver : public test::DirectTransport, Clock* const clock_; const size_t number_of_streams_; const bool rtx_used_; - const scoped_ptr test_done_; - const scoped_ptr rtp_parser_; - scoped_ptr rtp_rtcp_; + const rtc::scoped_ptr test_done_; + const rtc::scoped_ptr rtp_parser_; + rtc::scoped_ptr rtp_rtcp_; internal::TransportAdapter feedback_transport_; - const scoped_ptr receive_stats_; - scoped_ptr remote_bitrate_estimator_; + const rtc::scoped_ptr receive_stats_; + rtc::scoped_ptr remote_bitrate_estimator_; - scoped_ptr crit_; - const VideoSendStream* send_stream_ GUARDED_BY(crit_); + rtc::scoped_ptr crit_; + VideoSendStream* send_stream_ GUARDED_BY(crit_); FakeNetworkPipe::Config forward_transport_config_ GUARDED_BY(crit_); TestStates test_state_ GUARDED_BY(crit_); int64_t state_start_ms_ GUARDED_BY(crit_); diff --git a/media/webrtc/trunk/webrtc/video/receive_statistics_proxy.cc b/media/webrtc/trunk/webrtc/video/receive_statistics_proxy.cc index fc4a6c29d0..b7a38535a4 100644 --- a/media/webrtc/trunk/webrtc/video/receive_statistics_proxy.cc +++ b/media/webrtc/trunk/webrtc/video/receive_statistics_proxy.cc @@ -14,17 +14,9 @@ #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" namespace webrtc { -namespace internal { -ReceiveStatisticsProxy::ReceiveStatisticsProxy(uint32_t ssrc, - Clock* clock, - ViERTP_RTCP* rtp_rtcp, - ViECodec* codec, - int channel) - : channel_(channel), - clock_(clock), - codec_(codec), - rtp_rtcp_(rtp_rtcp), +ReceiveStatisticsProxy::ReceiveStatisticsProxy(uint32_t ssrc, Clock* clock) + : clock_(clock), crit_(CriticalSectionWrapper::CreateCriticalSection()), // 1000ms window, scale 1000 for ms to s. decode_fps_estimator_(1000, 1000), @@ -36,25 +28,8 @@ ReceiveStatisticsProxy::ReceiveStatisticsProxy(uint32_t ssrc, ReceiveStatisticsProxy::~ReceiveStatisticsProxy() {} VideoReceiveStream::Stats ReceiveStatisticsProxy::GetStats() const { - VideoReceiveStream::Stats stats; - { - CriticalSectionScoped lock(crit_.get()); - stats = stats_; - } - stats.c_name = GetCName(); - codec_->GetReceiveSideDelay(channel_, &stats.avg_delay_ms); - stats.discarded_packets = codec_->GetNumDiscardedPackets(channel_); - codec_->GetReceiveCodecStatistics( - channel_, stats.key_frames, stats.delta_frames); - - return stats; -} - -std::string ReceiveStatisticsProxy::GetCName() const { - char rtcp_cname[ViERTP_RTCP::KMaxRTCPCNameLength]; - if (rtp_rtcp_->GetRemoteRTCPCName(channel_, rtcp_cname) != 0) - rtcp_cname[0] = '\0'; - return rtcp_cname; + CriticalSectionScoped lock(crit_.get()); + return stats_; } void ReceiveStatisticsProxy::IncomingRate(const int video_channel, @@ -71,19 +46,58 @@ void ReceiveStatisticsProxy::ReceiveStateChange(const int video_channel, receive_state_ = state; } +void ReceiveStatisticsProxy::DecoderTiming(int decode_ms, + int max_decode_ms, + int current_delay_ms, + int target_delay_ms, + int jitter_buffer_ms, + int min_playout_delay_ms, + int render_delay_ms) { + CriticalSectionScoped lock(crit_.get()); + stats_.decode_ms = decode_ms; + stats_.max_decode_ms = max_decode_ms; + stats_.current_delay_ms = current_delay_ms; + stats_.target_delay_ms = target_delay_ms; + stats_.jitter_buffer_ms = jitter_buffer_ms; + stats_.min_playout_delay_ms = min_playout_delay_ms; + stats_.render_delay_ms = render_delay_ms; +} + +void ReceiveStatisticsProxy::RtcpPacketTypesCounterUpdated( + uint32_t ssrc, + const RtcpPacketTypeCounter& packet_counter) { + CriticalSectionScoped lock(crit_.get()); + if (stats_.ssrc != ssrc) + return; + stats_.rtcp_packet_type_counts = packet_counter; +} + void ReceiveStatisticsProxy::StatisticsUpdated( const webrtc::RtcpStatistics& statistics, uint32_t ssrc) { CriticalSectionScoped lock(crit_.get()); - + // TODO(pbos): Handle both local and remote ssrcs here and DCHECK that we + // receive stats from one of them. + if (stats_.ssrc != ssrc) + return; stats_.rtcp_stats = statistics; } +void ReceiveStatisticsProxy::CNameChanged(const char* cname, uint32_t ssrc) { + CriticalSectionScoped lock(crit_.get()); + // TODO(pbos): Handle both local and remote ssrcs here and DCHECK that we + // receive stats from one of them. + if (stats_.ssrc != ssrc) + return; + stats_.c_name = cname; +} + void ReceiveStatisticsProxy::DataCountersUpdated( const webrtc::StreamDataCounters& counters, uint32_t ssrc) { CriticalSectionScoped lock(crit_.get()); - + if (stats_.ssrc != ssrc) + return; stats_.rtp_stats = counters; } @@ -103,5 +117,19 @@ void ReceiveStatisticsProxy::OnRenderedFrame() { stats_.render_frame_rate = renders_fps_estimator_.Rate(now); } -} // namespace internal +void ReceiveStatisticsProxy::OnReceiveRatesUpdated(uint32_t bitRate, + uint32_t frameRate) { +} + +void ReceiveStatisticsProxy::OnFrameCountsUpdated( + const FrameCounts& frame_counts) { + CriticalSectionScoped lock(crit_.get()); + stats_.frame_counts = frame_counts; +} + +void ReceiveStatisticsProxy::OnDiscardedPacketsUpdated(int discarded_packets) { + CriticalSectionScoped lock(crit_.get()); + stats_.discarded_packets = discarded_packets; +} + } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video/receive_statistics_proxy.h b/media/webrtc/trunk/webrtc/video/receive_statistics_proxy.h index 2bbd9db969..aaecb02a38 100644 --- a/media/webrtc/trunk/webrtc/video/receive_statistics_proxy.h +++ b/media/webrtc/trunk/webrtc/video/receive_statistics_proxy.h @@ -17,6 +17,7 @@ #include "webrtc/common_types.h" #include "webrtc/frame_callback.h" #include "webrtc/modules/remote_bitrate_estimator/rate_statistics.h" +#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h" #include "webrtc/video_engine/include/vie_codec.h" #include "webrtc/video_engine/include/vie_rtp_rtcp.h" #include "webrtc/video_receive_stream.h" @@ -29,17 +30,13 @@ class CriticalSectionWrapper; class ViECodec; class ViEDecoderObserver; -namespace internal { - class ReceiveStatisticsProxy : public ViEDecoderObserver, + public VCMReceiveStatisticsCallback, public RtcpStatisticsCallback, + public RtcpPacketTypeCounterObserver, public StreamDataCountersCallback { public: - ReceiveStatisticsProxy(uint32_t ssrc, - Clock* clock, - ViERTP_RTCP* rtp_rtcp, - ViECodec* codec, - int channel); + ReceiveStatisticsProxy(uint32_t ssrc, Clock* clock); virtual ~ReceiveStatisticsProxy(); VideoReceiveStream::Stats GetStats() const; @@ -47,45 +44,49 @@ class ReceiveStatisticsProxy : public ViEDecoderObserver, void OnDecodedFrame(); void OnRenderedFrame(); + // Overrides VCMReceiveStatisticsCallback + void OnReceiveRatesUpdated(uint32_t bitRate, uint32_t frameRate) override; + void OnFrameCountsUpdated(const FrameCounts& frame_counts) override; + void OnDiscardedPacketsUpdated(int discarded_packets) override; + // Overrides ViEDecoderObserver. - virtual void IncomingCodecChanged(const int video_channel, - const VideoCodec& video_codec) OVERRIDE {} - virtual void IncomingRate(const int video_channel, - const unsigned int framerate, - const unsigned int bitrate_bps) OVERRIDE; - virtual void DecoderTiming(int decode_ms, - int max_decode_ms, - int current_delay_ms, - int target_delay_ms, - int jitter_buffer_ms, - int min_playout_delay_ms, - int render_delay_ms) OVERRIDE {} - virtual void RequestNewKeyFrame(const int video_channel) OVERRIDE {} - virtual void ReceiveStateChange(const int video_channel, VideoReceiveState state) OVERRIDE; + void IncomingCodecChanged(const int video_channel, + const VideoCodec& video_codec) override {} + void IncomingRate(const int video_channel, + const unsigned int framerate, + const unsigned int bitrate_bps) override; + void DecoderTiming(int decode_ms, + int max_decode_ms, + int current_delay_ms, + int target_delay_ms, + int jitter_buffer_ms, + int min_playout_delay_ms, + int render_delay_ms) override; + void RequestNewKeyFrame(const int video_channel) override {} + virtual void ReceiveStateChange(const int video_channel, VideoReceiveState state) override; - // Overrides RtcpStatisticsBallback. - virtual void StatisticsUpdated(const webrtc::RtcpStatistics& statistics, - uint32_t ssrc) OVERRIDE; + // Overrides RtcpStatisticsCallback. + void StatisticsUpdated(const webrtc::RtcpStatistics& statistics, + uint32_t ssrc) override; + void CNameChanged(const char* cname, uint32_t ssrc) override; + // Overrides RtcpPacketTypeCounterObserver + void RtcpPacketTypesCounterUpdated( + uint32_t ssrc, + const RtcpPacketTypeCounter& packet_counter) override; // Overrides StreamDataCountersCallback. - virtual void DataCountersUpdated(const webrtc::StreamDataCounters& counters, - uint32_t ssrc) OVERRIDE; + void DataCountersUpdated(const webrtc::StreamDataCounters& counters, + uint32_t ssrc) override; private: - std::string GetCName() const; - - const int channel_; Clock* const clock_; - ViECodec* const codec_; - ViERTP_RTCP* const rtp_rtcp_; - scoped_ptr crit_; + rtc::scoped_ptr crit_; VideoReceiveStream::Stats stats_ GUARDED_BY(crit_); RateStatistics decode_fps_estimator_ GUARDED_BY(crit_); RateStatistics renders_fps_estimator_ GUARDED_BY(crit_); VideoReceiveState receive_state_ GUARDED_BY(crit_); }; -} // namespace internal } // namespace webrtc #endif // WEBRTC_VIDEO_RECEIVE_STATISTICS_PROXY_H_ diff --git a/media/webrtc/trunk/webrtc/video/replay.cc b/media/webrtc/trunk/webrtc/video/replay.cc index 5cfb06f8b8..740d149be8 100644 --- a/media/webrtc/trunk/webrtc/video/replay.cc +++ b/media/webrtc/trunk/webrtc/video/replay.cc @@ -16,14 +16,16 @@ #include "gflags/gflags.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/checks.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/call.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" #include "webrtc/system_wrappers/interface/clock.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/sleep.h" #include "webrtc/test/encoder_settings.h" #include "webrtc/test/null_transport.h" +#include "webrtc/test/fake_decoder.h" #include "webrtc/test/rtp_file_reader.h" #include "webrtc/test/run_loop.h" #include "webrtc/test/run_test.h" @@ -106,6 +108,7 @@ bool ValidateInputFilenameNotEmpty(const char* flagname, const std::string& string) { return string != ""; } + DEFINE_string(input_file, "", "input file"); static std::string InputFile() { return static_cast(FLAGS_input_file); @@ -120,6 +123,11 @@ static std::string OutBase() { return static_cast(FLAGS_out_base); } +DEFINE_string(decoder_bitstream_filename, "", "Decoder bitstream output file"); +static std::string DecoderBitstreamFilename() { + return static_cast(FLAGS_decoder_bitstream_filename); +} + // Flag for video codec. DEFINE_string(codec, "VP8", "Video codec"); static std::string Codec() { return static_cast(FLAGS_codec); } @@ -133,26 +141,26 @@ class FileRenderPassthrough : public VideoRenderer { FileRenderPassthrough(const std::string& basename, VideoRenderer* renderer) : basename_(basename), renderer_(renderer), - file_(NULL), + file_(nullptr), count_(0), last_width_(0), last_height_(0) {} ~FileRenderPassthrough() { - if (file_ != NULL) + if (file_ != nullptr) fclose(file_); } private: - virtual void RenderFrame(const I420VideoFrame& video_frame, - int time_to_render_ms) OVERRIDE { - if (renderer_ != NULL) + void RenderFrame(const I420VideoFrame& video_frame, + int time_to_render_ms) override { + if (renderer_ != nullptr) renderer_->RenderFrame(video_frame, time_to_render_ms); if (basename_ == "") return; if (last_width_ != video_frame.width() || last_height_ != video_frame.height()) { - if (file_ != NULL) + if (file_ != nullptr) fclose(file_); std::stringstream filename; filename << basename_; @@ -161,7 +169,7 @@ class FileRenderPassthrough : public VideoRenderer { filename << '_' << video_frame.width() << 'x' << video_frame.height() << ".yuv"; file_ = fopen(filename.str().c_str(), "wb"); - if (file_ == NULL) { + if (file_ == nullptr) { fprintf(stderr, "Couldn't open file for writing: %s\n", filename.str().c_str()); @@ -169,11 +177,13 @@ class FileRenderPassthrough : public VideoRenderer { } last_width_ = video_frame.width(); last_height_ = video_frame.height(); - if (file_ == NULL) + if (file_ == nullptr) return; PrintI420VideoFrame(video_frame, file_); } + bool IsTextureSupported() const override { return false; } + const std::string basename_; VideoRenderer* const renderer_; FILE* file_; @@ -182,9 +192,25 @@ class FileRenderPassthrough : public VideoRenderer { int last_height_; }; +class DecoderBitstreamFileWriter : public EncodedFrameObserver { + public: + explicit DecoderBitstreamFileWriter(const char* filename) + : file_(fopen(filename, "wb")) { + DCHECK(file_ != nullptr); + } + ~DecoderBitstreamFileWriter() { fclose(file_); } + + virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) { + fwrite(encoded_frame.data_, 1, encoded_frame.length_, file_); + } + + private: + FILE* file_; +}; + void RtpReplay() { - scoped_ptr playback_video(test::VideoRenderer::Create( - "Playback Video", 640, 480)); + rtc::scoped_ptr playback_video( + test::VideoRenderer::Create("Playback Video", 640, 480)); FileRenderPassthrough file_passthrough(flags::OutBase(), playback_video.get()); @@ -192,7 +218,7 @@ void RtpReplay() { // etc. test::NullTransport transport; Call::Config call_config(&transport); - scoped_ptr call(Call::Create(call_config)); + rtc::scoped_ptr call(Call::Create(call_config)); VideoReceiveStream::Config receive_config; receive_config.rtp.remote_ssrc = flags::Ssrc(); @@ -213,23 +239,42 @@ void RtpReplay() { VideoSendStream::Config::EncoderSettings encoder_settings; encoder_settings.payload_name = flags::Codec(); encoder_settings.payload_type = flags::PayloadType(); - VideoReceiveStream::Decoder decoder = - test::CreateMatchingDecoder(encoder_settings); + VideoReceiveStream::Decoder decoder; + rtc::scoped_ptr bitstream_writer; + if (flags::DecoderBitstreamFilename() != "") { + bitstream_writer.reset(new DecoderBitstreamFileWriter( + flags::DecoderBitstreamFilename().c_str())); + receive_config.pre_decode_callback = bitstream_writer.get(); + } + decoder = test::CreateMatchingDecoder(encoder_settings); + if (flags::DecoderBitstreamFilename() != "") { + // Replace with a null decoder if we're writing the bitstream to a file + // instead. + delete decoder.decoder; + decoder.decoder = new test::FakeNullDecoder(); + } receive_config.decoders.push_back(decoder); VideoReceiveStream* receive_stream = call->CreateVideoReceiveStream(receive_config); - scoped_ptr rtp_reader(test::RtpFileReader::Create( + rtc::scoped_ptr rtp_reader(test::RtpFileReader::Create( test::RtpFileReader::kRtpDump, flags::InputFile())); - if (rtp_reader.get() == NULL) { + if (rtp_reader.get() == nullptr) { rtp_reader.reset(test::RtpFileReader::Create(test::RtpFileReader::kPcap, flags::InputFile())); - if (rtp_reader.get() == NULL) { + if (rtp_reader.get() == nullptr) { fprintf(stderr, "Couldn't open input file as either a rtpdump or .pcap. Note " - "that .pcapng is not supported.\n"); - return; + "that .pcapng is not supported.\nTrying to interpret the file as " + "length/packet interleaved.\n"); + rtp_reader.reset(test::RtpFileReader::Create( + test::RtpFileReader::kLengthPacketInterleaved, flags::InputFile())); + if (rtp_reader.get() == nullptr) { + fprintf(stderr, + "Unable to open input file with any supported format\n"); + return; + } } } receive_stream->Start(); @@ -238,7 +283,7 @@ void RtpReplay() { int num_packets = 0; std::map unknown_packets; while (true) { - test::RtpFileReader::Packet packet; + test::RtpPacket packet; if (!rtp_reader->NextPacket(&packet)) break; ++num_packets; @@ -247,7 +292,7 @@ void RtpReplay() { break; case PacketReceiver::DELIVERY_UNKNOWN_SSRC: { RTPHeader header; - scoped_ptr parser(RtpHeaderParser::Create()); + rtc::scoped_ptr parser(RtpHeaderParser::Create()); parser->Parse(packet.data, packet.length, &header); if (unknown_packets[header.ssrc] == 0) fprintf(stderr, "Unknown SSRC: %u!\n", header.ssrc); diff --git a/media/webrtc/trunk/webrtc/video/screenshare_loopback.cc b/media/webrtc/trunk/webrtc/video/screenshare_loopback.cc new file mode 100644 index 0000000000..66bdf6ebc5 --- /dev/null +++ b/media/webrtc/trunk/webrtc/video/screenshare_loopback.cc @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include + +#include + +#include "gflags/gflags.h" +#include "testing/gtest/include/gtest/gtest.h" + +#include "webrtc/test/field_trial.h" +#include "webrtc/test/frame_generator.h" +#include "webrtc/test/frame_generator_capturer.h" +#include "webrtc/test/run_test.h" +#include "webrtc/test/testsupport/fileutils.h" +#include "webrtc/typedefs.h" +#include "webrtc/video/loopback.h" +#include "webrtc/video/video_send_stream.h" + +namespace webrtc { +namespace flags { + +// Fixed for prerecorded screenshare content. +size_t Width() { + return 1850; +} +size_t Height() { + return 1110; +} + +DEFINE_int32(fps, 5, "Frames per second."); +int Fps() { + return static_cast(FLAGS_fps); +} + +DEFINE_int32(min_bitrate, 50, "Minimum video bitrate."); +size_t MinBitrate() { + return static_cast(FLAGS_min_bitrate); +} + +DEFINE_int32(tl0_bitrate, 100, "Temporal layer 0 target bitrate."); +size_t StartBitrate() { + return static_cast(FLAGS_tl0_bitrate); +} + +DEFINE_int32(tl1_bitrate, 1000, "Temporal layer 1 target bitrate."); +size_t MaxBitrate() { + return static_cast(FLAGS_tl1_bitrate); +} + +DEFINE_int32(min_transmit_bitrate, 400, "Min transmit bitrate incl. padding."); +int MinTransmitBitrate() { + return FLAGS_min_transmit_bitrate; +} + +DEFINE_string(codec, "VP8", "Video codec to use."); +std::string Codec() { + return static_cast(FLAGS_codec); +} + +DEFINE_int32(loss_percent, 0, "Percentage of packets randomly lost."); +int LossPercent() { + return static_cast(FLAGS_loss_percent); +} + +DEFINE_int32(link_capacity, + 0, + "Capacity (kbps) of the fake link. 0 means infinite."); +int LinkCapacity() { + return static_cast(FLAGS_link_capacity); +} + +DEFINE_int32(queue_size, 0, "Size of the bottleneck link queue in packets."); +int QueueSize() { + return static_cast(FLAGS_queue_size); +} + +DEFINE_int32(avg_propagation_delay_ms, + 0, + "Average link propagation delay in ms."); +int AvgPropagationDelayMs() { + return static_cast(FLAGS_avg_propagation_delay_ms); +} + +DEFINE_int32(std_propagation_delay_ms, + 0, + "Link propagation delay standard deviation in ms."); +int StdPropagationDelayMs() { + return static_cast(FLAGS_std_propagation_delay_ms); +} + +DEFINE_bool(logs, false, "print logs to stderr"); + +DEFINE_string( + force_fieldtrials, + "", + "Field trials control experimental feature code which can be forced. " + "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/" + " will assign the group Enable to field trial WebRTC-FooFeature. Multiple " + "trials are separated by \"/\""); +} // namespace flags + +class ScreenshareLoopback : public test::Loopback { + public: + explicit ScreenshareLoopback(const Config& config) : Loopback(config) {} + virtual ~ScreenshareLoopback() {} + + protected: + VideoEncoderConfig CreateEncoderConfig() override { + VideoEncoderConfig encoder_config(test::Loopback::CreateEncoderConfig()); + VideoStream* stream = &encoder_config.streams[0]; + encoder_config.content_type = VideoEncoderConfig::kScreenshare; + encoder_config.min_transmit_bitrate_bps = flags::MinTransmitBitrate(); + VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings(); + vp8_settings.denoisingOn = false; + vp8_settings.frameDroppingOn = false; + vp8_settings.numberOfTemporalLayers = 2; + encoder_config.encoder_specific_settings = &vp8_settings; + stream->temporal_layer_thresholds_bps.clear(); + stream->target_bitrate_bps = + static_cast(config_.start_bitrate_kbps) * 1000; + stream->temporal_layer_thresholds_bps.push_back(stream->target_bitrate_bps); + return encoder_config; + } + + test::VideoCapturer* CreateCapturer(VideoSendStream* send_stream) override { + std::vector slides; + slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv")); + slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv")); + slides.push_back(test::ResourcePath("photo_1850_1110", "yuv")); + slides.push_back(test::ResourcePath("difficult_photo_1850_1110", "yuv")); + + test::FrameGenerator* frame_generator = + test::FrameGenerator::CreateFromYuvFile( + slides, flags::Width(), flags::Height(), 10 * flags::Fps()); + test::FrameGeneratorCapturer* capturer(new test::FrameGeneratorCapturer( + clock_, send_stream->Input(), frame_generator, flags::Fps())); + EXPECT_TRUE(capturer->Init()); + return capturer; + } +}; + +void Loopback() { + test::Loopback::Config config{flags::Width(), + flags::Height(), + flags::Fps(), + flags::MinBitrate(), + flags::StartBitrate(), + flags::MaxBitrate(), + flags::MinTransmitBitrate(), + flags::Codec(), + flags::LossPercent(), + flags::LinkCapacity(), + flags::QueueSize(), + flags::AvgPropagationDelayMs(), + flags::StdPropagationDelayMs(), + flags::FLAGS_logs}; + ScreenshareLoopback loopback(config); + loopback.Run(); +} +} // namespace webrtc + +int main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + google::ParseCommandLineFlags(&argc, &argv, true); + webrtc::test::InitFieldTrialsFromString( + webrtc::flags::FLAGS_force_fieldtrials); + webrtc::test::RunTest(webrtc::Loopback); + return 0; +} diff --git a/media/webrtc/trunk/webrtc/video/send_statistics_proxy.cc b/media/webrtc/trunk/webrtc/video/send_statistics_proxy.cc index f2df0ed2f5..41a8a99727 100644 --- a/media/webrtc/trunk/webrtc/video/send_statistics_proxy.cc +++ b/media/webrtc/trunk/webrtc/video/send_statistics_proxy.cc @@ -12,13 +12,19 @@ #include +#include "webrtc/base/checks.h" + #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" +#include "webrtc/system_wrappers/interface/logging.h" namespace webrtc { -SendStatisticsProxy::SendStatisticsProxy( - const VideoSendStream::Config& config) - : config_(config), +const int SendStatisticsProxy::kStatsTimeoutMs = 5000; + +SendStatisticsProxy::SendStatisticsProxy(Clock* clock, + const VideoSendStream::Config& config) + : clock_(clock), + config_(config), crit_(CriticalSectionWrapper::CreateCriticalSection()) { } @@ -32,24 +38,45 @@ void SendStatisticsProxy::OutgoingRate(const int video_channel, stats_.media_bitrate_bps = bitrate; } +void SendStatisticsProxy::CpuOveruseMetricsUpdated( + const CpuOveruseMetrics& metrics) { + CriticalSectionScoped lock(crit_.get()); + stats_.avg_encode_time_ms = metrics.avg_encode_time_ms; + stats_.encode_usage_percent = metrics.encode_usage_percent; +} + void SendStatisticsProxy::SuspendChange(int video_channel, bool is_suspended) { CriticalSectionScoped lock(crit_.get()); stats_.suspended = is_suspended; } -void SendStatisticsProxy::CapturedFrameRate(const int capture_id, - const unsigned char frame_rate) { - CriticalSectionScoped lock(crit_.get()); - stats_.input_frame_rate = frame_rate; -} - -VideoSendStream::Stats SendStatisticsProxy::GetStats() const { +VideoSendStream::Stats SendStatisticsProxy::GetStats() { CriticalSectionScoped lock(crit_.get()); + PurgeOldStats(); + stats_.input_frame_rate = + static_cast(input_frame_rate_tracker_.units_second()); return stats_; } -SsrcStats* SendStatisticsProxy::GetStatsEntry(uint32_t ssrc) { - std::map::iterator it = stats_.substreams.find(ssrc); +void SendStatisticsProxy::PurgeOldStats() { + int64_t current_time_ms = clock_->TimeInMilliseconds(); + for (std::map::iterator it = + stats_.substreams.begin(); + it != stats_.substreams.end(); ++it) { + uint32_t ssrc = it->first; + if (update_times_[ssrc].resolution_update_ms + kStatsTimeoutMs > + current_time_ms) + continue; + + it->second.width = 0; + it->second.height = 0; + } +} + +VideoSendStream::StreamStats* SendStatisticsProxy::GetStatsEntry( + uint32_t ssrc) { + std::map::iterator it = + stats_.substreams.find(ssrc); if (it != stats_.substreams.end()) return &it->second; @@ -58,29 +85,75 @@ SsrcStats* SendStatisticsProxy::GetStatsEntry(uint32_t ssrc) { std::find(config_.rtp.rtx.ssrcs.begin(), config_.rtp.rtx.ssrcs.end(), ssrc) == config_.rtp.rtx.ssrcs.end()) { - return NULL; + return nullptr; } return &stats_.substreams[ssrc]; // Insert new entry and return ptr. } +void SendStatisticsProxy::OnSetRates(uint32_t bitrate_bps, int framerate) { + CriticalSectionScoped lock(crit_.get()); + stats_.target_media_bitrate_bps = bitrate_bps; +} + +void SendStatisticsProxy::OnSendEncodedImage( + const EncodedImage& encoded_image, + const RTPVideoHeader* rtp_video_header) { + size_t simulcast_idx = + rtp_video_header != nullptr ? rtp_video_header->simulcastIdx : 0; + if (simulcast_idx >= config_.rtp.ssrcs.size()) { + LOG(LS_ERROR) << "Encoded image outside simulcast range (" << simulcast_idx + << " >= " << config_.rtp.ssrcs.size() << ")."; + return; + } + uint32_t ssrc = config_.rtp.ssrcs[simulcast_idx]; + + CriticalSectionScoped lock(crit_.get()); + VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc); + if (stats == nullptr) + return; + + stats->width = encoded_image._encodedWidth; + stats->height = encoded_image._encodedHeight; + update_times_[ssrc].resolution_update_ms = clock_->TimeInMilliseconds(); +} + +void SendStatisticsProxy::OnIncomingFrame() { + CriticalSectionScoped lock(crit_.get()); + input_frame_rate_tracker_.Update(1); +} + +void SendStatisticsProxy::RtcpPacketTypesCounterUpdated( + uint32_t ssrc, + const RtcpPacketTypeCounter& packet_counter) { + CriticalSectionScoped lock(crit_.get()); + VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc); + if (stats == nullptr) + return; + + stats->rtcp_packet_type_counts = packet_counter; +} + void SendStatisticsProxy::StatisticsUpdated(const RtcpStatistics& statistics, uint32_t ssrc) { CriticalSectionScoped lock(crit_.get()); - SsrcStats* stats = GetStatsEntry(ssrc); - if (stats == NULL) + VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc); + if (stats == nullptr) return; stats->rtcp_stats = statistics; } +void SendStatisticsProxy::CNameChanged(const char* cname, uint32_t ssrc) { +} + void SendStatisticsProxy::DataCountersUpdated( const StreamDataCounters& counters, uint32_t ssrc) { CriticalSectionScoped lock(crit_.get()); - SsrcStats* stats = GetStatsEntry(ssrc); - if (stats == NULL) - return; + VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc); + DCHECK(stats != nullptr) << "DataCountersUpdated reported for unknown ssrc: " + << ssrc; stats->rtp_stats = counters; } @@ -89,42 +162,30 @@ void SendStatisticsProxy::Notify(const BitrateStatistics& total_stats, const BitrateStatistics& retransmit_stats, uint32_t ssrc) { CriticalSectionScoped lock(crit_.get()); - SsrcStats* stats = GetStatsEntry(ssrc); - if (stats == NULL) + VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc); + if (stats == nullptr) return; stats->total_bitrate_bps = total_stats.bitrate_bps; stats->retransmit_bitrate_bps = retransmit_stats.bitrate_bps; } -void SendStatisticsProxy::FrameCountUpdated(FrameType frame_type, - uint32_t frame_count, - const unsigned int ssrc) { +void SendStatisticsProxy::FrameCountUpdated(const FrameCounts& frame_counts, + uint32_t ssrc) { CriticalSectionScoped lock(crit_.get()); - SsrcStats* stats = GetStatsEntry(ssrc); - if (stats == NULL) + VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc); + if (stats == nullptr) return; - switch (frame_type) { - case kVideoFrameDelta: - stats->delta_frames = frame_count; - break; - case kVideoFrameKey: - stats->key_frames = frame_count; - break; - case kFrameEmpty: - case kAudioFrameSpeech: - case kAudioFrameCN: - break; - } + stats->frame_counts = frame_counts; } void SendStatisticsProxy::SendSideDelayUpdated(int avg_delay_ms, int max_delay_ms, uint32_t ssrc) { CriticalSectionScoped lock(crit_.get()); - SsrcStats* stats = GetStatsEntry(ssrc); - if (stats == NULL) + VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc); + if (stats == nullptr) return; stats->avg_delay_ms = avg_delay_ms; stats->max_delay_ms = max_delay_ms; diff --git a/media/webrtc/trunk/webrtc/video/send_statistics_proxy.h b/media/webrtc/trunk/webrtc/video/send_statistics_proxy.h index 2f645b1ebe..0a048a59c2 100644 --- a/media/webrtc/trunk/webrtc/video/send_statistics_proxy.h +++ b/media/webrtc/trunk/webrtc/video/send_statistics_proxy.h @@ -13,75 +13,97 @@ #include +#include "webrtc/base/ratetracker.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/common_types.h" -#include "webrtc/video_engine/include/vie_codec.h" +#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" +#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h" +#include "webrtc/system_wrappers/interface/clock.h" +#include "webrtc/video_engine/include/vie_base.h" #include "webrtc/video_engine/include/vie_capture.h" +#include "webrtc/video_engine/include/vie_codec.h" #include "webrtc/video_send_stream.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" namespace webrtc { class CriticalSectionWrapper; -class SendStatisticsProxy : public RtcpStatisticsCallback, +class SendStatisticsProxy : public CpuOveruseMetricsObserver, + public RtcpStatisticsCallback, + public RtcpPacketTypeCounterObserver, public StreamDataCountersCallback, public BitrateStatisticsObserver, public FrameCountObserver, public ViEEncoderObserver, - public ViECaptureObserver, + public VideoEncoderRateObserver, public SendSideDelayObserver { public: - explicit SendStatisticsProxy(const VideoSendStream::Config& config); + static const int kStatsTimeoutMs; + + SendStatisticsProxy(Clock* clock, const VideoSendStream::Config& config); virtual ~SendStatisticsProxy(); - VideoSendStream::Stats GetStats() const; + VideoSendStream::Stats GetStats(); + + virtual void OnSendEncodedImage(const EncodedImage& encoded_image, + const RTPVideoHeader* rtp_video_header); + // Used to update incoming frame rate. + void OnIncomingFrame(); + + // From VideoEncoderRateObserver. + void OnSetRates(uint32_t bitrate_bps, int framerate) override; protected: + // From CpuOveruseMetricsObserver. + void CpuOveruseMetricsUpdated(const CpuOveruseMetrics& metrics) override; // From RtcpStatisticsCallback. - virtual void StatisticsUpdated(const RtcpStatistics& statistics, - uint32_t ssrc) OVERRIDE; + void StatisticsUpdated(const RtcpStatistics& statistics, + uint32_t ssrc) override; + void CNameChanged(const char* cname, uint32_t ssrc) override; + // From RtcpPacketTypeCounterObserver + void RtcpPacketTypesCounterUpdated( + uint32_t ssrc, + const RtcpPacketTypeCounter& packet_counter) override; // From StreamDataCountersCallback. - virtual void DataCountersUpdated(const StreamDataCounters& counters, - uint32_t ssrc) OVERRIDE; + void DataCountersUpdated(const StreamDataCounters& counters, + uint32_t ssrc) override; // From BitrateStatisticsObserver. - virtual void Notify(const BitrateStatistics& total_stats, - const BitrateStatistics& retransmit_stats, - uint32_t ssrc) OVERRIDE; + void Notify(const BitrateStatistics& total_stats, + const BitrateStatistics& retransmit_stats, + uint32_t ssrc) override; // From FrameCountObserver. - virtual void FrameCountUpdated(FrameType frame_type, - uint32_t frame_count, - const unsigned int ssrc) OVERRIDE; + void FrameCountUpdated(const FrameCounts& frame_counts, + uint32_t ssrc) override; // From ViEEncoderObserver. - virtual void OutgoingRate(const int video_channel, - const unsigned int framerate, - const unsigned int bitrate) OVERRIDE; + void OutgoingRate(const int video_channel, + const unsigned int framerate, + const unsigned int bitrate) override; - virtual void SuspendChange(int video_channel, bool is_suspended) OVERRIDE; + void SuspendChange(int video_channel, bool is_suspended) override; - // From ViECaptureObserver. - virtual void BrightnessAlarm(const int capture_id, - const Brightness brightness) OVERRIDE {} - - virtual void CapturedFrameRate(const int capture_id, - const unsigned char frame_rate) OVERRIDE; - - virtual void NoPictureAlarm(const int capture_id, - const CaptureAlarm alarm) OVERRIDE {} - - virtual void SendSideDelayUpdated(int avg_delay_ms, - int max_delay_ms, - uint32_t ssrc) OVERRIDE; + void SendSideDelayUpdated(int avg_delay_ms, + int max_delay_ms, + uint32_t ssrc) override; private: - SsrcStats* GetStatsEntry(uint32_t ssrc) EXCLUSIVE_LOCKS_REQUIRED(crit_); + struct StatsUpdateTimes { + StatsUpdateTimes() : resolution_update_ms(0) {} + int64_t resolution_update_ms; + }; + void PurgeOldStats() EXCLUSIVE_LOCKS_REQUIRED(crit_); + VideoSendStream::StreamStats* GetStatsEntry(uint32_t ssrc) + EXCLUSIVE_LOCKS_REQUIRED(crit_); + Clock* const clock_; const VideoSendStream::Config config_; - scoped_ptr crit_; + rtc::scoped_ptr crit_; VideoSendStream::Stats stats_ GUARDED_BY(crit_); + rtc::RateTracker input_frame_rate_tracker_ GUARDED_BY(crit_); + std::map update_times_ GUARDED_BY(crit_); }; } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video/send_statistics_proxy_unittest.cc b/media/webrtc/trunk/webrtc/video/send_statistics_proxy_unittest.cc index d7750f8aaf..0243add3b0 100644 --- a/media/webrtc/trunk/webrtc/video/send_statistics_proxy_unittest.cc +++ b/media/webrtc/trunk/webrtc/video/send_statistics_proxy_unittest.cc @@ -21,13 +21,14 @@ namespace webrtc { class SendStatisticsProxyTest : public ::testing::Test { public: - SendStatisticsProxyTest() : avg_delay_ms_(0), max_delay_ms_(0) {} + SendStatisticsProxyTest() + : fake_clock_(1234), avg_delay_ms_(0), max_delay_ms_(0) {} virtual ~SendStatisticsProxyTest() {} protected: virtual void SetUp() { statistics_proxy_.reset( - new SendStatisticsProxy(GetTestConfig())); + new SendStatisticsProxy(&fake_clock_, GetTestConfig())); config_ = GetTestConfig(); expected_ = VideoSendStream::Stats(); } @@ -48,29 +49,32 @@ class SendStatisticsProxyTest : public ::testing::Test { EXPECT_EQ(one.suspended, other.suspended); EXPECT_EQ(one.substreams.size(), other.substreams.size()); - for (std::map::const_iterator it = + for (std::map::const_iterator it = one.substreams.begin(); - it != one.substreams.end(); - ++it) { - std::map::const_iterator corresponding_it = - other.substreams.find(it->first); + it != one.substreams.end(); ++it) { + std::map::const_iterator + corresponding_it = other.substreams.find(it->first); ASSERT_TRUE(corresponding_it != other.substreams.end()); - const SsrcStats& a = it->second; - const SsrcStats& b = corresponding_it->second; + const VideoSendStream::StreamStats& a = it->second; + const VideoSendStream::StreamStats& b = corresponding_it->second; - EXPECT_EQ(a.key_frames, b.key_frames); - EXPECT_EQ(a.delta_frames, b.delta_frames); + EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames); + EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames); EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps); EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms); EXPECT_EQ(a.max_delay_ms, b.max_delay_ms); - EXPECT_EQ(a.rtp_stats.bytes, b.rtp_stats.bytes); - EXPECT_EQ(a.rtp_stats.header_bytes, b.rtp_stats.header_bytes); - EXPECT_EQ(a.rtp_stats.padding_bytes, b.rtp_stats.padding_bytes); - EXPECT_EQ(a.rtp_stats.packets, b.rtp_stats.packets); - EXPECT_EQ(a.rtp_stats.retransmitted_packets, - b.rtp_stats.retransmitted_packets); - EXPECT_EQ(a.rtp_stats.fec_packets, b.rtp_stats.fec_packets); + EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes, + b.rtp_stats.transmitted.payload_bytes); + EXPECT_EQ(a.rtp_stats.transmitted.header_bytes, + b.rtp_stats.transmitted.header_bytes); + EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes, + b.rtp_stats.transmitted.padding_bytes); + EXPECT_EQ(a.rtp_stats.transmitted.packets, + b.rtp_stats.transmitted.packets); + EXPECT_EQ(a.rtp_stats.retransmitted.packets, + b.rtp_stats.retransmitted.packets); + EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets); EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost); EXPECT_EQ(a.rtcp_stats.cumulative_lost, b.rtcp_stats.cumulative_lost); @@ -80,12 +84,14 @@ class SendStatisticsProxyTest : public ::testing::Test { } } - scoped_ptr statistics_proxy_; + rtc::scoped_ptr statistics_proxy_; + SimulatedClock fake_clock_; VideoSendStream::Config config_; int avg_delay_ms_; int max_delay_ms_; VideoSendStream::Stats expected_; - typedef std::map::const_iterator StreamIterator; + typedef std::map::const_iterator + StreamIterator; }; TEST_F(SendStatisticsProxyTest, RtcpStatistics) { @@ -94,7 +100,7 @@ TEST_F(SendStatisticsProxyTest, RtcpStatistics) { it != config_.rtp.ssrcs.end(); ++it) { const uint32_t ssrc = *it; - SsrcStats& ssrc_stats = expected_.substreams[ssrc]; + VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc]; // Add statistics with some arbitrary, but unique, numbers. uint32_t offset = ssrc * sizeof(RtcpStatistics); @@ -108,7 +114,7 @@ TEST_F(SendStatisticsProxyTest, RtcpStatistics) { it != config_.rtp.rtx.ssrcs.end(); ++it) { const uint32_t ssrc = *it; - SsrcStats& ssrc_stats = expected_.substreams[ssrc]; + VideoSendStream::StreamStats& ssrc_stats = expected_.substreams[ssrc]; // Add statistics with some arbitrary, but unique, numbers. uint32_t offset = ssrc * sizeof(RtcpStatistics); @@ -122,16 +128,6 @@ TEST_F(SendStatisticsProxyTest, RtcpStatistics) { ExpectEqual(expected_, stats); } -TEST_F(SendStatisticsProxyTest, CaptureFramerate) { - const int capture_fps = 31; - - ViECaptureObserver* capture_observer = statistics_proxy_.get(); - capture_observer->CapturedFrameRate(0, capture_fps); - - VideoSendStream::Stats stats = statistics_proxy_->GetStats(); - EXPECT_EQ(capture_fps, stats.input_frame_rate); -} - TEST_F(SendStatisticsProxyTest, EncodedBitrateAndFramerate) { const int media_bitrate_bps = 500; const int encode_fps = 29; @@ -165,24 +161,26 @@ TEST_F(SendStatisticsProxyTest, FrameCounts) { ++it) { const uint32_t ssrc = *it; // Add statistics with some arbitrary, but unique, numbers. - SsrcStats& stats = expected_.substreams[ssrc]; - uint32_t offset = ssrc * sizeof(SsrcStats); - stats.key_frames = offset; - stats.delta_frames = offset + 1; - observer->FrameCountUpdated(kVideoFrameKey, stats.key_frames, ssrc); - observer->FrameCountUpdated(kVideoFrameDelta, stats.delta_frames, ssrc); + VideoSendStream::StreamStats& stats = expected_.substreams[ssrc]; + uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats); + FrameCounts frame_counts; + frame_counts.key_frames = offset; + frame_counts.delta_frames = offset + 1; + stats.frame_counts = frame_counts; + observer->FrameCountUpdated(frame_counts, ssrc); } for (std::vector::const_iterator it = config_.rtp.rtx.ssrcs.begin(); it != config_.rtp.rtx.ssrcs.end(); ++it) { const uint32_t ssrc = *it; // Add statistics with some arbitrary, but unique, numbers. - SsrcStats& stats = expected_.substreams[ssrc]; - uint32_t offset = ssrc * sizeof(SsrcStats); - stats.key_frames = offset; - stats.delta_frames = offset + 1; - observer->FrameCountUpdated(kVideoFrameKey, stats.key_frames, ssrc); - observer->FrameCountUpdated(kVideoFrameDelta, stats.delta_frames, ssrc); + VideoSendStream::StreamStats& stats = expected_.substreams[ssrc]; + uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats); + FrameCounts frame_counts; + frame_counts.key_frames = offset; + frame_counts.delta_frames = offset + 1; + stats.frame_counts = frame_counts; + observer->FrameCountUpdated(frame_counts, ssrc); } VideoSendStream::Stats stats = statistics_proxy_->GetStats(); @@ -197,13 +195,14 @@ TEST_F(SendStatisticsProxyTest, DataCounters) { const uint32_t ssrc = *it; StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats; // Add statistics with some arbitrary, but unique, numbers. - uint32_t offset = ssrc * sizeof(StreamDataCounters); - counters.bytes = offset; - counters.header_bytes = offset + 1; - counters.fec_packets = offset + 2; - counters.padding_bytes = offset + 3; - counters.retransmitted_packets = offset + 4; - counters.packets = offset + 5; + size_t offset = ssrc * sizeof(StreamDataCounters); + uint32_t offset_uint32 = static_cast(offset); + counters.transmitted.payload_bytes = offset; + counters.transmitted.header_bytes = offset + 1; + counters.fec.packets = offset_uint32 + 2; + counters.transmitted.padding_bytes = offset + 3; + counters.retransmitted.packets = offset_uint32 + 4; + counters.transmitted.packets = offset_uint32 + 5; callback->DataCountersUpdated(counters, ssrc); } for (std::vector::const_iterator it = config_.rtp.rtx.ssrcs.begin(); @@ -212,13 +211,14 @@ TEST_F(SendStatisticsProxyTest, DataCounters) { const uint32_t ssrc = *it; StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats; // Add statistics with some arbitrary, but unique, numbers. - uint32_t offset = ssrc * sizeof(StreamDataCounters); - counters.bytes = offset; - counters.header_bytes = offset + 1; - counters.fec_packets = offset + 2; - counters.padding_bytes = offset + 3; - counters.retransmitted_packets = offset + 4; - counters.packets = offset + 5; + size_t offset = ssrc * sizeof(StreamDataCounters); + uint32_t offset_uint32 = static_cast(offset); + counters.transmitted.payload_bytes = offset; + counters.transmitted.header_bytes = offset + 1; + counters.fec.packets = offset_uint32 + 2; + counters.transmitted.padding_bytes = offset + 3; + counters.retransmitted.packets = offset_uint32 + 4; + counters.transmitted.packets = offset_uint32 + 5; callback->DataCountersUpdated(counters, ssrc); } @@ -290,7 +290,7 @@ TEST_F(SendStatisticsProxyTest, SendSideDelay) { } TEST_F(SendStatisticsProxyTest, NoSubstreams) { - uint32_t exluded_ssrc = + uint32_t excluded_ssrc = std::max( *std::max_element(config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end()), *std::max_element(config_.rtp.rtx.ssrcs.begin(), @@ -299,25 +299,69 @@ TEST_F(SendStatisticsProxyTest, NoSubstreams) { // From RtcpStatisticsCallback. RtcpStatistics rtcp_stats; RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get(); - rtcp_callback->StatisticsUpdated(rtcp_stats, exluded_ssrc); - - // From StreamDataCountersCallback. - StreamDataCounters rtp_stats; - StreamDataCountersCallback* rtp_callback = statistics_proxy_.get(); - rtp_callback->DataCountersUpdated(rtp_stats, exluded_ssrc); + rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc); // From BitrateStatisticsObserver. BitrateStatistics total; BitrateStatistics retransmit; BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get(); - bitrate_observer->Notify(total, retransmit, exluded_ssrc); + bitrate_observer->Notify(total, retransmit, excluded_ssrc); // From FrameCountObserver. FrameCountObserver* fps_observer = statistics_proxy_.get(); - fps_observer->FrameCountUpdated(kVideoFrameKey, 1, exluded_ssrc); + FrameCounts frame_counts; + frame_counts.key_frames = 1; + fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc); VideoSendStream::Stats stats = statistics_proxy_->GetStats(); EXPECT_TRUE(stats.substreams.empty()); } +TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) { + static const int kEncodedWidth = 123; + static const int kEncodedHeight = 81; + EncodedImage encoded_image; + encoded_image._encodedWidth = kEncodedWidth; + encoded_image._encodedHeight = kEncodedHeight; + + RTPVideoHeader rtp_video_header; + + rtp_video_header.simulcastIdx = 0; + statistics_proxy_->OnSendEncodedImage(encoded_image, &rtp_video_header); + rtp_video_header.simulcastIdx = 1; + statistics_proxy_->OnSendEncodedImage(encoded_image, &rtp_video_header); + + VideoSendStream::Stats stats = statistics_proxy_->GetStats(); + EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width); + EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height); + EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width); + EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height); + + // Forward almost to timeout, this should not have removed stats. + fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1); + stats = statistics_proxy_->GetStats(); + EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width); + EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height); + + // Update the first SSRC with bogus RTCP stats to make sure that encoded + // resolution still times out (no global timeout for all stats). + RtcpStatistics rtcp_statistics; + RtcpStatisticsCallback* rtcp_stats = statistics_proxy_.get(); + rtcp_stats->StatisticsUpdated(rtcp_statistics, config_.rtp.ssrcs[0]); + + // Report stats for second SSRC to make sure it's not outdated along with the + // first SSRC. + rtp_video_header.simulcastIdx = 1; + statistics_proxy_->OnSendEncodedImage(encoded_image, &rtp_video_header); + + // Forward 1 ms, reach timeout, substream 0 should have no resolution + // reported, but substream 1 should. + fake_clock_.AdvanceTimeMilliseconds(1); + stats = statistics_proxy_->GetStats(); + EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width); + EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height); + EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width); + EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height); +} + } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video/transport_adapter.cc b/media/webrtc/trunk/webrtc/video/transport_adapter.cc index 6f27d9972a..7b5a6962c4 100644 --- a/media/webrtc/trunk/webrtc/video/transport_adapter.cc +++ b/media/webrtc/trunk/webrtc/video/transport_adapter.cc @@ -18,24 +18,24 @@ TransportAdapter::TransportAdapter(newapi::Transport* transport) int TransportAdapter::SendPacket(int /*channel*/, const void* packet, - int length) { + size_t length) { if (enabled_.Value() == 0) return false; bool success = transport_->SendRtp(static_cast(packet), - static_cast(length)); - return success ? length : -1; + length); + return success ? static_cast(length) : -1; } int TransportAdapter::SendRTCPPacket(int /*channel*/, const void* packet, - int length) { + size_t length) { if (enabled_.Value() == 0) return false; bool success = transport_->SendRtcp(static_cast(packet), - static_cast(length)); - return success ? length : -1; + length); + return success ? static_cast(length) : -1; } void TransportAdapter::Enable() { diff --git a/media/webrtc/trunk/webrtc/video/transport_adapter.h b/media/webrtc/trunk/webrtc/video/transport_adapter.h index a9a72e1672..cd27d7cfe0 100644 --- a/media/webrtc/trunk/webrtc/video/transport_adapter.h +++ b/media/webrtc/trunk/webrtc/video/transport_adapter.h @@ -21,12 +21,10 @@ class TransportAdapter : public webrtc::Transport { public: explicit TransportAdapter(newapi::Transport* transport); - virtual int SendPacket(int /*channel*/, - const void* packet, - int length) OVERRIDE; - virtual int SendRTCPPacket(int /*channel*/, - const void* packet, - int length) OVERRIDE; + int SendPacket(int /*channel*/, const void* packet, size_t length) override; + int SendRTCPPacket(int /*channel*/, + const void* packet, + size_t length) override; void Enable(); void Disable(); diff --git a/media/webrtc/trunk/webrtc/video/video_loopback.cc b/media/webrtc/trunk/webrtc/video/video_loopback.cc new file mode 100644 index 0000000000..d183920b16 --- /dev/null +++ b/media/webrtc/trunk/webrtc/video/video_loopback.cc @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include + +#include + +#include "gflags/gflags.h" +#include "testing/gtest/include/gtest/gtest.h" + +#include "webrtc/test/field_trial.h" +#include "webrtc/test/run_test.h" +#include "webrtc/typedefs.h" +#include "webrtc/video/loopback.h" + +namespace webrtc { + +namespace flags { + +DEFINE_int32(width, 640, "Video width."); +size_t Width() { + return static_cast(FLAGS_width); +} + +DEFINE_int32(height, 480, "Video height."); +size_t Height() { + return static_cast(FLAGS_height); +} + +DEFINE_int32(fps, 30, "Frames per second."); +int Fps() { + return static_cast(FLAGS_fps); +} + +DEFINE_int32(min_bitrate, 50, "Minimum video bitrate."); +size_t MinBitrate() { + return static_cast(FLAGS_min_bitrate); +} + +DEFINE_int32(start_bitrate, 300, "Video starting bitrate."); +size_t StartBitrate() { + return static_cast(FLAGS_start_bitrate); +} + +DEFINE_int32(max_bitrate, 800, "Maximum video bitrate."); +size_t MaxBitrate() { + return static_cast(FLAGS_max_bitrate); +} + +int MinTransmitBitrate() { + return 0; +} // No min padding for regular video. + +DEFINE_string(codec, "VP8", "Video codec to use."); +std::string Codec() { + return static_cast(FLAGS_codec); +} + +DEFINE_int32(loss_percent, 0, "Percentage of packets randomly lost."); +int LossPercent() { + return static_cast(FLAGS_loss_percent); +} + +DEFINE_int32(link_capacity, + 0, + "Capacity (kbps) of the fake link. 0 means infinite."); +int LinkCapacity() { + return static_cast(FLAGS_link_capacity); +} + +DEFINE_int32(queue_size, 0, "Size of the bottleneck link queue in packets."); +int QueueSize() { + return static_cast(FLAGS_queue_size); +} + +DEFINE_int32(avg_propagation_delay_ms, + 0, + "Average link propagation delay in ms."); +int AvgPropagationDelayMs() { + return static_cast(FLAGS_avg_propagation_delay_ms); +} + +DEFINE_int32(std_propagation_delay_ms, + 0, + "Link propagation delay standard deviation in ms."); +int StdPropagationDelayMs() { + return static_cast(FLAGS_std_propagation_delay_ms); +} + +DEFINE_bool(logs, false, "print logs to stderr"); + +DEFINE_string( + force_fieldtrials, + "", + "Field trials control experimental feature code which can be forced. " + "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/" + " will assign the group Enable to field trial WebRTC-FooFeature. Multiple " + "trials are separated by \"/\""); +} // namespace flags + +void Loopback() { + test::Loopback::Config config{flags::Width(), + flags::Height(), + flags::Fps(), + flags::MinBitrate(), + flags::StartBitrate(), + flags::MaxBitrate(), + 0, // No min transmit bitrate. + flags::Codec(), + flags::LossPercent(), + flags::LinkCapacity(), + flags::QueueSize(), + flags::AvgPropagationDelayMs(), + flags::StdPropagationDelayMs(), + flags::FLAGS_logs}; + test::Loopback loopback(config); + loopback.Run(); +} +} // namespace webrtc + +int main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + google::ParseCommandLineFlags(&argc, &argv, true); + webrtc::test::InitFieldTrialsFromString( + webrtc::flags::FLAGS_force_fieldtrials); + webrtc::test::RunTest(webrtc::Loopback); + return 0; +} diff --git a/media/webrtc/trunk/webrtc/video/video_receive_stream.cc b/media/webrtc/trunk/webrtc/video/video_receive_stream.cc index 5b085bb856..126d485e58 100644 --- a/media/webrtc/trunk/webrtc/video/video_receive_stream.cc +++ b/media/webrtc/trunk/webrtc/video/video_receive_stream.cc @@ -10,11 +10,11 @@ #include "webrtc/video/video_receive_stream.h" -#include #include #include +#include "webrtc/base/checks.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/system_wrappers/interface/clock.h" #include "webrtc/system_wrappers/interface/logging.h" @@ -31,8 +31,77 @@ #include "webrtc/video_receive_stream.h" namespace webrtc { +std::string VideoReceiveStream::Decoder::ToString() const { + std::stringstream ss; + ss << "{decoder: " << (decoder != nullptr ? "(VideoDecoder)" : "nullptr"); + ss << ", payload_type: " << payload_type; + ss << ", payload_name: " << payload_name; + ss << ", is_renderer: " << (is_renderer ? "yes" : "no"); + ss << ", expected_delay_ms: " << expected_delay_ms; + ss << '}'; + + return ss.str(); +} + +std::string VideoReceiveStream::Config::ToString() const { + std::stringstream ss; + ss << "{decoders: ["; + for (size_t i = 0; i < decoders.size(); ++i) { + ss << decoders[i].ToString(); + if (i != decoders.size() - 1) + ss << ", "; + } + ss << ']'; + ss << ", rtp: " << rtp.ToString(); + ss << ", renderer: " << (renderer != nullptr ? "(renderer)" : "nullptr"); + ss << ", render_delay_ms: " << render_delay_ms; + ss << ", audio_channel_id: " << audio_channel_id; + ss << ", pre_decode_callback: " + << (pre_decode_callback != nullptr ? "(EncodedFrameObserver)" : "nullptr"); + ss << ", pre_render_callback: " + << (pre_render_callback != nullptr ? "(I420FrameCallback)" : "nullptr"); + ss << ", target_delay_ms: " << target_delay_ms; + ss << '}'; + + return ss.str(); +} + +std::string VideoReceiveStream::Config::Rtp::ToString() const { + std::stringstream ss; + ss << "{remote_ssrc: " << remote_ssrc; + ss << ", local_ssrc: " << local_ssrc; + ss << ", rtcp_mode: " << (rtcp_mode == newapi::kRtcpCompound + ? "kRtcpCompound" + : "kRtcpReducedSize"); + ss << ", rtcp_xr: "; + ss << "{receiver_reference_time_report: " + << (rtcp_xr.receiver_reference_time_report ? "on" : "off"); + ss << '}'; + ss << ", remb: " << (remb ? "on" : "off"); + ss << ", nack: {rtp_history_ms: " << nack.rtp_history_ms << '}'; + ss << ", fec: " << fec.ToString(); + ss << ", rtx: {"; + for (auto& kv : rtx) { + ss << kv.first << " -> "; + ss << "{ssrc: " << kv.second.ssrc; + ss << ", payload_type: " << kv.second.payload_type; + ss << '}'; + } + ss << '}'; + ss << ", extensions: ["; + for (size_t i = 0; i < extensions.size(); ++i) { + ss << extensions[i].ToString(); + if (i != extensions.size() - 1) + ss << ", "; + } + ss << ']'; + ss << '}'; + return ss.str(); +} + namespace internal { namespace { + VideoCodec CreateDecoderVideoCodec(const VideoReceiveStream::Decoder& decoder) { VideoCodec codec; memset(&codec, 0, sizeof(codec)); @@ -74,27 +143,27 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine, channel_(-1) { video_engine_base_ = ViEBase::GetInterface(video_engine); video_engine_base_->CreateReceiveChannel(channel_, base_channel); - assert(channel_ != -1); + DCHECK(channel_ != -1); rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine); - assert(rtp_rtcp_ != NULL); + DCHECK(rtp_rtcp_ != nullptr); // TODO(pbos): This is not fine grained enough... rtp_rtcp_->SetNACKStatus(channel_, config_.rtp.nack.rtp_history_ms > 0); rtp_rtcp_->SetKeyFrameRequestMethod(channel_, kViEKeyFrameRequestPliRtcp); SetRtcpMode(config_.rtp.rtcp_mode); - assert(config_.rtp.remote_ssrc != 0); + DCHECK(config_.rtp.remote_ssrc != 0); // TODO(pbos): What's an appropriate local_ssrc for receive-only streams? - assert(config_.rtp.local_ssrc != 0); - assert(config_.rtp.remote_ssrc != config_.rtp.local_ssrc); + DCHECK(config_.rtp.local_ssrc != 0); + DCHECK(config_.rtp.remote_ssrc != config_.rtp.local_ssrc); rtp_rtcp_->SetLocalSSRC(channel_, config_.rtp.local_ssrc); // TODO(pbos): Support multiple RTX, per video payload. Config::Rtp::RtxMap::const_iterator it = config_.rtp.rtx.begin(); if (it != config_.rtp.rtx.end()) { - assert(it->second.ssrc != 0); - assert(it->second.payload_type != 0); + DCHECK(it->second.ssrc != 0); + DCHECK(it->second.payload_type != 0); rtp_rtcp_->SetRemoteSSRCType(channel_, kViEStreamTypeRtx, it->second.ssrc); rtp_rtcp_->SetRtxReceivePayloadType(channel_, it->second.payload_type); @@ -105,19 +174,24 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine, for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) { const std::string& extension = config_.rtp.extensions[i].name; int id = config_.rtp.extensions[i].id; + // One-byte-extension local identifiers are in the range 1-14 inclusive. + DCHECK_GE(id, 1); + DCHECK_LE(id, 14); if (extension == RtpExtension::kTOffset) { - if (rtp_rtcp_->SetReceiveTimestampOffsetStatus(channel_, true, id) != 0) - abort(); + CHECK_EQ(0, + rtp_rtcp_->SetReceiveTimestampOffsetStatus(channel_, true, id)); } else if (extension == RtpExtension::kAbsSendTime) { - if (rtp_rtcp_->SetReceiveAbsoluteSendTimeStatus(channel_, true, id) != 0) - abort(); + CHECK_EQ(0, + rtp_rtcp_->SetReceiveAbsoluteSendTimeStatus(channel_, true, id)); + } else if (extension == RtpExtension::kVideoRotation) { + CHECK_EQ(0, rtp_rtcp_->SetReceiveVideoRotationStatus(channel_, true, id)); } else { - abort(); // Unsupported extension. + RTC_NOTREACHED() << "Unsupported RTP extension."; } } network_ = ViENetwork::GetInterface(video_engine); - assert(network_ != NULL); + DCHECK(network_ != nullptr); network_->RegisterSendTransport(channel_, transport_adapter_); @@ -125,16 +199,13 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine, if (config_.rtp.fec.ulpfec_payload_type != -1) { // ULPFEC without RED doesn't make sense. - assert(config_.rtp.fec.red_payload_type != -1); + DCHECK(config_.rtp.fec.red_payload_type != -1); VideoCodec codec; memset(&codec, 0, sizeof(codec)); codec.codecType = kVideoCodecULPFEC; strcpy(codec.plName, "ulpfec"); codec.plType = config_.rtp.fec.ulpfec_payload_type; - if (codec_->SetReceiveCodec(channel_, codec) != 0) { - LOG(LS_ERROR) << "Could not set ULPFEC codec. This shouldn't happen."; - abort(); - } + CHECK_EQ(0, codec_->SetReceiveCodec(channel_, codec)); } if (config_.rtp.fec.red_payload_type != -1) { VideoCodec codec; @@ -142,53 +213,40 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine, codec.codecType = kVideoCodecRED; strcpy(codec.plName, "red"); codec.plType = config_.rtp.fec.red_payload_type; - if (codec_->SetReceiveCodec(channel_, codec) != 0) { - LOG(LS_ERROR) << "Could not set RED codec. This shouldn't happen."; - abort(); - } + CHECK_EQ(0, codec_->SetReceiveCodec(channel_, codec)); } - stats_proxy_.reset(new ReceiveStatisticsProxy( - config_.rtp.local_ssrc, clock_, rtp_rtcp_, codec_, channel_)); + stats_proxy_.reset( + new ReceiveStatisticsProxy(config_.rtp.remote_ssrc, clock_)); - if (rtp_rtcp_->RegisterReceiveChannelRtcpStatisticsCallback( - channel_, stats_proxy_.get()) != 0) - abort(); + CHECK_EQ(0, rtp_rtcp_->RegisterReceiveChannelRtcpStatisticsCallback( + channel_, stats_proxy_.get())); + CHECK_EQ(0, rtp_rtcp_->RegisterReceiveChannelRtpStatisticsCallback( + channel_, stats_proxy_.get())); + CHECK_EQ(0, rtp_rtcp_->RegisterRtcpPacketTypeCounterObserver( + channel_, stats_proxy_.get())); + CHECK_EQ(0, codec_->RegisterDecoderObserver(channel_, *stats_proxy_)); - if (rtp_rtcp_->RegisterReceiveChannelRtpStatisticsCallback( - channel_, stats_proxy_.get()) != 0) - abort(); - - if (codec_->RegisterDecoderObserver(channel_, *stats_proxy_) != 0) - abort(); + video_engine_base_->RegisterReceiveStatisticsProxy(channel_, + stats_proxy_.get()); external_codec_ = ViEExternalCodec::GetInterface(video_engine); - assert(!config_.decoders.empty()); + DCHECK(!config_.decoders.empty()); for (size_t i = 0; i < config_.decoders.size(); ++i) { const Decoder& decoder = config_.decoders[i]; - if (external_codec_->RegisterExternalReceiveCodec( - channel_, - decoder.payload_type, - decoder.decoder, - decoder.renderer, - decoder.expected_delay_ms) != 0) { - // TODO(pbos): Abort gracefully? Can this be a runtime error? - abort(); - } + CHECK_EQ(0, external_codec_->RegisterExternalReceiveCodec( + channel_, decoder.payload_type, decoder.decoder, + decoder.is_renderer, decoder.expected_delay_ms)); VideoCodec codec = CreateDecoderVideoCodec(decoder); - if (codec_->SetReceiveCodec(channel_, codec) != 0) { - // TODO(pbos): Abort gracefully, this can be a runtime error. - // Factor out to an Init() method. - abort(); - } + CHECK_EQ(0, codec_->SetReceiveCodec(channel_, codec)); } render_ = ViERender::GetInterface(video_engine); - assert(render_ != NULL); + DCHECK(render_ != nullptr); - render_->AddRenderCallback(channel_, this); + render_->AddRenderer(channel_, kVideoI420, this); if (voice_engine && config_.audio_channel_id != -1) { video_engine_base_->SetVoiceEngine(voice_engine); @@ -220,7 +278,7 @@ VideoReceiveStream::~VideoReceiveStream() { network_->DeregisterSendTransport(channel_); - video_engine_base_->SetVoiceEngine(NULL); + video_engine_base_->SetVoiceEngine(nullptr); image_process_->Release(); external_codec_->Release(); codec_->DeregisterDecoderObserver(channel_); @@ -228,6 +286,7 @@ VideoReceiveStream::~VideoReceiveStream() { stats_proxy_.get()); rtp_rtcp_->DeregisterReceiveChannelRtcpStatisticsCallback(channel_, stats_proxy_.get()); + rtp_rtcp_->RegisterRtcpPacketTypeCounterObserver(channel_, nullptr); codec_->Release(); network_->Release(); render_->Release(); @@ -238,17 +297,13 @@ VideoReceiveStream::~VideoReceiveStream() { void VideoReceiveStream::Start() { transport_adapter_.Enable(); - if (render_->StartRender(channel_) != 0) - abort(); - if (video_engine_base_->StartReceive(channel_) != 0) - abort(); + CHECK_EQ(0, render_->StartRender(channel_)); + CHECK_EQ(0, video_engine_base_->StartReceive(channel_)); } void VideoReceiveStream::Stop() { - if (render_->StopRender(channel_) != 0) - abort(); - if (video_engine_base_->StopReceive(channel_) != 0) - abort(); + CHECK_EQ(0, render_->StopRender(channel_)); + CHECK_EQ(0, video_engine_base_->StopReceive(channel_)); transport_adapter_.Disable(); } @@ -257,13 +312,12 @@ VideoReceiveStream::Stats VideoReceiveStream::GetStats() const { } bool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) { - return network_->ReceivedRTCPPacket( - channel_, packet, static_cast(length)) == 0; + return network_->ReceivedRTCPPacket(channel_, packet, length) == 0; } bool VideoReceiveStream::DeliverRtp(const uint8_t* packet, size_t length) { - return network_->ReceivedRTPPacket( - channel_, packet, static_cast(length), PacketTime()) == 0; + return network_->ReceivedRTPPacket(channel_, packet, length, PacketTime()) == + 0; } void VideoReceiveStream::FrameCallback(I420VideoFrame* video_frame) { @@ -273,9 +327,25 @@ void VideoReceiveStream::FrameCallback(I420VideoFrame* video_frame) { config_.pre_render_callback->FrameCallback(video_frame); } -int32_t VideoReceiveStream::RenderFrame(const uint32_t stream_id, - I420VideoFrame& video_frame) { - if (config_.renderer != NULL) +int VideoReceiveStream::FrameSizeChange(unsigned int width, + unsigned int height, + unsigned int number_of_streams) { + return 0; +} + +int VideoReceiveStream::DeliverFrame(unsigned char* buffer, + size_t buffer_size, + uint32_t timestamp, + int64_t ntp_time_ms, + int64_t render_time_ms, + void* handle) { + CHECK(false) << "Renderer should be configured as kVideoI420 and never " + "receive callbacks on DeliverFrame."; + return 0; +} + +int VideoReceiveStream::DeliverI420Frame(const I420VideoFrame& video_frame) { + if (config_.renderer != nullptr) config_.renderer->RenderFrame( video_frame, video_frame.render_time_ms() - clock_->TimeInMilliseconds()); @@ -285,6 +355,12 @@ int32_t VideoReceiveStream::RenderFrame(const uint32_t stream_id, return 0; } +bool VideoReceiveStream::IsTextureSupported() { + if (config_.renderer == nullptr) + return false; + return config_.renderer->IsTextureSupported(); +} + void VideoReceiveStream::SignalNetworkState(Call::NetworkState state) { if (state == Call::kNetworkUp) SetRtcpMode(config_.rtp.rtcp_mode); diff --git a/media/webrtc/trunk/webrtc/video/video_receive_stream.h b/media/webrtc/trunk/webrtc/video/video_receive_stream.h index 2aa39e2389..dcc8122ee4 100644 --- a/media/webrtc/trunk/webrtc/video/video_receive_stream.h +++ b/media/webrtc/trunk/webrtc/video/video_receive_stream.h @@ -13,11 +13,11 @@ #include +#include "webrtc/base/scoped_ptr.h" #include "webrtc/call.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/modules/video_render/include/video_render_defines.h" #include "webrtc/system_wrappers/interface/clock.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/video/encoded_frame_callback_adapter.h" #include "webrtc/video/receive_statistics_proxy.h" #include "webrtc/video/transport_adapter.h" @@ -40,7 +40,7 @@ namespace internal { class VideoReceiveStream : public webrtc::VideoReceiveStream, public I420FrameCallback, - public VideoRenderCallback { + public ExternalRenderer { public: VideoReceiveStream(webrtc::VideoEngine* video_engine, const VideoReceiveStream::Config& config, @@ -49,16 +49,25 @@ class VideoReceiveStream : public webrtc::VideoReceiveStream, int base_channel); virtual ~VideoReceiveStream(); - virtual void Start() OVERRIDE; - virtual void Stop() OVERRIDE; - virtual Stats GetStats() const OVERRIDE; + void Start() override; + void Stop() override; + Stats GetStats() const override; // Overrides I420FrameCallback. - virtual void FrameCallback(I420VideoFrame* video_frame) OVERRIDE; + void FrameCallback(I420VideoFrame* video_frame) override; - // Overrides VideoRenderCallback. - virtual int32_t RenderFrame(const uint32_t stream_id, - I420VideoFrame& video_frame) OVERRIDE; + // Overrides ExternalRenderer. + int FrameSizeChange(unsigned int width, + unsigned int height, + unsigned int number_of_streams) override; + int DeliverFrame(unsigned char* buffer, + size_t buffer_size, + uint32_t timestamp, + int64_t ntp_time_ms, + int64_t render_time_ms, + void* handle) override; + int DeliverI420Frame(const I420VideoFrame& webrtc_frame) override; + bool IsTextureSupported() override; void SignalNetworkState(Call::NetworkState state); @@ -81,7 +90,7 @@ class VideoReceiveStream : public webrtc::VideoReceiveStream, ViERTP_RTCP* rtp_rtcp_; ViEImageProcess* image_process_; - scoped_ptr stats_proxy_; + rtc::scoped_ptr stats_proxy_; int channel_; }; diff --git a/media/webrtc/trunk/webrtc/video/video_send_stream.cc b/media/webrtc/trunk/webrtc/video/video_send_stream.cc index 489cd14081..9949f5017e 100644 --- a/media/webrtc/trunk/webrtc/video/video_send_stream.cc +++ b/media/webrtc/trunk/webrtc/video/video_send_stream.cc @@ -15,8 +15,10 @@ #include #include +#include "webrtc/base/checks.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/system_wrappers/interface/logging.h" +#include "webrtc/system_wrappers/interface/trace_event.h" #include "webrtc/video_engine/include/vie_base.h" #include "webrtc/video_engine/include/vie_capture.h" #include "webrtc/video_engine/include/vie_codec.h" @@ -33,8 +35,7 @@ VideoSendStream::Config::EncoderSettings::ToString() const { std::stringstream ss; ss << "{payload_name: " << payload_name; ss << ", payload_type: " << payload_type; - if (encoder != NULL) - ss << ", encoder: " << (encoder != NULL ? "(encoder)" : "NULL"); + ss << ", encoder: " << (encoder != nullptr ? "(VideoEncoder)" : "nullptr"); ss << '}'; return ss.str(); } @@ -42,13 +43,13 @@ VideoSendStream::Config::EncoderSettings::ToString() const { std::string VideoSendStream::Config::Rtp::Rtx::ToString() const { std::stringstream ss; - ss << "{ssrcs: {"; + ss << "{ssrcs: ["; for (size_t i = 0; i < ssrcs.size(); ++i) { ss << ssrcs[i]; if (i != ssrcs.size() - 1) - ss << "}, {"; + ss << ", "; } - ss << '}'; + ss << ']'; ss << ", payload_type: " << payload_type; ss << '}'; @@ -57,32 +58,26 @@ std::string VideoSendStream::Config::Rtp::Rtx::ToString() std::string VideoSendStream::Config::Rtp::ToString() const { std::stringstream ss; - ss << "{ssrcs: {"; + ss << "{ssrcs: ["; for (size_t i = 0; i < ssrcs.size(); ++i) { ss << ssrcs[i]; if (i != ssrcs.size() - 1) - ss << "}, {"; + ss << ", "; } - ss << '}'; - + ss << ']'; ss << ", max_packet_size: " << max_packet_size; - - ss << ", extensions: {"; + ss << ", extensions: ["; for (size_t i = 0; i < extensions.size(); ++i) { ss << extensions[i].ToString(); if (i != extensions.size() - 1) - ss << "}, {"; + ss << ", "; } - ss << '}'; + ss << ']'; - if (nack.rtp_history_ms != 0) - ss << ", nack.rtp_history_ms: " << nack.rtp_history_ms; - if (fec.ulpfec_payload_type != -1 || fec.red_payload_type != -1) - ss << ", fec: " << fec.ToString(); - if (rtx.payload_type != 0 || !rtx.ssrcs.empty()) - ss << ", rtx: " << rtx.ToString(); - if (c_name != "") - ss << ", c_name: " << c_name; + ss << ", nack: {rtp_history_ms: " << nack.rtp_history_ms << '}'; + ss << ", fec: " << fec.ToString(); + ss << ", rtx: " << rtx.ToString(); + ss << ", c_name: " << c_name; ss << '}'; return ss.str(); } @@ -91,17 +86,17 @@ std::string VideoSendStream::Config::ToString() const { std::stringstream ss; ss << "{encoder_settings: " << encoder_settings.ToString(); ss << ", rtp: " << rtp.ToString(); - if (pre_encode_callback != NULL) - ss << ", (pre_encode_callback)"; - if (post_encode_callback != NULL) - ss << ", (post_encode_callback)"; - if (local_renderer != NULL) { - ss << ", (local_renderer, render_delay_ms: " << render_delay_ms << ")"; - } - if (target_delay_ms > 0) - ss << ", target_delay_ms: " << target_delay_ms; - if (suspend_below_min_bitrate) - ss << ", suspend_below_min_bitrate: on"; + ss << ", pre_encode_callback: " + << (pre_encode_callback != nullptr ? "(I420FrameCallback)" : "nullptr"); + ss << ", post_encode_callback: " << (post_encode_callback != nullptr + ? "(EncodedFrameObserver)" + : "nullptr"); + ss << "local_renderer: " << (local_renderer != nullptr ? "(VideoRenderer)" + : "nullptr"); + ss << ", render_delay_ms: " << render_delay_ms; + ss << ", target_delay_ms: " << target_delay_ms; + ss << ", suspend_below_min_bitrate: " << (suspend_below_min_bitrate ? "on" + : "off"); ss << '}'; return ss.str(); } @@ -114,38 +109,39 @@ VideoSendStream::VideoSendStream( const VideoSendStream::Config& config, const VideoEncoderConfig& encoder_config, const std::map& suspended_ssrcs, - int base_channel, - int start_bitrate_bps) + int base_channel) : transport_adapter_(transport), encoded_frame_proxy_(config.post_encode_callback), config_(config), - start_bitrate_bps_(start_bitrate_bps), suspended_ssrcs_(suspended_ssrcs), - external_codec_(NULL), + external_codec_(nullptr), channel_(-1), - use_default_bitrate_(true), - stats_proxy_(config) { + use_config_bitrate_(true), + stats_proxy_(Clock::GetRealTimeClock(), config) { video_engine_base_ = ViEBase::GetInterface(video_engine); - video_engine_base_->CreateChannel(channel_, base_channel); - assert(channel_ != -1); - assert(start_bitrate_bps_ > 0); + video_engine_base_->CreateChannelWithoutDefaultEncoder(channel_, + base_channel); + DCHECK(channel_ != -1); rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine); - assert(rtp_rtcp_ != NULL); + DCHECK(rtp_rtcp_ != nullptr); - assert(config_.rtp.ssrcs.size() > 0); + DCHECK(!config_.rtp.ssrcs.empty()); for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) { const std::string& extension = config_.rtp.extensions[i].name; int id = config_.rtp.extensions[i].id; + // One-byte-extension local identifiers are in the range 1-14 inclusive. + DCHECK_GE(id, 1); + DCHECK_LE(id, 14); if (extension == RtpExtension::kTOffset) { - if (rtp_rtcp_->SetSendTimestampOffsetStatus(channel_, true, id) != 0) - abort(); + CHECK_EQ(0, rtp_rtcp_->SetSendTimestampOffsetStatus(channel_, true, id)); } else if (extension == RtpExtension::kAbsSendTime) { - if (rtp_rtcp_->SetSendAbsoluteSendTimeStatus(channel_, true, id) != 0) - abort(); + CHECK_EQ(0, rtp_rtcp_->SetSendAbsoluteSendTimeStatus(channel_, true, id)); + } else if (extension == RtpExtension::kVideoRotation) { + CHECK_EQ(0, rtp_rtcp_->SetSendVideoRotationStatus(channel_, true, id)); } else { - abort(); // Unsupported extension. + RTC_NOTREACHED() << "Registering unsupported RTP extension."; } } @@ -153,7 +149,7 @@ VideoSendStream::VideoSendStream( // Enable NACK, FEC or both. if (config_.rtp.fec.red_payload_type != -1) { - assert(config_.rtp.fec.ulpfec_payload_type != -1); + DCHECK(config_.rtp.fec.ulpfec_payload_type != -1); if (config_.rtp.nack.rtp_history_ms > 0) { rtp_rtcp_->SetHybridNACKFECStatus( channel_, @@ -174,7 +170,8 @@ VideoSendStream::VideoSendStream( ConfigureSsrcs(); char rtcp_cname[ViERTP_RTCP::KMaxRTCPCNameLength]; - assert(config_.rtp.c_name.length() < ViERTP_RTCP::KMaxRTCPCNameLength); + DCHECK_LT(config_.rtp.c_name.length(), + static_cast(ViERTP_RTCP::KMaxRTCPCNameLength)); strncpy(rtcp_cname, config_.rtp.c_name.c_str(), sizeof(rtcp_cname) - 1); rtcp_cname[sizeof(rtcp_cname) - 1] = '\0'; @@ -185,33 +182,32 @@ VideoSendStream::VideoSendStream( capture_->ConnectCaptureDevice(capture_id_, channel_); network_ = ViENetwork::GetInterface(video_engine); - assert(network_ != NULL); + DCHECK(network_ != nullptr); network_->RegisterSendTransport(channel_, transport_adapter_); // 28 to match packet overhead in ModuleRtpRtcpImpl. network_->SetMTU(channel_, static_cast(config_.rtp.max_packet_size + 28)); - assert(config.encoder_settings.encoder != NULL); - assert(config.encoder_settings.payload_type >= 0); - assert(config.encoder_settings.payload_type <= 127); + DCHECK(config.encoder_settings.encoder != nullptr); + DCHECK_GE(config.encoder_settings.payload_type, 0); + DCHECK_LE(config.encoder_settings.payload_type, 127); external_codec_ = ViEExternalCodec::GetInterface(video_engine); - if (external_codec_->RegisterExternalSendCodec( - channel_, - config.encoder_settings.payload_type, - config.encoder_settings.encoder, - false) != 0) { - abort(); - } + CHECK_EQ(0, external_codec_->RegisterExternalSendCodec( + channel_, config.encoder_settings.payload_type, + config.encoder_settings.encoder, false)); codec_ = ViECodec::GetInterface(video_engine); - if (!ReconfigureVideoEncoder(encoder_config)) - abort(); + CHECK(ReconfigureVideoEncoder(encoder_config)); if (overuse_observer) video_engine_base_->RegisterCpuOveruseObserver(channel_, overuse_observer); + // Registered regardless of monitoring, used for stats. + video_engine_base_->RegisterCpuOveruseMetricsObserver(channel_, + &stats_proxy_); video_engine_base_->RegisterSendSideDelayObserver(channel_, &stats_proxy_); + video_engine_base_->RegisterSendStatisticsProxy(channel_, &stats_proxy_); image_process_ = ViEImageProcess::GetInterface(video_engine); image_process_->RegisterPreEncodeCallback(channel_, @@ -228,11 +224,11 @@ VideoSendStream::VideoSendStream( &stats_proxy_); rtp_rtcp_->RegisterSendChannelRtpStatisticsCallback(channel_, &stats_proxy_); + rtp_rtcp_->RegisterRtcpPacketTypeCounterObserver(channel_, &stats_proxy_); rtp_rtcp_->RegisterSendBitrateObserver(channel_, &stats_proxy_); rtp_rtcp_->RegisterSendFrameCountObserver(channel_, &stats_proxy_); codec_->RegisterEncoderObserver(channel_, stats_proxy_); - capture_->RegisterObserver(capture_id_, stats_proxy_); } VideoSendStream::~VideoSendStream() { @@ -241,6 +237,7 @@ VideoSendStream::~VideoSendStream() { rtp_rtcp_->DeregisterSendFrameCountObserver(channel_, &stats_proxy_); rtp_rtcp_->DeregisterSendBitrateObserver(channel_, &stats_proxy_); + rtp_rtcp_->RegisterRtcpPacketTypeCounterObserver(channel_, nullptr); rtp_rtcp_->DeregisterSendChannelRtpStatisticsCallback(channel_, &stats_proxy_); rtp_rtcp_->DeregisterSendChannelRtcpStatisticsCallback(channel_, @@ -268,12 +265,13 @@ VideoSendStream::~VideoSendStream() { rtp_rtcp_->Release(); } -void VideoSendStream::SwapFrame(I420VideoFrame* frame) { +void VideoSendStream::IncomingCapturedFrame(const I420VideoFrame& frame) { // TODO(pbos): Local rendering should not be done on the capture thread. - if (config_.local_renderer != NULL) - config_.local_renderer->RenderFrame(*frame, 0); + if (config_.local_renderer != nullptr) + config_.local_renderer->RenderFrame(frame, 0); - external_capture_->SwapFrame(frame); + stats_proxy_.OnIncomingFrame(); + external_capture_->IncomingFrame(frame); } VideoSendStreamInput* VideoSendStream::Input() { return this; } @@ -292,10 +290,11 @@ void VideoSendStream::Stop() { bool VideoSendStream::ReconfigureVideoEncoder( const VideoEncoderConfig& config) { + TRACE_EVENT0("webrtc", "VideoSendStream::(Re)configureVideoEncoder"); LOG(LS_INFO) << "(Re)configureVideoEncoder: " << config.ToString(); const std::vector& streams = config.streams; - assert(!streams.empty()); - assert(config_.rtp.ssrcs.size() >= streams.size()); + DCHECK(!streams.empty()); + DCHECK_GE(config_.rtp.ssrcs.size(), streams.size()); VideoCodec video_codec; memset(&video_codec, 0, sizeof(video_codec)); @@ -332,16 +331,30 @@ bool VideoSendStream::ReconfigureVideoEncoder( } if (video_codec.codecType == kVideoCodecVP8) { - if (config.encoder_specific_settings != NULL) { + if (config.encoder_specific_settings != nullptr) { video_codec.codecSpecific.VP8 = *reinterpret_cast( config.encoder_specific_settings); } video_codec.codecSpecific.VP8.numberOfTemporalLayers = static_cast( streams.back().temporal_layer_thresholds_bps.size() + 1); + } else if (video_codec.codecType == kVideoCodecVP9) { + if (config.encoder_specific_settings != nullptr) { + video_codec.codecSpecific.VP9 = *reinterpret_cast( + config.encoder_specific_settings); + } + video_codec.codecSpecific.VP9.numberOfTemporalLayers = + static_cast( + streams.back().temporal_layer_thresholds_bps.size() + 1); + } else if (video_codec.codecType == kVideoCodecH264) { + if (config.encoder_specific_settings != nullptr) { + video_codec.codecSpecific.H264 = *reinterpret_cast( + config.encoder_specific_settings); + } } else { // TODO(pbos): Support encoder_settings codec-agnostically. - assert(config.encoder_specific_settings == NULL); + DCHECK(config.encoder_specific_settings == nullptr) + << "Encoder-specific settings for codec type not wired up."; } strncpy(video_codec.plName, @@ -352,18 +365,18 @@ bool VideoSendStream::ReconfigureVideoEncoder( video_codec.numberOfSimulcastStreams = static_cast(streams.size()); video_codec.minBitrate = streams[0].min_bitrate_bps / 1000; - assert(streams.size() <= kMaxSimulcastStreams); + DCHECK_LE(streams.size(), static_cast(kMaxSimulcastStreams)); for (size_t i = 0; i < streams.size(); ++i) { SimulcastStream* sim_stream = &video_codec.simulcastStream[i]; - assert(streams[i].width > 0); - assert(streams[i].height > 0); - assert(streams[i].max_framerate > 0); + DCHECK_GT(streams[i].width, 0u); + DCHECK_GT(streams[i].height, 0u); + DCHECK_GT(streams[i].max_framerate, 0); // Different framerates not supported per stream at the moment. - assert(streams[i].max_framerate == streams[0].max_framerate); - assert(streams[i].min_bitrate_bps >= 0); - assert(streams[i].target_bitrate_bps >= streams[i].min_bitrate_bps); - assert(streams[i].max_bitrate_bps >= streams[i].target_bitrate_bps); - assert(streams[i].max_qp >= 0); + DCHECK_EQ(streams[i].max_framerate, streams[0].max_framerate); + DCHECK_GE(streams[i].min_bitrate_bps, 0); + DCHECK_GE(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps); + DCHECK_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps); + DCHECK_GE(streams[i].max_qp, 0); sim_stream->width = static_cast(streams[i].width); sim_stream->height = static_cast(streams[i].height); @@ -385,52 +398,41 @@ bool VideoSendStream::ReconfigureVideoEncoder( video_codec.qpMax = std::max(video_codec.qpMax, static_cast(streams[i].max_qp)); } - unsigned int start_bitrate_bps; - if (codec_->GetCodecTargetBitrate(channel_, &start_bitrate_bps) != 0 || - use_default_bitrate_) { - start_bitrate_bps = start_bitrate_bps_; - } - video_codec.startBitrate = - static_cast(start_bitrate_bps) / 1000; + + // Set to zero to not update the bitrate controller from ViEEncoder, as + // the bitrate controller is already set from Call. + video_codec.startBitrate = 0; if (video_codec.minBitrate < kViEMinCodecBitrate) video_codec.minBitrate = kViEMinCodecBitrate; if (video_codec.maxBitrate < kViEMinCodecBitrate) video_codec.maxBitrate = kViEMinCodecBitrate; - if (video_codec.startBitrate < video_codec.minBitrate) - video_codec.startBitrate = video_codec.minBitrate; - if (video_codec.startBitrate > video_codec.maxBitrate) - video_codec.startBitrate = video_codec.maxBitrate; - if (video_codec.startBitrate < video_codec.minBitrate) - video_codec.startBitrate = video_codec.minBitrate; - if (video_codec.startBitrate > video_codec.maxBitrate) - video_codec.startBitrate = video_codec.maxBitrate; - - assert(streams[0].max_framerate > 0); + DCHECK_GT(streams[0].max_framerate, 0); video_codec.maxFramerate = streams[0].max_framerate; if (codec_->SetSendCodec(channel_, video_codec) != 0) return false; - assert(config.min_transmit_bitrate_bps >= 0); + DCHECK_GE(config.min_transmit_bitrate_bps, 0); rtp_rtcp_->SetMinTransmitBitrate(channel_, config.min_transmit_bitrate_bps / 1000); - use_default_bitrate_ = false; + encoder_config_ = config; + use_config_bitrate_ = false; return true; } bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { - return network_->ReceivedRTCPPacket( - channel_, packet, static_cast(length)) == 0; + return network_->ReceivedRTCPPacket(channel_, packet, length) == 0; } -VideoSendStream::Stats VideoSendStream::GetStats() const { +VideoSendStream::Stats VideoSendStream::GetStats() { return stats_proxy_.GetStats(); } void VideoSendStream::ConfigureSsrcs() { + rtp_rtcp_->SetLocalSSRC(channel_, config_.rtp.ssrcs.front()); for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { uint32_t ssrc = config_.rtp.ssrcs[i]; rtp_rtcp_->SetLocalSSRC( @@ -441,12 +443,11 @@ void VideoSendStream::ConfigureSsrcs() { } if (config_.rtp.rtx.ssrcs.empty()) { - assert(!config_.rtp.rtx.pad_with_redundant_payloads); return; } // Set up RTX. - assert(config_.rtp.rtx.ssrcs.size() == config_.rtp.ssrcs.size()); + DCHECK_EQ(config_.rtp.rtx.ssrcs.size(), config_.rtp.ssrcs.size()); for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; rtp_rtcp_->SetLocalSSRC(channel_, @@ -458,11 +459,7 @@ void VideoSendStream::ConfigureSsrcs() { rtp_rtcp_->SetRtpStateForSsrc(channel_, ssrc, it->second); } - if (config_.rtp.rtx.pad_with_redundant_payloads) { - rtp_rtcp_->SetPadWithRedundantPayloads(channel_, true); - } - - assert(config_.rtp.rtx.payload_type >= 0); + DCHECK_GE(config_.rtp.rtx.payload_type, 0); rtp_rtcp_->SetRtxSendPayloadType(channel_, config_.rtp.rtx.payload_type); } @@ -492,12 +489,22 @@ void VideoSendStream::SignalNetworkState(Call::NetworkState state) { rtp_rtcp_->SetRTCPStatus(channel_, kRtcpNone); } -int VideoSendStream::GetPacerQueuingDelayMs() const { - int pacer_delay_ms = 0; +int64_t VideoSendStream::GetPacerQueuingDelayMs() const { + int64_t pacer_delay_ms = 0; if (rtp_rtcp_->GetPacerQueuingDelayMs(channel_, &pacer_delay_ms) != 0) { return 0; } return pacer_delay_ms; } + +int64_t VideoSendStream::GetRtt() const { + webrtc::RtcpStatistics rtcp_stats; + int64_t rtt_ms; + if (rtp_rtcp_->GetSendChannelRtcpStatistics(channel_, rtcp_stats, rtt_ms) == + 0) { + return rtt_ms; + } + return -1; +} } // namespace internal } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video/video_send_stream.h b/media/webrtc/trunk/webrtc/video/video_send_stream.h index 873785dc9e..a5cd1ce77c 100644 --- a/media/webrtc/trunk/webrtc/video/video_send_stream.h +++ b/media/webrtc/trunk/webrtc/video/video_send_stream.h @@ -48,40 +48,40 @@ class VideoSendStream : public webrtc::VideoSendStream, const VideoSendStream::Config& config, const VideoEncoderConfig& encoder_config, const std::map& suspended_ssrcs, - int base_channel, - int start_bitrate); + int base_channel); virtual ~VideoSendStream(); - virtual void Start() OVERRIDE; - virtual void Stop() OVERRIDE; + void Start() override; + void Stop() override; - virtual bool ReconfigureVideoEncoder( - const VideoEncoderConfig& config) OVERRIDE; + bool ReconfigureVideoEncoder(const VideoEncoderConfig& config) override; - virtual Stats GetStats() const OVERRIDE; + Stats GetStats() override; bool DeliverRtcp(const uint8_t* packet, size_t length); // From VideoSendStreamInput. - virtual void SwapFrame(I420VideoFrame* frame) OVERRIDE; + void IncomingCapturedFrame(const I420VideoFrame& frame) override; // From webrtc::VideoSendStream. - virtual VideoSendStreamInput* Input() OVERRIDE; + VideoSendStreamInput* Input() override; typedef std::map RtpStateMap; RtpStateMap GetRtpStates() const; void SignalNetworkState(Call::NetworkState state); - int GetPacerQueuingDelayMs() const; + int64_t GetPacerQueuingDelayMs() const; + + int64_t GetRtt() const; private: void ConfigureSsrcs(); TransportAdapter transport_adapter_; EncodedFrameCallbackAdapter encoded_frame_proxy_; const VideoSendStream::Config config_; - const int start_bitrate_bps_; + VideoEncoderConfig encoder_config_; std::map suspended_ssrcs_; ViEBase* video_engine_base_; @@ -99,7 +99,7 @@ class VideoSendStream : public webrtc::VideoSendStream, // Used as a workaround to indicate that we should be using the configured // start bitrate initially, instead of the one reported by VideoEngine (which // defaults to too high). - bool use_default_bitrate_; + bool use_config_bitrate_; SendStatisticsProxy stats_proxy_; }; diff --git a/media/webrtc/trunk/webrtc/video/video_send_stream_tests.cc b/media/webrtc/trunk/webrtc/video/video_send_stream_tests.cc index 3ab1127444..428a2735c1 100644 --- a/media/webrtc/trunk/webrtc/video/video_send_stream_tests.cc +++ b/media/webrtc/trunk/webrtc/video/video_send_stream_tests.cc @@ -8,13 +8,15 @@ * be found in the AUTHORS file in the root of the source tree. */ #include // max +#include #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/checks.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/call.h" #include "webrtc/common_video/interface/i420_video_frame.h" #include "webrtc/common_video/interface/native_handle.h" -#include "webrtc/common_video/interface/texture_video_frame.h" #include "webrtc/frame_callback.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" @@ -23,8 +25,6 @@ #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/event_wrapper.h" #include "webrtc/system_wrappers/interface/ref_count.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/system_wrappers/interface/scoped_vector.h" #include "webrtc/system_wrappers/interface/sleep.h" #include "webrtc/system_wrappers/interface/thread_wrapper.h" #include "webrtc/system_wrappers/interface/logging.h" @@ -32,6 +32,7 @@ #include "webrtc/test/configurable_frame_size_encoder.h" #include "webrtc/test/null_transport.h" #include "webrtc/test/testsupport/perf_test.h" +#include "webrtc/video/send_statistics_proxy.h" #include "webrtc/video/transport_adapter.h" #include "webrtc/video_send_stream.h" @@ -45,15 +46,15 @@ void ExpectEqualTextureFrames(const I420VideoFrame& frame1, const I420VideoFrame& frame2); void ExpectEqualBufferFrames(const I420VideoFrame& frame1, const I420VideoFrame& frame2); -void ExpectEqualFramesVector(const std::vector& frames1, - const std::vector& frames2); -I420VideoFrame* CreateI420VideoFrame(int width, int height, uint8_t data); +void ExpectEqualFramesVector(const std::vector& frames1, + const std::vector& frames2); +I420VideoFrame CreateI420VideoFrame(int width, int height, uint8_t data); class FakeNativeHandle : public NativeHandle { public: FakeNativeHandle() {} virtual ~FakeNativeHandle() {} - virtual void* GetHandle() { return NULL; } + virtual void* GetHandle() { return nullptr; } }; class VideoSendStreamTest : public test::CallTest { @@ -94,7 +95,7 @@ TEST_F(VideoSendStreamTest, SupportsCName) { CNameObserver() : SendTest(kDefaultTimeoutMs) {} private: - virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtcp(const uint8_t* packet, size_t length) override { RTCPUtility::RTCPParserV2 parser(packet, length, true); EXPECT_TRUE(parser.IsValid()); @@ -111,14 +112,13 @@ TEST_F(VideoSendStreamTest, SupportsCName) { return SEND_PACKET; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->rtp.c_name = kCName; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for RTCP with CNAME."; } @@ -136,7 +136,7 @@ TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) { kRtpExtensionAbsoluteSendTime, kAbsSendTimeExtensionId)); } - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { RTPHeader header; EXPECT_TRUE(parser_->Parse(packet, length, &header)); @@ -149,15 +149,14 @@ TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) { return SEND_PACKET; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->rtp.extensions.push_back( RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId)); } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for single RTP packet."; } @@ -168,16 +167,18 @@ TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) { TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) { static const uint8_t kTOffsetExtensionId = 13; + static const int kEncodeDelayMs = 5; class TransmissionTimeOffsetObserver : public test::SendTest { public: TransmissionTimeOffsetObserver() - : SendTest(kDefaultTimeoutMs), encoder_(Clock::GetRealTimeClock()) { + : SendTest(kDefaultTimeoutMs), + encoder_(Clock::GetRealTimeClock(), kEncodeDelayMs) { EXPECT_TRUE(parser_->RegisterRtpHeaderExtension( kRtpExtensionTransmissionTimeOffset, kTOffsetExtensionId)); } private: - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { RTPHeader header; EXPECT_TRUE(parser_->Parse(packet, length, &header)); @@ -190,36 +191,20 @@ TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) { return SEND_PACKET; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->encoder_settings.encoder = &encoder_; send_config->rtp.extensions.push_back( RtpExtension(RtpExtension::kTOffset, kTOffsetExtensionId)); } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for a single RTP packet."; } - class DelayedEncoder : public test::FakeEncoder { - public: - explicit DelayedEncoder(Clock* clock) : test::FakeEncoder(clock) {} - virtual int32_t Encode( - const I420VideoFrame& input_image, - const CodecSpecificInfo* codec_specific_info, - const std::vector* frame_types) OVERRIDE { - // A delay needs to be introduced to assure that we get a timestamp - // offset. - SleepMs(5); - return FakeEncoder::Encode( - input_image, codec_specific_info, frame_types); - } - }; - - DelayedEncoder encoder_; + test::DelayedEncoder encoder_; } test; RunBaseTest(&test); @@ -237,11 +222,9 @@ class FakeReceiveStatistics : public NullReceiveStatistics { stats_map_[send_ssrc] = lossy_stats_.get(); } - virtual StatisticianMap GetActiveStatisticians() const OVERRIDE { - return stats_map_; - } + StatisticianMap GetActiveStatisticians() const override { return stats_map_; } - virtual StreamStatistician* GetStatistician(uint32_t ssrc) const OVERRIDE { + StreamStatistician* GetStatistician(uint32_t ssrc) const override { return lossy_stats_.get(); } @@ -255,58 +238,35 @@ class FakeReceiveStatistics : public NullReceiveStatistics { stats_.cumulative_lost = cumulative_lost; stats_.extended_max_sequence_number = extended_max_sequence_number; } - virtual bool GetStatistics(RtcpStatistics* statistics, - bool reset) OVERRIDE { + bool GetStatistics(RtcpStatistics* statistics, bool reset) override { *statistics = stats_; return true; } - virtual void GetDataCounters(uint32_t* bytes_received, - uint32_t* packets_received) const OVERRIDE { + void GetDataCounters(size_t* bytes_received, + uint32_t* packets_received) const override { *bytes_received = 0; *packets_received = 0; } - virtual uint32_t BitrateReceived() const OVERRIDE { return 0; } - virtual void ResetStatistics() OVERRIDE {} - virtual bool IsRetransmitOfOldPacket(const RTPHeader& header, - int min_rtt) const OVERRIDE { + void GetReceiveStreamDataCounters( + StreamDataCounters* data_counters) const override {} + uint32_t BitrateReceived() const override { return 0; } + void ResetStatistics() override {} + bool IsRetransmitOfOldPacket(const RTPHeader& header, + int64_t min_rtt) const override { return false; } - virtual bool IsPacketInOrder(uint16_t sequence_number) const OVERRIDE { + bool IsPacketInOrder(uint16_t sequence_number) const override { return true; } RtcpStatistics stats_; }; - scoped_ptr lossy_stats_; + rtc::scoped_ptr lossy_stats_; StatisticianMap stats_map_; }; -TEST_F(VideoSendStreamTest, SwapsI420VideoFrames) { - static const size_t kWidth = 320; - static const size_t kHeight = 240; - - test::NullTransport transport; - Call::Config call_config(&transport); - CreateSenderCall(call_config); - - CreateSendConfig(1); - CreateStreams(); - send_stream_->Start(); - - I420VideoFrame frame; - frame.CreateEmptyFrame( - kWidth, kHeight, kWidth, (kWidth + 1) / 2, (kWidth + 1) / 2); - uint8_t* old_y_buffer = frame.buffer(kYPlane); - - send_stream_->Input()->SwapFrame(&frame); - - EXPECT_NE(frame.buffer(kYPlane), old_y_buffer); - - DestroyStreams(); -} - TEST_F(VideoSendStreamTest, SupportsFec) { class FecObserver : public test::SendTest { public: @@ -320,7 +280,7 @@ TEST_F(VideoSendStreamTest, SupportsFec) { } private: - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { RTPHeader header; EXPECT_TRUE(parser_->Parse(packet, length, &header)); @@ -329,8 +289,8 @@ TEST_F(VideoSendStreamTest, SupportsFec) { // Receive statistics reporting having lost 50% of the packets. FakeReceiveStatistics lossy_receive_stats( kSendSsrcs[0], header.sequenceNumber, send_count_ / 2, 127); - RTCPSender rtcp_sender( - 0, false, Clock::GetRealTimeClock(), &lossy_receive_stats); + RTCPSender rtcp_sender(0, false, Clock::GetRealTimeClock(), + &lossy_receive_stats, nullptr); EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_)); rtcp_sender.SetRTCPStatus(kRtcpNonCompound); @@ -357,15 +317,14 @@ TEST_F(VideoSendStreamTest, SupportsFec) { return SEND_PACKET; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->rtp.fec.red_payload_type = kRedPayloadType; send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets."; } @@ -395,7 +354,7 @@ void VideoSendStreamTest::TestNackRetransmission( } private: - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { RTPHeader header; EXPECT_TRUE(parser_->Parse(packet, length, &header)); @@ -405,7 +364,7 @@ void VideoSendStreamTest::TestNackRetransmission( nacked_sequence_number_ = nack_sequence_number; NullReceiveStatistics null_stats; RTCPSender rtcp_sender( - 0, false, Clock::GetRealTimeClock(), &null_stats); + 0, false, Clock::GetRealTimeClock(), &null_stats, nullptr); EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_)); rtcp_sender.SetRTCPStatus(kRtcpNonCompound); @@ -437,17 +396,16 @@ void VideoSendStreamTest::TestNackRetransmission( return SEND_PACKET; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; send_config->rtp.rtx.payload_type = retransmit_payload_type_; if (retransmit_ssrc_ != kSendSsrcs[0]) send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_); } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for NACK retransmission."; } @@ -477,18 +435,18 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format, // Use a fake encoder to output a frame of every size in the range [90, 290], // for each size making sure that the exact number of payload bytes received // is correct and that packets are fragmented to respect max packet size. - static const uint32_t kMaxPacketSize = 128; - static const uint32_t start = 90; - static const uint32_t stop = 290; + static const size_t kMaxPacketSize = 128; + static const size_t start = 90; + static const size_t stop = 290; // Observer that verifies that the expected number of packets and bytes // arrive for each frame size, from start_size to stop_size. class FrameFragmentationTest : public test::SendTest, public EncodedFrameObserver { public: - FrameFragmentationTest(uint32_t max_packet_size, - uint32_t start_size, - uint32_t stop_size, + FrameFragmentationTest(size_t max_packet_size, + size_t start_size, + size_t stop_size, bool test_generic_packetization, bool use_fec) : SendTest(kLongTimeoutMs), @@ -503,16 +461,16 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format, accumulated_payload_(0), fec_packet_received_(false), current_size_rtp_(start_size), - current_size_frame_(start_size) { + current_size_frame_(static_cast(start_size)) { // Fragmentation required, this test doesn't make sense without it. - encoder_.SetFrameSize(start); - assert(stop_size > max_packet_size); + encoder_.SetFrameSize(start_size); + DCHECK_GT(stop_size, max_packet_size); transport_adapter_.Enable(); } private: - virtual Action OnSendRtp(const uint8_t* packet, size_t size) OVERRIDE { - uint32_t length = static_cast(size); + Action OnSendRtp(const uint8_t* packet, size_t size) override { + size_t length = size; RTPHeader header; EXPECT_TRUE(parser_->Parse(packet, length, &header)); @@ -534,7 +492,7 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format, TriggerLossReport(header); if (test_generic_packetization_) { - uint32_t overhead = header.headerLength + header.paddingLength + + size_t overhead = header.headerLength + header.paddingLength + (1 /* Generic header */); if (use_fec_) overhead += 1; // RED for FEC header. @@ -587,8 +545,8 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format, // Receive statistics reporting having lost 50% of the packets. FakeReceiveStatistics lossy_receive_stats( kSendSsrcs[0], header.sequenceNumber, packet_count_ / 2, 127); - RTCPSender rtcp_sender( - 0, false, Clock::GetRealTimeClock(), &lossy_receive_stats); + RTCPSender rtcp_sender(0, false, Clock::GetRealTimeClock(), + &lossy_receive_stats, nullptr); EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_)); rtcp_sender.SetRTCPStatus(kRtcpNonCompound); @@ -607,13 +565,19 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format, current_size_frame_.Value() < static_cast(stop_size_)) { ++current_size_frame_; } - encoder_.SetFrameSize(current_size_frame_.Value()); + encoder_.SetFrameSize(static_cast(current_size_frame_.Value())); } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + Call::Config GetSenderCallConfig() override { + Call::Config config(SendTransport()); + const int kMinBitrateBps = 30000; + config.bitrate_config.min_bitrate_bps = kMinBitrateBps; + return config; + } + + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { if (use_fec_) { send_config->rtp.fec.red_payload_type = kRedPayloadType; send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; @@ -633,7 +597,7 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format, RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId)); } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while observing incoming RTP packets."; } @@ -641,17 +605,17 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format, internal::TransportAdapter transport_adapter_; test::ConfigurableFrameSizeEncoder encoder_; - const uint32_t max_packet_size_; - const uint32_t stop_size_; + const size_t max_packet_size_; + const size_t stop_size_; const bool test_generic_packetization_; const bool use_fec_; uint32_t packet_count_; - uint32_t accumulated_size_; - uint32_t accumulated_payload_; + size_t accumulated_size_; + size_t accumulated_payload_; bool fec_packet_received_; - uint32_t current_size_rtp_; + size_t current_size_rtp_; Atomic32 current_size_frame_; }; @@ -709,7 +673,7 @@ TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) { } private: - virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtcp(const uint8_t* packet, size_t length) override { // Receive statistics reporting having lost 0% of the packets. // This is needed for the send-side bitrate controller to work properly. CriticalSectionScoped lock(crit_.get()); @@ -717,7 +681,7 @@ TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) { return SEND_PACKET; } - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { CriticalSectionScoped lock(crit_.get()); ++rtp_count_; RTPHeader header; @@ -752,7 +716,7 @@ TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) { } // This method implements the I420FrameCallback. - void FrameCallback(I420VideoFrame* video_frame) OVERRIDE { + void FrameCallback(I420VideoFrame* video_frame) override { CriticalSectionScoped lock(crit_.get()); if (test_state_ == kDuringSuspend && ++suspended_frame_count_ > kSuspendTimeFrames) { @@ -773,22 +737,20 @@ TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) { high_remb_bps_ = value; } - virtual void SetReceivers( - PacketReceiver* send_transport_receiver, - PacketReceiver* receive_transport_receiver) OVERRIDE { + void SetReceivers(PacketReceiver* send_transport_receiver, + PacketReceiver* receive_transport_receiver) override { transport_.SetReceiver(send_transport_receiver); } - virtual void OnStreamsCreated( + void OnStreamsCreated( VideoSendStream* send_stream, - const std::vector& receive_streams) OVERRIDE { + const std::vector& receive_streams) override { stream_ = send_stream; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs; send_config->pre_encode_callback = this; send_config->suspend_below_min_bitrate = true; @@ -800,7 +762,7 @@ TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) { set_high_remb_bps(min_bitrate_bps + threshold_window + 5000); } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out during suspend-below-min-bitrate test."; transport_.StopSending(); @@ -817,14 +779,14 @@ TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) { EXCLUSIVE_LOCKS_REQUIRED(crit_) { FakeReceiveStatistics receive_stats( kSendSsrcs[0], last_sequence_number_, rtp_count_, 0); - RTCPSender rtcp_sender(0, false, clock_, &receive_stats); + RTCPSender rtcp_sender(0, false, clock_, &receive_stats, nullptr); EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_)); rtcp_sender.SetRTCPStatus(kRtcpNonCompound); rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]); if (remb_value > 0) { rtcp_sender.SetREMBStatus(true); - rtcp_sender.SetREMBData(remb_value, 0, NULL); + rtcp_sender.SetREMBData(remb_value, std::vector()); } RTCPSender::FeedbackState feedback_state; EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr)); @@ -835,7 +797,7 @@ TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) { Clock* const clock_; VideoSendStream* stream_; - const scoped_ptr crit_; + const rtc::scoped_ptr crit_; TestState test_state_ GUARDED_BY(crit_); int rtp_count_ GUARDED_BY(crit_); int last_sequence_number_ GUARDED_BY(crit_); @@ -856,19 +818,19 @@ TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) { transport_adapter_(ReceiveTransport()), crit_(CriticalSectionWrapper::CreateCriticalSection()), last_packet_time_ms_(-1), - capturer_(NULL) { + capturer_(nullptr) { transport_adapter_.Enable(); } private: - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { CriticalSectionScoped lock(crit_.get()); last_packet_time_ms_ = clock_->TimeInMilliseconds(); capturer_->Stop(); return SEND_PACKET; } - virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtcp(const uint8_t* packet, size_t length) override { CriticalSectionScoped lock(crit_.get()); const int kVideoMutedThresholdMs = 10000; if (last_packet_time_ms_ > 0 && @@ -877,8 +839,8 @@ TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) { observation_complete_->Set(); // Receive statistics reporting having lost 50% of the packets. FakeReceiveStatistics receive_stats(kSendSsrcs[0], 1, 1, 0); - RTCPSender rtcp_sender( - 0, false, Clock::GetRealTimeClock(), &receive_stats); + RTCPSender rtcp_sender(0, false, Clock::GetRealTimeClock(), + &receive_stats, nullptr); EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_)); rtcp_sender.SetRTCPStatus(kRtcpNonCompound); @@ -890,14 +852,13 @@ TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) { return SEND_PACKET; } - virtual void SetReceivers( - PacketReceiver* send_transport_receiver, - PacketReceiver* receive_transport_receiver) OVERRIDE { + void SetReceivers(PacketReceiver* send_transport_receiver, + PacketReceiver* receive_transport_receiver) override { RtpRtcpObserver::SetReceivers(send_transport_receiver, send_transport_receiver); } - virtual size_t GetNumStreams() const OVERRIDE { return 3; } + size_t GetNumStreams() const override { return 3; } virtual void OnFrameGeneratorCapturerCreated( test::FrameGeneratorCapturer* frame_generator_capturer) { @@ -905,14 +866,14 @@ TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) { capturer_ = frame_generator_capturer; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for RTP packets to stop being sent."; } Clock* const clock_; internal::TransportAdapter transport_adapter_; - const scoped_ptr crit_; + const rtc::scoped_ptr crit_; int64_t last_packet_time_ms_ GUARDED_BY(crit_); test::FrameGeneratorCapturer* capturer_ GUARDED_BY(crit_); } test; @@ -920,86 +881,6 @@ TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) { RunBaseTest(&test); } -TEST_F(VideoSendStreamTest, ProducesStats) { - class ProducesStats : public test::SendTest { - public: - ProducesStats() - : SendTest(kDefaultTimeoutMs), - stream_(NULL), - event_(EventWrapper::Create()) {} - - virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE { - event_->Set(); - - return SEND_PACKET; - } - - private: - bool WaitForFilledStats() { - Clock* clock = Clock::GetRealTimeClock(); - int64_t now = clock->TimeInMilliseconds(); - int64_t stop_time = now + kDefaultTimeoutMs; - while (now < stop_time) { - int64_t time_left = stop_time - now; - if (time_left > 0 && event_->Wait(time_left) == kEventSignaled && - CheckStats()) { - return true; - } - now = clock->TimeInMilliseconds(); - } - return false; - } - - bool CheckStats() { - VideoSendStream::Stats stats = stream_->GetStats(); - // Check that all applicable data sources have been used. - if (stats.input_frame_rate > 0 && stats.encode_frame_rate > 0 - && !stats.substreams.empty()) { - uint32_t ssrc = stats.substreams.begin()->first; - EXPECT_NE( - config_.rtp.ssrcs.end(), - std::find( - config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end(), ssrc)); - // Check for data populated by various sources. RTCP excluded as this - // data is received from remote side. Tested in call tests instead. - const SsrcStats& entry = stats.substreams[ssrc]; - if (entry.key_frames > 0u && entry.total_bitrate_bps > 0 && - entry.rtp_stats.packets > 0u && entry.avg_delay_ms > 0 && - entry.max_delay_ms > 0) { - return true; - } - } - return false; - } - - void SetConfig(const VideoSendStream::Config& config) { config_ = config; } - - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { - SetConfig(*send_config); - } - - virtual void OnStreamsCreated( - VideoSendStream* send_stream, - const std::vector& receive_streams) OVERRIDE { - stream_ = send_stream; - } - - virtual void PerformTest() OVERRIDE { - EXPECT_TRUE(WaitForFilledStats()) - << "Timed out waiting for filled statistics."; - } - - VideoSendStream* stream_; - VideoSendStream::Config config_; - scoped_ptr event_; - } test; - - RunBaseTest(&test); -} - // This test first observes "high" bitrate use at which point it sends a REMB to // indicate that it should be lowered significantly. The test then observes that // the bitrate observed is sinking well below the min-transmit-bitrate threshold @@ -1026,22 +907,22 @@ TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) { rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound); } - virtual void OnStreamsCreated( + void OnStreamsCreated( VideoSendStream* send_stream, - const std::vector& receive_streams) OVERRIDE { + const std::vector& receive_streams) override { stream_ = send_stream; } private: - virtual DeliveryStatus DeliverPacket(const uint8_t* packet, - size_t length) OVERRIDE { + DeliveryStatus DeliverPacket(const uint8_t* packet, + size_t length) override { if (RtpHeaderParser::IsRtcp(packet, length)) return DELIVERY_OK; RTPHeader header; if (!parser_->Parse(packet, length, &header)) return DELIVERY_PACKET_ERROR; - assert(stream_ != NULL); + DCHECK(stream_ != nullptr); VideoSendStream::Stats stats = stream_->GetStats(); if (!stats.substreams.empty()) { EXPECT_EQ(1u, stats.substreams.size()); @@ -1054,7 +935,8 @@ TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) { "bps", false); if (total_bitrate_bps > kHighBitrateBps) { - rtp_rtcp_->SetREMBData(kRembBitrateBps, 1, &header.ssrc); + rtp_rtcp_->SetREMBData(kRembBitrateBps, + std::vector(1, header.ssrc)); rtp_rtcp_->Process(); bitrate_capped_ = true; } else if (bitrate_capped_ && @@ -1065,25 +947,23 @@ TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) { return DELIVERY_OK; } - virtual void SetReceivers( - PacketReceiver* send_transport_receiver, - PacketReceiver* receive_transport_receiver) OVERRIDE { + void SetReceivers(PacketReceiver* send_transport_receiver, + PacketReceiver* receive_transport_receiver) override { RtpRtcpObserver::SetReceivers(this, send_transport_receiver); } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timeout while waiting for low bitrate stats after REMB."; } - scoped_ptr rtp_rtcp_; + rtc::scoped_ptr rtp_rtcp_; internal::TransportAdapter feedback_transport_; VideoSendStream* stream_; bool bitrate_capped_; @@ -1092,14 +972,73 @@ TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) { RunBaseTest(&test); } +TEST_F(VideoSendStreamTest, CanReconfigureToUseStartBitrateAbovePreviousMax) { + class StartBitrateObserver : public test::FakeEncoder { + public: + StartBitrateObserver() + : FakeEncoder(Clock::GetRealTimeClock()), start_bitrate_kbps_(0) {} + int32_t InitEncode(const VideoCodec* config, + int32_t number_of_cores, + size_t max_payload_size) override { + rtc::CritScope lock(&crit_); + start_bitrate_kbps_ = config->startBitrate; + return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size); + } + + int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override { + rtc::CritScope lock(&crit_); + start_bitrate_kbps_ = new_target_bitrate; + return FakeEncoder::SetRates(new_target_bitrate, framerate); + } + + int GetStartBitrateKbps() const { + rtc::CritScope lock(&crit_); + return start_bitrate_kbps_; + } + + private: + mutable rtc::CriticalSection crit_; + int start_bitrate_kbps_ GUARDED_BY(crit_); + }; + + test::NullTransport transport; + CreateSenderCall(Call::Config(&transport)); + + CreateSendConfig(1); + + Call::Config::BitrateConfig bitrate_config; + bitrate_config.start_bitrate_bps = + 2 * encoder_config_.streams[0].max_bitrate_bps; + sender_call_->SetBitrateConfig(bitrate_config); + + StartBitrateObserver encoder; + send_config_.encoder_settings.encoder = &encoder; + + CreateStreams(); + + EXPECT_EQ(encoder_config_.streams[0].max_bitrate_bps / 1000, + encoder.GetStartBitrateKbps()); + + encoder_config_.streams[0].max_bitrate_bps = + 2 * bitrate_config.start_bitrate_bps; + send_stream_->ReconfigureVideoEncoder(encoder_config_); + + // New bitrate should be reconfigured above the previous max. As there's no + // network connection this shouldn't be flaky, as no bitrate should've been + // reported in between. + EXPECT_EQ(bitrate_config.start_bitrate_bps / 1000, + encoder.GetStartBitrateKbps()); + + DestroyStreams(); +} + TEST_F(VideoSendStreamTest, CapturesTextureAndI420VideoFrames) { class FrameObserver : public I420FrameCallback { public: FrameObserver() : output_frame_event_(EventWrapper::Create()) {} - void FrameCallback(I420VideoFrame* video_frame) OVERRIDE { - // Clone the frame because the caller owns it. - output_frames_.push_back(video_frame->CloneFrame()); + void FrameCallback(I420VideoFrame* video_frame) override { + output_frames_.push_back(*video_frame); output_frame_event_->Set(); } @@ -1109,16 +1048,16 @@ TEST_F(VideoSendStreamTest, CapturesTextureAndI420VideoFrames) { << "Timeout while waiting for output frames."; } - const std::vector& output_frames() const { - return output_frames_.get(); + const std::vector& output_frames() const { + return output_frames_; } private: // Delivered output frames. - ScopedVector output_frames_; + std::vector output_frames_; // Indicate an output frame has arrived. - scoped_ptr output_frame_event_; + rtc::scoped_ptr output_frame_event_; }; // Initialize send stream. @@ -1130,9 +1069,9 @@ TEST_F(VideoSendStreamTest, CapturesTextureAndI420VideoFrames) { send_config_.pre_encode_callback = &observer; CreateStreams(); - // Prepare five input frames. Send I420VideoFrame and TextureVideoFrame + // Prepare five input frames. Send ordinary I420VideoFrame and texture frames // alternatively. - ScopedVector input_frames; + std::vector input_frames; int width = static_cast(encoder_config_.streams[0].width); int height = static_cast(encoder_config_.streams[0].height); webrtc::RefCountImpl* handle1 = @@ -1141,17 +1080,15 @@ TEST_F(VideoSendStreamTest, CapturesTextureAndI420VideoFrames) { new webrtc::RefCountImpl(); webrtc::RefCountImpl* handle3 = new webrtc::RefCountImpl(); - input_frames.push_back(new TextureVideoFrame(handle1, width, height, 1, 1)); - input_frames.push_back(new TextureVideoFrame(handle2, width, height, 2, 2)); - input_frames.push_back(CreateI420VideoFrame(width, height, 1)); - input_frames.push_back(CreateI420VideoFrame(width, height, 2)); - input_frames.push_back(new TextureVideoFrame(handle3, width, height, 3, 3)); + input_frames.push_back(I420VideoFrame(handle1, width, height, 1, 1)); + input_frames.push_back(I420VideoFrame(handle2, width, height, 2, 2)); + input_frames.push_back(CreateI420VideoFrame(width, height, 3)); + input_frames.push_back(CreateI420VideoFrame(width, height, 4)); + input_frames.push_back(I420VideoFrame(handle3, width, height, 5, 5)); send_stream_->Start(); for (size_t i = 0; i < input_frames.size(); i++) { - // Make a copy of the input frame because the buffer will be swapped. - scoped_ptr frame(input_frames[i]->CloneFrame()); - send_stream_->Input()->SwapFrame(frame.get()); + send_stream_->Input()->IncomingCapturedFrame(input_frames[i]); // Do not send the next frame too fast, so the frame dropper won't drop it. if (i < input_frames.size() - 1) SleepMs(1000 / encoder_config_.streams[0].max_framerate); @@ -1163,14 +1100,14 @@ TEST_F(VideoSendStreamTest, CapturesTextureAndI420VideoFrames) { // Test if the input and output frames are the same. render_time_ms and // timestamp are not compared because capturer sets those values. - ExpectEqualFramesVector(input_frames.get(), observer.output_frames()); + ExpectEqualFramesVector(input_frames, observer.output_frames()); DestroyStreams(); } void ExpectEqualFrames(const I420VideoFrame& frame1, const I420VideoFrame& frame2) { - if (frame1.native_handle() != NULL || frame2.native_handle() != NULL) + if (frame1.native_handle() != nullptr || frame2.native_handle() != nullptr) ExpectEqualTextureFrames(frame1, frame2); else ExpectEqualBufferFrames(frame1, frame2); @@ -1181,6 +1118,7 @@ void ExpectEqualTextureFrames(const I420VideoFrame& frame1, EXPECT_EQ(frame1.native_handle(), frame2.native_handle()); EXPECT_EQ(frame1.width(), frame2.width()); EXPECT_EQ(frame1.height(), frame2.height()); + EXPECT_EQ(frame1.render_time_ms(), frame2.render_time_ms()); } void ExpectEqualBufferFrames(const I420VideoFrame& frame1, @@ -1190,7 +1128,7 @@ void ExpectEqualBufferFrames(const I420VideoFrame& frame1, EXPECT_EQ(frame1.stride(kYPlane), frame2.stride(kYPlane)); EXPECT_EQ(frame1.stride(kUPlane), frame2.stride(kUPlane)); EXPECT_EQ(frame1.stride(kVPlane), frame2.stride(kVPlane)); - EXPECT_EQ(frame1.ntp_time_ms(), frame2.ntp_time_ms()); + EXPECT_EQ(frame1.render_time_ms(), frame2.render_time_ms()); ASSERT_EQ(frame1.allocated_size(kYPlane), frame2.allocated_size(kYPlane)); EXPECT_EQ(0, memcmp(frame1.buffer(kYPlane), @@ -1208,33 +1146,22 @@ void ExpectEqualBufferFrames(const I420VideoFrame& frame1, frame1.allocated_size(kVPlane))); } -void ExpectEqualFramesVector(const std::vector& frames1, - const std::vector& frames2) { +void ExpectEqualFramesVector(const std::vector& frames1, + const std::vector& frames2) { EXPECT_EQ(frames1.size(), frames2.size()); for (size_t i = 0; i < std::min(frames1.size(), frames2.size()); ++i) - ExpectEqualFrames(*frames1[i], *frames2[i]); + ExpectEqualFrames(frames1[i], frames2[i]); } -I420VideoFrame* CreateI420VideoFrame(int width, int height, uint8_t data) { - I420VideoFrame* frame = new I420VideoFrame(); +I420VideoFrame CreateI420VideoFrame(int width, int height, uint8_t data) { const int kSizeY = width * height * 2; - const int kSizeUV = width * height; - scoped_ptr buffer(new uint8_t[kSizeY]); + rtc::scoped_ptr buffer(new uint8_t[kSizeY]); memset(buffer.get(), data, kSizeY); - frame->CreateFrame(kSizeY, - buffer.get(), - kSizeUV, - buffer.get(), - kSizeUV, - buffer.get(), - width, - height, - width, - width / 2, - width / 2); - frame->set_timestamp(data); - frame->set_ntp_time_ms(data); - frame->set_render_time_ms(data); + I420VideoFrame frame; + frame.CreateFrame(buffer.get(), buffer.get(), buffer.get(), width, height, + width, width / 2, width / 2); + frame.set_timestamp(data); + frame.set_render_time_ms(data); return frame; } @@ -1265,9 +1192,9 @@ TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) { } private: - virtual int32_t InitEncode(const VideoCodec* codecSettings, - int32_t numberOfCores, - uint32_t maxPayloadSize) OVERRIDE { + int32_t InitEncode(const VideoCodec* codecSettings, + int32_t numberOfCores, + size_t maxPayloadSize) override { CriticalSectionScoped lock(crit_.get()); EXPECT_FALSE(initialized_); initialized_ = true; @@ -1275,25 +1202,24 @@ TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) { return 0; } - virtual int32_t Encode( - const I420VideoFrame& inputImage, - const CodecSpecificInfo* codecSpecificInfo, - const std::vector* frame_types) OVERRIDE { + int32_t Encode(const I420VideoFrame& inputImage, + const CodecSpecificInfo* codecSpecificInfo, + const std::vector* frame_types) override { EXPECT_TRUE(IsReadyForEncode()); observation_complete_->Set(); return 0; } - virtual int32_t RegisterEncodeCompleteCallback( - EncodedImageCallback* callback) OVERRIDE { + int32_t RegisterEncodeCompleteCallback( + EncodedImageCallback* callback) override { CriticalSectionScoped lock(crit_.get()); EXPECT_TRUE(initialized_); callback_registered_ = true; return 0; } - virtual int32_t Release() OVERRIDE { + int32_t Release() override { CriticalSectionScoped lock(crit_.get()); EXPECT_TRUE(IsReadyForEncode()); EXPECT_FALSE(released_); @@ -1304,35 +1230,33 @@ TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) { return 0; } - virtual int32_t SetChannelParameters(uint32_t packetLoss, - int rtt) OVERRIDE { + int32_t SetChannelParameters(uint32_t packetLoss, int64_t rtt) override { EXPECT_TRUE(IsReadyForEncode()); return 0; } - virtual int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) OVERRIDE { + int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) override { EXPECT_TRUE(IsReadyForEncode()); return 0; } - virtual void OnStreamsCreated( + void OnStreamsCreated( VideoSendStream* send_stream, - const std::vector& receive_streams) OVERRIDE { + const std::vector& receive_streams) override { // Encoder initialization should be done in stream construction before // starting. EXPECT_TRUE(IsReadyForEncode()); stream_ = send_stream; } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->encoder_settings.encoder = this; encoder_config_ = *encoder_config; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for Encode."; EXPECT_EQ(0u, num_releases()); @@ -1348,7 +1272,7 @@ TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) { << "Timed out while waiting for Encode."; } - scoped_ptr crit_; + rtc::scoped_ptr crit_; VideoSendStream* stream_; bool initialized_ GUARDED_BY(crit_); bool callback_registered_ GUARDED_BY(crit_); @@ -1373,23 +1297,22 @@ TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) { num_initializations_(0) {} private: - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->encoder_settings.encoder = this; encoder_config_ = *encoder_config; } - virtual void OnStreamsCreated( + void OnStreamsCreated( VideoSendStream* send_stream, - const std::vector& receive_streams) OVERRIDE { + const std::vector& receive_streams) override { stream_ = send_stream; } - virtual int32_t InitEncode(const VideoCodec* config, - int32_t number_of_cores, - uint32_t max_payload_size) OVERRIDE { + int32_t InitEncode(const VideoCodec* config, + int32_t number_of_cores, + size_t max_payload_size) override { if (num_initializations_ == 0) { // Verify default values. EXPECT_EQ(kRealtimeVideo, config->mode); @@ -1401,7 +1324,7 @@ TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) { return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size); } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized."; encoder_config_.content_type = VideoEncoderConfig::kScreenshare; @@ -1419,131 +1342,188 @@ TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) { RunBaseTest(&test); } +static const size_t kVideoCodecConfigObserverNumberOfTemporalLayers = 4; +template +class VideoCodecConfigObserver : public test::SendTest, + public test::FakeEncoder { + + public: + VideoCodecConfigObserver(VideoCodecType video_codec_type, + const char* codec_name) + : SendTest(VideoSendStreamTest::kDefaultTimeoutMs), + FakeEncoder(Clock::GetRealTimeClock()), + video_codec_type_(video_codec_type), + codec_name_(codec_name), + num_initializations_(0) { + memset(&encoder_settings_, 0, sizeof(encoder_settings_)); + } + + private: + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { + send_config->encoder_settings.encoder = this; + send_config->encoder_settings.payload_name = codec_name_; + + for (size_t i = 0; i < encoder_config->streams.size(); ++i) { + encoder_config->streams[i].temporal_layer_thresholds_bps.resize( + kVideoCodecConfigObserverNumberOfTemporalLayers - 1); + } + + encoder_config->encoder_specific_settings = &encoder_settings_; + encoder_config_ = *encoder_config; + } + + void OnStreamsCreated( + VideoSendStream* send_stream, + const std::vector& receive_streams) override { + stream_ = send_stream; + } + + int32_t InitEncode(const VideoCodec* config, + int32_t number_of_cores, + size_t max_payload_size) override { + EXPECT_EQ(video_codec_type_, config->codecType); + VerifyCodecSpecifics(*config); + ++num_initializations_; + return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size); + } + + void VerifyCodecSpecifics(const VideoCodec& config) const; + + void PerformTest() override { + EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized."; + + encoder_settings_.frameDroppingOn = true; + stream_->ReconfigureVideoEncoder(encoder_config_); + EXPECT_EQ(2u, num_initializations_) + << "ReconfigureVideoEncoder did not reinitialize the encoder with " + "new encoder settings."; + } + + int32_t Encode(const I420VideoFrame& input_image, + const CodecSpecificInfo* codec_specific_info, + const std::vector* frame_types) override { + // Silently skip the encode, FakeEncoder::Encode doesn't produce VP8. + return 0; + } + + T encoder_settings_; + const VideoCodecType video_codec_type_; + const char* const codec_name_; + size_t num_initializations_; + VideoSendStream* stream_; + VideoEncoderConfig encoder_config_; +}; + +template <> +void VideoCodecConfigObserver::VerifyCodecSpecifics( + const VideoCodec& config) const { + EXPECT_EQ(0, memcmp(&config.codecSpecific.H264, &encoder_settings_, + sizeof(encoder_settings_))); +} +template <> +void VideoCodecConfigObserver::VerifyCodecSpecifics( + const VideoCodec& config) const { + // Check that the number of temporal layers has propagated properly to + // VideoCodec. + EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers, + config.codecSpecific.VP8.numberOfTemporalLayers); + + for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) { + EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers, + config.simulcastStream[i].numberOfTemporalLayers); + } + + // Set expected temporal layers as they should have been set when + // reconfiguring the encoder and not match the set config. + VideoCodecVP8 encoder_settings = encoder_settings_; + encoder_settings.numberOfTemporalLayers = + kVideoCodecConfigObserverNumberOfTemporalLayers; + EXPECT_EQ(0, memcmp(&config.codecSpecific.VP8, &encoder_settings, + sizeof(encoder_settings_))); +} +template <> +void VideoCodecConfigObserver::VerifyCodecSpecifics( + const VideoCodec& config) const { + // Check that the number of temporal layers has propagated properly to + // VideoCodec. + EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers, + config.codecSpecific.VP9.numberOfTemporalLayers); + + for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) { + EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers, + config.simulcastStream[i].numberOfTemporalLayers); + } + + // Set expected temporal layers as they should have been set when + // reconfiguring the encoder and not match the set config. + VideoCodecVP9 encoder_settings = encoder_settings_; + encoder_settings.numberOfTemporalLayers = + kVideoCodecConfigObserverNumberOfTemporalLayers; + EXPECT_EQ(0, memcmp(&config.codecSpecific.VP9, &encoder_settings, + sizeof(encoder_settings_))); +} + TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp8Config) { - static const size_t kNumberOfTemporalLayers = 4; - class VideoCodecConfigObserver : public test::SendTest, - public test::FakeEncoder { - public: - VideoCodecConfigObserver() - : SendTest(kDefaultTimeoutMs), - FakeEncoder(Clock::GetRealTimeClock()), - num_initializations_(0) { - memset(&vp8_settings_, 0, sizeof(vp8_settings_)); - } + VideoCodecConfigObserver test(kVideoCodecVP8, "VP8"); + RunBaseTest(&test); +} - private: - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { - send_config->encoder_settings.encoder = this; - send_config->encoder_settings.payload_name = "VP8"; - - for (size_t i = 0; i < encoder_config->streams.size(); ++i) { - encoder_config->streams[i].temporal_layer_thresholds_bps.resize( - kNumberOfTemporalLayers - 1); - } - - encoder_config->encoder_specific_settings = &vp8_settings_; - encoder_config_ = *encoder_config; - } - - virtual void OnStreamsCreated( - VideoSendStream* send_stream, - const std::vector& receive_streams) OVERRIDE { - stream_ = send_stream; - } - - virtual int32_t InitEncode(const VideoCodec* config, - int32_t number_of_cores, - uint32_t max_payload_size) OVERRIDE { - EXPECT_EQ(kVideoCodecVP8, config->codecType); - - // Check that the number of temporal layers has propagated properly to - // VideoCodec. - EXPECT_EQ(kNumberOfTemporalLayers, - config->codecSpecific.VP8.numberOfTemporalLayers); - - for (unsigned char i = 0; i < config->numberOfSimulcastStreams; ++i) { - EXPECT_EQ(kNumberOfTemporalLayers, - config->simulcastStream[i].numberOfTemporalLayers); - } - - // Set expected temporal layers as they should have been set when - // reconfiguring the encoder and not match the set config. - vp8_settings_.numberOfTemporalLayers = kNumberOfTemporalLayers; - EXPECT_EQ(0, - memcmp(&config->codecSpecific.VP8, - &vp8_settings_, - sizeof(vp8_settings_))); - ++num_initializations_; - return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size); - } - - virtual void PerformTest() OVERRIDE { - EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized."; - - vp8_settings_.denoisingOn = true; - stream_->ReconfigureVideoEncoder(encoder_config_); - EXPECT_EQ(2u, num_initializations_) - << "ReconfigureVideoEncoder did not reinitialize the encoder with " - "new encoder settings."; - } - - int32_t Encode(const I420VideoFrame& input_image, - const CodecSpecificInfo* codec_specific_info, - const std::vector* frame_types) OVERRIDE { - // Silently skip the encode, FakeEncoder::Encode doesn't produce VP8. - return 0; - } - - VideoCodecVP8 vp8_settings_; - size_t num_initializations_; - VideoSendStream* stream_; - VideoEncoderConfig encoder_config_; - } test; +TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp9Config) { + VideoCodecConfigObserver test(kVideoCodecVP9, "VP9"); + RunBaseTest(&test); +} +TEST_F(VideoSendStreamTest, EncoderSetupPropagatesH264Config) { + VideoCodecConfigObserver test(kVideoCodecH264, "H264"); RunBaseTest(&test); } TEST_F(VideoSendStreamTest, RtcpSenderReportContainsMediaBytesSent) { - class RtcpByeTest : public test::SendTest { + class RtcpSenderReportTest : public test::SendTest { public: - RtcpByeTest() : SendTest(kDefaultTimeoutMs), media_bytes_sent_(0) {} + RtcpSenderReportTest() : SendTest(kDefaultTimeoutMs), + rtp_packets_sent_(0), + media_bytes_sent_(0) {} private: - virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtp(const uint8_t* packet, size_t length) override { RTPHeader header; EXPECT_TRUE(parser_->Parse(packet, length, &header)); + ++rtp_packets_sent_; media_bytes_sent_ += length - header.headerLength - header.paddingLength; return SEND_PACKET; } - virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE { + Action OnSendRtcp(const uint8_t* packet, size_t length) override { RTCPUtility::RTCPParserV2 parser(packet, length, true); EXPECT_TRUE(parser.IsValid()); RTCPUtility::RTCPPacketTypes packet_type = parser.Begin(); - uint32_t sender_octet_count = 0; while (packet_type != RTCPUtility::kRtcpNotValidCode) { if (packet_type == RTCPUtility::kRtcpSrCode) { - sender_octet_count = parser.Packet().SR.SenderOctetCount; - EXPECT_EQ(sender_octet_count, media_bytes_sent_); - if (sender_octet_count > 0) + // Only compare sent media bytes if SenderPacketCount matches the + // number of sent rtp packets (a new rtp packet could be sent before + // the rtcp packet). + if (parser.Packet().SR.SenderOctetCount > 0 && + parser.Packet().SR.SenderPacketCount == rtp_packets_sent_) { + EXPECT_EQ(media_bytes_sent_, parser.Packet().SR.SenderOctetCount); observation_complete_->Set(); + } } - packet_type = parser.Iterate(); } return SEND_PACKET; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for RTCP sender report."; } + size_t rtp_packets_sent_; size_t media_bytes_sent_; } test; @@ -1560,19 +1540,18 @@ TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) { test::FakeEncoder(Clock::GetRealTimeClock()) {} private: - virtual int32_t InitEncode(const VideoCodec* config, - int32_t number_of_cores, - uint32_t max_payload_size) { + int32_t InitEncode(const VideoCodec* config, + int32_t number_of_cores, + size_t max_payload_size) override { EXPECT_EQ(static_cast(kScreencastTargetBitrateKbps), config->targetBitrate); observation_complete_->Set(); return test::FakeEncoder::InitEncode( config, number_of_cores, max_payload_size); } - virtual void ModifyConfigs( - VideoSendStream::Config* send_config, - std::vector* receive_configs, - VideoEncoderConfig* encoder_config) OVERRIDE { + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { send_config->encoder_settings.encoder = this; EXPECT_EQ(1u, encoder_config->streams.size()); EXPECT_TRUE( @@ -1582,7 +1561,7 @@ TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) { encoder_config->content_type = VideoEncoderConfig::kScreenshare; } - virtual void PerformTest() OVERRIDE { + void PerformTest() override { EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for the encoder to be initialized."; } @@ -1590,4 +1569,189 @@ TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) { RunBaseTest(&test); } + +TEST_F(VideoSendStreamTest, ReconfigureBitratesSetsEncoderBitratesCorrectly) { + // These are chosen to be "kind of odd" to not be accidentally checked against + // default values. + static const int kMinBitrateKbps = 137; + static const int kStartBitrateKbps = 345; + static const int kLowerMaxBitrateKbps = 312; + static const int kMaxBitrateKbps = 413; + static const int kIncreasedStartBitrateKbps = 451; + static const int kIncreasedMaxBitrateKbps = 597; + class EncoderBitrateThresholdObserver : public test::SendTest, + public test::FakeEncoder { + public: + EncoderBitrateThresholdObserver() + : SendTest(kDefaultTimeoutMs), + FakeEncoder(Clock::GetRealTimeClock()), + num_initializations_(0) {} + + private: + int32_t InitEncode(const VideoCodec* codecSettings, + int32_t numberOfCores, + size_t maxPayloadSize) override { + if (num_initializations_ == 0) { + EXPECT_EQ(static_cast(kMinBitrateKbps), + codecSettings->minBitrate); + EXPECT_EQ(static_cast(kStartBitrateKbps), + codecSettings->startBitrate); + EXPECT_EQ(static_cast(kMaxBitrateKbps), + codecSettings->maxBitrate); + observation_complete_->Set(); + } else if (num_initializations_ == 1) { + EXPECT_EQ(static_cast(kLowerMaxBitrateKbps), + codecSettings->maxBitrate); + // The start bitrate should be kept (-1) and capped to the max bitrate. + // Since this is not an end-to-end call no receiver should have been + // returning a REMB that could lower this estimate. + EXPECT_EQ(codecSettings->startBitrate, codecSettings->maxBitrate); + } else if (num_initializations_ == 2) { + EXPECT_EQ(static_cast(kIncreasedMaxBitrateKbps), + codecSettings->maxBitrate); + EXPECT_EQ(static_cast(kIncreasedStartBitrateKbps), + codecSettings->startBitrate); + } + ++num_initializations_; + return FakeEncoder::InitEncode(codecSettings, numberOfCores, + maxPayloadSize); + } + + Call::Config GetSenderCallConfig() override { + Call::Config config(SendTransport()); + config.bitrate_config.min_bitrate_bps = kMinBitrateKbps * 1000; + config.bitrate_config.start_bitrate_bps = kStartBitrateKbps * 1000; + config.bitrate_config.max_bitrate_bps = kMaxBitrateKbps * 1000; + return config; + } + + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { + send_config->encoder_settings.encoder = this; + // Set bitrates lower/higher than min/max to make sure they are properly + // capped. + encoder_config->streams.front().min_bitrate_bps = kMinBitrateKbps * 1000; + encoder_config->streams.front().max_bitrate_bps = kMaxBitrateKbps * 1000; + encoder_config_ = *encoder_config; + } + + void OnCallsCreated(Call* sender_call, Call* receiver_call) override { + call_ = sender_call; + } + + void OnStreamsCreated( + VideoSendStream* send_stream, + const std::vector& receive_streams) override { + send_stream_ = send_stream; + } + + void PerformTest() override { + Call::Config::BitrateConfig bitrate_config; + bitrate_config.start_bitrate_bps = kIncreasedStartBitrateKbps * 1000; + bitrate_config.max_bitrate_bps = kIncreasedMaxBitrateKbps * 1000; + call_->SetBitrateConfig(bitrate_config); + EXPECT_EQ(kEventSignaled, Wait()) + << "Timed out while waiting encoder to be configured."; + encoder_config_.streams[0].min_bitrate_bps = 0; + encoder_config_.streams[0].max_bitrate_bps = kLowerMaxBitrateKbps * 1000; + send_stream_->ReconfigureVideoEncoder(encoder_config_); + EXPECT_EQ(2, num_initializations_) + << "Encoder should have been reconfigured with the new value."; + encoder_config_.streams[0].target_bitrate_bps = + encoder_config_.streams[0].min_bitrate_bps; + encoder_config_.streams[0].max_bitrate_bps = + kIncreasedMaxBitrateKbps * 1000; + send_stream_->ReconfigureVideoEncoder(encoder_config_); + EXPECT_EQ(3, num_initializations_) + << "Encoder should have been reconfigured with the new value."; + } + + int num_initializations_; + webrtc::Call* call_; + webrtc::VideoSendStream* send_stream_; + webrtc::VideoEncoderConfig encoder_config_; + } test; + + RunBaseTest(&test); +} + +TEST_F(VideoSendStreamTest, ReportsSentResolution) { + static const size_t kNumStreams = 3; + // Unusual resolutions to make sure that they are the ones being reported. + static const struct { + int width; + int height; + } kEncodedResolution[kNumStreams] = { + {241, 181}, {300, 121}, {121, 221}}; + class ScreencastTargetBitrateTest : public test::SendTest, + public test::FakeEncoder { + public: + ScreencastTargetBitrateTest() + : SendTest(kDefaultTimeoutMs), + test::FakeEncoder(Clock::GetRealTimeClock()) {} + + private: + int32_t Encode(const I420VideoFrame& input_image, + const CodecSpecificInfo* codecSpecificInfo, + const std::vector* frame_types) override { + CodecSpecificInfo specifics; + memset(&specifics, 0, sizeof(specifics)); + specifics.codecType = kVideoCodecGeneric; + + uint8_t buffer[16] = {0}; + EncodedImage encoded(buffer, sizeof(buffer), sizeof(buffer)); + encoded._timeStamp = input_image.timestamp(); + encoded.capture_time_ms_ = input_image.render_time_ms(); + + for (size_t i = 0; i < kNumStreams; ++i) { + specifics.codecSpecific.generic.simulcast_idx = static_cast(i); + encoded._frameType = (*frame_types)[i]; + encoded._encodedWidth = kEncodedResolution[i].width; + encoded._encodedHeight = kEncodedResolution[i].height; + DCHECK(callback_ != nullptr); + if (callback_->Encoded(encoded, &specifics, nullptr) != 0) + return -1; + } + + observation_complete_->Set(); + return 0; + } + void ModifyConfigs(VideoSendStream::Config* send_config, + std::vector* receive_configs, + VideoEncoderConfig* encoder_config) override { + send_config->encoder_settings.encoder = this; + EXPECT_EQ(kNumStreams, encoder_config->streams.size()); + } + + size_t GetNumStreams() const override { return kNumStreams; } + + void PerformTest() override { + EXPECT_EQ(kEventSignaled, Wait()) + << "Timed out while waiting for the encoder to send one frame."; + VideoSendStream::Stats stats = send_stream_->GetStats(); + + for (size_t i = 0; i < kNumStreams; ++i) { + ASSERT_TRUE(stats.substreams.find(kSendSsrcs[i]) != + stats.substreams.end()) + << "No stats for SSRC: " << kSendSsrcs[i] + << ", stats should exist as soon as frames have been encoded."; + VideoSendStream::StreamStats ssrc_stats = + stats.substreams[kSendSsrcs[i]]; + EXPECT_EQ(kEncodedResolution[i].width, ssrc_stats.width); + EXPECT_EQ(kEncodedResolution[i].height, ssrc_stats.height); + } + } + + void OnStreamsCreated( + VideoSendStream* send_stream, + const std::vector& receive_streams) override { + send_stream_ = send_stream; + } + + VideoSendStream* send_stream_; + } test; + + RunBaseTest(&test); +} } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_encoder.h b/media/webrtc/trunk/webrtc/video_encoder.h index 2bf52f3c32..c933a33469 100644 --- a/media/webrtc/trunk/webrtc/video_encoder.h +++ b/media/webrtc/trunk/webrtc/video_encoder.h @@ -29,11 +29,9 @@ class EncodedImageCallback { virtual ~EncodedImageCallback() {} // Callback function which is called when an image has been encoded. - // TODO(pbos): Make encoded_image const or pointer. Remove default arguments. - virtual int32_t Encoded( - EncodedImage& encoded_image, - const CodecSpecificInfo* codec_specific_info = NULL, - const RTPFragmentationHeader* fragmentation = NULL) = 0; + virtual int32_t Encoded(const EncodedImage& encoded_image, + const CodecSpecificInfo* codec_specific_info, + const RTPFragmentationHeader* fragmentation) = 0; }; class VideoEncoder { @@ -68,7 +66,7 @@ class VideoEncoder { // WEBRTC_VIDEO_CODEC_ERROR virtual int32_t InitEncode(const VideoCodec* codec_settings, int32_t number_of_cores, - uint32_t max_payload_size) = 0; + size_t max_payload_size) = 0; // Register an encode complete callback object. // @@ -109,7 +107,7 @@ class VideoEncoder { // - rtt : Round-trip time in milliseconds // Return value : WEBRTC_VIDEO_CODEC_OK if OK // <0 - Errors: WEBRTC_VIDEO_CODEC_ERROR - virtual int32_t SetChannelParameters(uint32_t packet_loss, int rtt) = 0; + virtual int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) = 0; // Inform the encoder about the new target bit rate. // diff --git a/media/webrtc/trunk/webrtc/video_engine/BUILD.gn b/media/webrtc/trunk/webrtc/video_engine/BUILD.gn index debcd2f8db..2e496417a5 100644 --- a/media/webrtc/trunk/webrtc/video_engine/BUILD.gn +++ b/media/webrtc/trunk/webrtc/video_engine/BUILD.gn @@ -29,6 +29,10 @@ source_set("video_engine_core") { "encoder_state_feedback.h", "overuse_frame_detector.cc", "overuse_frame_detector.h", + "payload_router.cc", + "payload_router.h", + "report_block_stats.cc", + "report_block_stats.h", "stream_synchronization.cc", "stream_synchronization.h", "vie_base_impl.cc", @@ -99,18 +103,21 @@ source_set("video_engine_core") { cflags = [ # TODO(jschuh): Bug 1348: fix size_t to int truncations. "/wd4267", # size_t to int truncation. + # Bug 261. + "/wd4373", # legacy warning for ignoring const / volatile in signatures. ] } deps = [ + "..:webrtc_common", "../common_video", "../modules/bitrate_controller", "../modules/rtp_rtcp", "../modules/utility", - "../modules/video_capture", + "../modules/video_capture:video_capture_module", "../modules/video_coding", "../modules/video_processing", - "../modules/video_render", + "../modules/video_render:video_render_module", "../voice_engine", "../system_wrappers", ] diff --git a/media/webrtc/trunk/webrtc/video_engine/OWNERS b/media/webrtc/trunk/webrtc/video_engine/OWNERS index 7c5d371a7e..5e47b1ae06 100644 --- a/media/webrtc/trunk/webrtc/video_engine/OWNERS +++ b/media/webrtc/trunk/webrtc/video_engine/OWNERS @@ -1,6 +1,5 @@ mflodman@webrtc.org stefan@webrtc.org -mallinath@webrtc.org per-file *.isolate=kjellander@webrtc.org diff --git a/media/webrtc/trunk/webrtc/video_engine/browser_capture_impl.h b/media/webrtc/trunk/webrtc/video_engine/browser_capture_impl.h index e2585a4638..b45842709b 100644 --- a/media/webrtc/trunk/webrtc/video_engine/browser_capture_impl.h +++ b/media/webrtc/trunk/webrtc/video_engine/browser_capture_impl.h @@ -36,7 +36,7 @@ namespace webrtc { VideoCaptureCapability& capability) { return 0;}; virtual int32_t GetOrientation(const char* deviceUniqueIdUTF8, - VideoCaptureRotation& orientation) { return 0; } + VideoRotation& orientation) { return 0; } virtual int32_t GetBestMatchedCapability(const char* deviceUniqueIdUTF8, const VideoCaptureCapability& requested, diff --git a/media/webrtc/trunk/webrtc/video_engine/call_stats.cc b/media/webrtc/trunk/webrtc/video_engine/call_stats.cc index 05385c35ea..6e51eebe5a 100644 --- a/media/webrtc/trunk/webrtc/video_engine/call_stats.cc +++ b/media/webrtc/trunk/webrtc/video_engine/call_stats.cc @@ -17,23 +17,70 @@ #include "webrtc/system_wrappers/interface/tick_util.h" namespace webrtc { - -// A rtt report is considered valid for this long. -const int kRttTimeoutMs = 1500; +namespace { // Time interval for updating the observers. -const int kUpdateIntervalMs = 1000; +const int64_t kUpdateIntervalMs = 1000; +// Weight factor to apply to the average rtt. +const float kWeightFactor = 0.3f; + +void RemoveOldReports(int64_t now, std::list* reports) { + // A rtt report is considered valid for this long. + const int64_t kRttTimeoutMs = 1500; + while (!reports->empty() && + (now - reports->front().time) > kRttTimeoutMs) { + reports->pop_front(); + } +} + +int64_t GetMaxRttMs(std::list* reports) { + int64_t max_rtt_ms = 0; + for (std::list::const_iterator it = reports->begin(); + it != reports->end(); ++it) { + max_rtt_ms = std::max(it->rtt, max_rtt_ms); + } + return max_rtt_ms; +} + +int64_t GetAvgRttMs(std::list* reports) { + if (reports->empty()) { + return 0; + } + int64_t sum = 0; + for (std::list::const_iterator it = reports->begin(); + it != reports->end(); ++it) { + sum += it->rtt; + } + return sum / reports->size(); +} + +void UpdateAvgRttMs(std::list* reports, int64_t* avg_rtt) { + uint32_t cur_rtt_ms = GetAvgRttMs(reports); + if (cur_rtt_ms == 0) { + // Reset. + *avg_rtt = 0; + return; + } + if (*avg_rtt == 0) { + // Initialize. + *avg_rtt = cur_rtt_ms; + return; + } + *avg_rtt = *avg_rtt * (1.0f - kWeightFactor) + cur_rtt_ms * kWeightFactor; +} +} // namespace class RtcpObserver : public RtcpRttStats { public: explicit RtcpObserver(CallStats* owner) : owner_(owner) {} virtual ~RtcpObserver() {} - virtual void OnRttUpdate(uint32_t rtt) { + virtual void OnRttUpdate(int64_t rtt) { owner_->OnRttUpdate(rtt); } - virtual uint32_t LastProcessedRtt() const { - return owner_->last_processed_rtt_ms(); + // Returns the average RTT. + virtual int64_t LastProcessedRtt() const { + return owner_->avg_rtt_ms(); } private: @@ -46,53 +93,45 @@ CallStats::CallStats() : crit_(CriticalSectionWrapper::CreateCriticalSection()), rtcp_rtt_stats_(new RtcpObserver(this)), last_process_time_(TickTime::MillisecondTimestamp()), - last_processed_rtt_ms_(0) { + max_rtt_ms_(0), + avg_rtt_ms_(0) { } CallStats::~CallStats() { assert(observers_.empty()); } -int32_t CallStats::TimeUntilNextProcess() { +int64_t CallStats::TimeUntilNextProcess() { return last_process_time_ + kUpdateIntervalMs - TickTime::MillisecondTimestamp(); } int32_t CallStats::Process() { CriticalSectionScoped cs(crit_.get()); - if (TickTime::MillisecondTimestamp() < last_process_time_ + kUpdateIntervalMs) + int64_t now = TickTime::MillisecondTimestamp(); + if (now < last_process_time_ + kUpdateIntervalMs) return 0; - // Remove invalid, as in too old, rtt values. - int64_t time_now = TickTime::MillisecondTimestamp(); - while (!reports_.empty() && reports_.front().time + kRttTimeoutMs < - time_now) { - reports_.pop_front(); - } + last_process_time_ = now; - // Find the max stored RTT. - uint32_t max_rtt = 0; - for (std::list::const_iterator it = reports_.begin(); - it != reports_.end(); ++it) { - if (it->rtt > max_rtt) - max_rtt = it->rtt; - } + RemoveOldReports(now, &reports_); + max_rtt_ms_ = GetMaxRttMs(&reports_); + UpdateAvgRttMs(&reports_, &avg_rtt_ms_); - // If there is a valid rtt, update all observers. - if (max_rtt > 0) { + // If there is a valid rtt, update all observers with the max rtt. + // TODO(asapersson): Consider changing this to report the average rtt. + if (max_rtt_ms_ > 0) { for (std::list::iterator it = observers_.begin(); it != observers_.end(); ++it) { - (*it)->OnRttUpdate(max_rtt); + (*it)->OnRttUpdate(max_rtt_ms_); } } - last_processed_rtt_ms_ = max_rtt; - last_process_time_ = time_now; return 0; } -uint32_t CallStats::last_processed_rtt_ms() const { +int64_t CallStats::avg_rtt_ms() const { CriticalSectionScoped cs(crit_.get()); - return last_processed_rtt_ms_; + return avg_rtt_ms_; } RtcpRttStats* CallStats::rtcp_rtt_stats() const { @@ -120,10 +159,9 @@ void CallStats::DeregisterStatsObserver(CallStatsObserver* observer) { } } -void CallStats::OnRttUpdate(uint32_t rtt) { +void CallStats::OnRttUpdate(int64_t rtt) { CriticalSectionScoped cs(crit_.get()); - int64_t time_now = TickTime::MillisecondTimestamp(); - reports_.push_back(RttTime(rtt, time_now)); + reports_.push_back(RttTime(rtt, TickTime::MillisecondTimestamp())); } } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/call_stats.h b/media/webrtc/trunk/webrtc/video_engine/call_stats.h index 95f4fee71e..79a8af6267 100644 --- a/media/webrtc/trunk/webrtc/video_engine/call_stats.h +++ b/media/webrtc/trunk/webrtc/video_engine/call_stats.h @@ -14,8 +14,8 @@ #include #include "webrtc/base/constructormagic.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/interface/module.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" namespace webrtc { @@ -32,8 +32,8 @@ class CallStats : public Module { ~CallStats(); // Implements Module, to use the process thread. - virtual int32_t TimeUntilNextProcess() OVERRIDE; - virtual int32_t Process() OVERRIDE; + int64_t TimeUntilNextProcess() override; + int32_t Process() override; // Returns a RtcpRttStats to register at a statistics provider. The object // has the same lifetime as the CallStats instance. @@ -43,28 +43,29 @@ class CallStats : public Module { void RegisterStatsObserver(CallStatsObserver* observer); void DeregisterStatsObserver(CallStatsObserver* observer); - protected: - void OnRttUpdate(uint32_t rtt); - - uint32_t last_processed_rtt_ms() const; - - private: // Helper struct keeping track of the time a rtt value is reported. struct RttTime { - RttTime(uint32_t new_rtt, int64_t rtt_time) + RttTime(int64_t new_rtt, int64_t rtt_time) : rtt(new_rtt), time(rtt_time) {} - const uint32_t rtt; + const int64_t rtt; const int64_t time; }; + protected: + void OnRttUpdate(int64_t rtt); + + int64_t avg_rtt_ms() const; + + private: // Protecting all members. - scoped_ptr crit_; + rtc::scoped_ptr crit_; // Observer receiving statistics updates. - scoped_ptr rtcp_rtt_stats_; + rtc::scoped_ptr rtcp_rtt_stats_; // The last time 'Process' resulted in statistic update. int64_t last_process_time_; // The last RTT in the statistics update (zero if there is no valid estimate). - uint32_t last_processed_rtt_ms_; + int64_t max_rtt_ms_; + int64_t avg_rtt_ms_; // All Rtt reports within valid time interval, oldest first. std::list reports_; diff --git a/media/webrtc/trunk/webrtc/video_engine/call_stats_unittest.cc b/media/webrtc/trunk/webrtc/video_engine/call_stats_unittest.cc index f504094ba2..0febbd0198 100644 --- a/media/webrtc/trunk/webrtc/video_engine/call_stats_unittest.cc +++ b/media/webrtc/trunk/webrtc/video_engine/call_stats_unittest.cc @@ -11,8 +11,8 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/tick_util.h" #include "webrtc/video_engine/call_stats.h" @@ -27,7 +27,7 @@ class MockStatsObserver : public CallStatsObserver { MockStatsObserver() {} virtual ~MockStatsObserver() {} - MOCK_METHOD1(OnRttUpdate, void(uint32_t)); + MOCK_METHOD1(OnRttUpdate, void(int64_t)); }; class CallStatsTest : public ::testing::Test { @@ -36,7 +36,7 @@ class CallStatsTest : public ::testing::Test { TickTime::UseFakeClock(12345); call_stats_.reset(new CallStats()); } - scoped_ptr call_stats_; + rtc::scoped_ptr call_stats_; }; TEST_F(CallStatsTest, AddAndTriggerCallback) { @@ -44,21 +44,21 @@ TEST_F(CallStatsTest, AddAndTriggerCallback) { RtcpRttStats* rtcp_rtt_stats = call_stats_->rtcp_rtt_stats(); call_stats_->RegisterStatsObserver(&stats_observer); TickTime::AdvanceFakeClock(1000); - EXPECT_EQ(0U, rtcp_rtt_stats->LastProcessedRtt()); + EXPECT_EQ(0, rtcp_rtt_stats->LastProcessedRtt()); - const uint32_t kRtt = 25; + const int64_t kRtt = 25; rtcp_rtt_stats->OnRttUpdate(kRtt); EXPECT_CALL(stats_observer, OnRttUpdate(kRtt)) .Times(1); call_stats_->Process(); EXPECT_EQ(kRtt, rtcp_rtt_stats->LastProcessedRtt()); - const int kRttTimeOutMs = 1500 + 10; + const int64_t kRttTimeOutMs = 1500 + 10; TickTime::AdvanceFakeClock(kRttTimeOutMs); EXPECT_CALL(stats_observer, OnRttUpdate(_)) .Times(0); call_stats_->Process(); - EXPECT_EQ(0U, rtcp_rtt_stats->LastProcessedRtt()); + EXPECT_EQ(0, rtcp_rtt_stats->LastProcessedRtt()); call_stats_->DeregisterStatsObserver(&stats_observer); } @@ -101,42 +101,42 @@ TEST_F(CallStatsTest, ProcessTime) { TEST_F(CallStatsTest, MultipleObservers) { MockStatsObserver stats_observer_1; call_stats_->RegisterStatsObserver(&stats_observer_1); - // Add the secondobserver twice, there should still be only one report to the + // Add the second observer twice, there should still be only one report to the // observer. MockStatsObserver stats_observer_2; call_stats_->RegisterStatsObserver(&stats_observer_2); call_stats_->RegisterStatsObserver(&stats_observer_2); RtcpRttStats* rtcp_rtt_stats = call_stats_->rtcp_rtt_stats(); - uint32_t rtt = 100; - rtcp_rtt_stats->OnRttUpdate(rtt); + const int64_t kRtt = 100; + rtcp_rtt_stats->OnRttUpdate(kRtt); // Verify both observers are updated. TickTime::AdvanceFakeClock(1000); - EXPECT_CALL(stats_observer_1, OnRttUpdate(rtt)) + EXPECT_CALL(stats_observer_1, OnRttUpdate(kRtt)) .Times(1); - EXPECT_CALL(stats_observer_2, OnRttUpdate(rtt)) + EXPECT_CALL(stats_observer_2, OnRttUpdate(kRtt)) .Times(1); call_stats_->Process(); // Deregister the second observer and verify update is only sent to the first // observer. call_stats_->DeregisterStatsObserver(&stats_observer_2); - rtcp_rtt_stats->OnRttUpdate(rtt); + rtcp_rtt_stats->OnRttUpdate(kRtt); TickTime::AdvanceFakeClock(1000); - EXPECT_CALL(stats_observer_1, OnRttUpdate(rtt)) + EXPECT_CALL(stats_observer_1, OnRttUpdate(kRtt)) .Times(1); - EXPECT_CALL(stats_observer_2, OnRttUpdate(rtt)) + EXPECT_CALL(stats_observer_2, OnRttUpdate(kRtt)) .Times(0); call_stats_->Process(); // Deregister the first observer. call_stats_->DeregisterStatsObserver(&stats_observer_1); - rtcp_rtt_stats->OnRttUpdate(rtt); + rtcp_rtt_stats->OnRttUpdate(kRtt); TickTime::AdvanceFakeClock(1000); - EXPECT_CALL(stats_observer_1, OnRttUpdate(rtt)) + EXPECT_CALL(stats_observer_1, OnRttUpdate(kRtt)) .Times(0); - EXPECT_CALL(stats_observer_2, OnRttUpdate(rtt)) + EXPECT_CALL(stats_observer_2, OnRttUpdate(kRtt)) .Times(0); call_stats_->Process(); } @@ -151,17 +151,17 @@ TEST_F(CallStatsTest, ChangeRtt) { TickTime::AdvanceFakeClock(1000); // Set a first value and verify the callback is triggered. - const uint32_t first_rtt = 100; - rtcp_rtt_stats->OnRttUpdate(first_rtt); - EXPECT_CALL(stats_observer, OnRttUpdate(first_rtt)) + const int64_t kFirstRtt = 100; + rtcp_rtt_stats->OnRttUpdate(kFirstRtt); + EXPECT_CALL(stats_observer, OnRttUpdate(kFirstRtt)) .Times(1); call_stats_->Process(); // Increase rtt and verify the new value is reported. TickTime::AdvanceFakeClock(1000); - const uint32_t high_rtt = first_rtt + 20; - rtcp_rtt_stats->OnRttUpdate(high_rtt); - EXPECT_CALL(stats_observer, OnRttUpdate(high_rtt)) + const int64_t kHighRtt = kFirstRtt + 20; + rtcp_rtt_stats->OnRttUpdate(kHighRtt); + EXPECT_CALL(stats_observer, OnRttUpdate(kHighRtt)) .Times(1); call_stats_->Process(); @@ -169,20 +169,50 @@ TEST_F(CallStatsTest, ChangeRtt) { // rtt invalid. Report a lower rtt and verify the old/high value still is sent // in the callback. TickTime::AdvanceFakeClock(1000); - const uint32_t low_rtt = first_rtt - 20; - rtcp_rtt_stats->OnRttUpdate(low_rtt); - EXPECT_CALL(stats_observer, OnRttUpdate(high_rtt)) + const int64_t kLowRtt = kFirstRtt - 20; + rtcp_rtt_stats->OnRttUpdate(kLowRtt); + EXPECT_CALL(stats_observer, OnRttUpdate(kHighRtt)) .Times(1); call_stats_->Process(); // Advance time to make the high report invalid, the lower rtt should now be // in the callback. TickTime::AdvanceFakeClock(1000); - EXPECT_CALL(stats_observer, OnRttUpdate(low_rtt)) + EXPECT_CALL(stats_observer, OnRttUpdate(kLowRtt)) .Times(1); call_stats_->Process(); call_stats_->DeregisterStatsObserver(&stats_observer); } +TEST_F(CallStatsTest, LastProcessedRtt) { + MockStatsObserver stats_observer; + call_stats_->RegisterStatsObserver(&stats_observer); + RtcpRttStats* rtcp_rtt_stats = call_stats_->rtcp_rtt_stats(); + TickTime::AdvanceFakeClock(1000); + + // Set a first values and verify that LastProcessedRtt initially returns the + // average rtt. + const int64_t kRttLow = 10; + const int64_t kRttHigh = 30; + const int64_t kAvgRtt = 20; + rtcp_rtt_stats->OnRttUpdate(kRttLow); + rtcp_rtt_stats->OnRttUpdate(kRttHigh); + EXPECT_CALL(stats_observer, OnRttUpdate(kRttHigh)) + .Times(1); + call_stats_->Process(); + EXPECT_EQ(kAvgRtt, rtcp_rtt_stats->LastProcessedRtt()); + + // Update values and verify LastProcessedRtt. + TickTime::AdvanceFakeClock(1000); + rtcp_rtt_stats->OnRttUpdate(kRttLow); + rtcp_rtt_stats->OnRttUpdate(kRttHigh); + EXPECT_CALL(stats_observer, OnRttUpdate(kRttHigh)) + .Times(1); + call_stats_->Process(); + EXPECT_EQ(kAvgRtt, rtcp_rtt_stats->LastProcessedRtt()); + + call_stats_->DeregisterStatsObserver(&stats_observer); +} + } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.cc b/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.cc index 31861b53cf..0c0b69f1c8 100644 --- a/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.cc +++ b/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.cc @@ -124,7 +124,7 @@ int32_t ScreenDeviceInfoImpl::GetBestMatchedCapability(const char* deviceUniqueI } int32_t ScreenDeviceInfoImpl::GetOrientation(const char* deviceUniqueIdUTF8, - VideoCaptureRotation& orientation) { + VideoRotation& orientation) { return 0; } @@ -216,7 +216,7 @@ int32_t AppDeviceInfoImpl::GetBestMatchedCapability( } int32_t AppDeviceInfoImpl::GetOrientation(const char* deviceUniqueIdUTF8, - VideoCaptureRotation& orientation) { + VideoRotation& orientation) { return 0; } @@ -320,7 +320,7 @@ int32_t WindowDeviceInfoImpl::GetBestMatchedCapability(const char* deviceUniqueI } int32_t WindowDeviceInfoImpl::GetOrientation(const char* deviceUniqueIdUTF8, - VideoCaptureRotation& orientation) { + VideoRotation& orientation) { return 0; } @@ -355,11 +355,6 @@ const char* DesktopCaptureImpl::CurrentDeviceName() const { return _deviceUniqueId.c_str(); } -int32_t DesktopCaptureImpl::ChangeUniqueId(const int32_t id) { - _id = id; - return 0; -} - int32_t DesktopCaptureImpl::Init(const char* uniqueId, const CaptureDeviceType type) { DesktopCaptureOptions options = DesktopCaptureOptions::CreateDefault(); @@ -407,11 +402,11 @@ int32_t DesktopCaptureImpl::Init(const char* uniqueId, } // returns the number of milliseconds until the module want a worker thread to call Process -int32_t DesktopCaptureImpl::TimeUntilNextProcess() { +int64_t DesktopCaptureImpl::TimeUntilNextProcess() { CriticalSectionScoped cs(&_callBackCs); - int32_t timeToNormalProcess = kProcessInterval - - (int32_t)((TickTime::Now() - _lastProcessTime).Milliseconds()); + int64_t timeToNormalProcess = 300 + - (int64_t)((TickTime::Now() - _lastProcessTime).Milliseconds()); return timeToNormalProcess; } @@ -469,18 +464,19 @@ DesktopCaptureImpl::DesktopCaptureImpl(const int32_t id) _setCaptureDelay(0), _dataCallBack(NULL), _captureCallBack(NULL), - _lastProcessFrameCount(TickTime::Now()), - _rotateFrame(kRotateNone), + _lastProcessFrameCount(TickTime::Now()), + _rotateFrame(kVideoRotation_0), last_capture_time_(TickTime::MillisecondTimestamp()), delta_ntp_internal_ms_( Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() - TickTime::MillisecondTimestamp()), - time_event_(*EventWrapper::Create()), + time_event_(EventWrapper::Create()), #if defined(_WIN32) - capturer_thread_(*ThreadWrapper::CreateUIThread(Run, this, kHighPriority, "ScreenCaptureThread")) { + capturer_thread_(ThreadWrapper::CreateUIThread(Run, this, "ScreenCaptureThread")) { #else - capturer_thread_(*ThreadWrapper::CreateThread(Run, this, kHighPriority, "ScreenCaptureThread")) { + capturer_thread_(ThreadWrapper::CreateThread(Run, this, "ScreenCaptureThread")) { #endif + capturer_thread_->SetPriority(kHighPriority); _requestedCapability.width = kDefaultWidth; _requestedCapability.height = kDefaultHeight; _requestedCapability.maxFPS = 30; @@ -490,10 +486,8 @@ DesktopCaptureImpl::DesktopCaptureImpl(const int32_t id) } DesktopCaptureImpl::~DesktopCaptureImpl() { - time_event_.Set(); - capturer_thread_.Stop(); - delete &time_event_; - delete &capturer_thread_; + time_event_->Set(); + capturer_thread_->Stop(); DeRegisterCaptureDataCallback(); DeRegisterCaptureCallback(); @@ -579,7 +573,7 @@ int32_t DesktopCaptureImpl::DeliverCapturedFrame(I420VideoFrame& captureFrame, // Copied from VideoCaptureImpl::IncomingFrame. See Bug 1038324 int32_t DesktopCaptureImpl::IncomingFrame(uint8_t* videoFrame, - int32_t videoFrameLength, + size_t videoFrameLength, const VideoCaptureCapability& frameInfo, int64_t captureTime/*=0*/) { @@ -614,7 +608,7 @@ int32_t DesktopCaptureImpl::IncomingFrame(uint8_t* videoFrame, int target_width = width; int target_height = abs(height); // Rotating resolution when for 90/270 degree rotations. - if (_rotateFrame == kRotate90 || _rotateFrame == kRotate270) { + if (_rotateFrame == kVideoRotation_90 || _rotateFrame == kVideoRotation_270) { target_height = width; target_width = abs(height); } @@ -719,50 +713,15 @@ int32_t DesktopCaptureImpl::IncomingFrame(uint8_t* videoFrame, return 0; } -int32_t DesktopCaptureImpl::IncomingI420VideoFrame(I420VideoFrame* video_frame, int64_t captureTime) { - - CriticalSectionScoped cs(&_callBackCs); - int stride_y = video_frame->stride(kYPlane); - int stride_u = video_frame->stride(kUPlane); - int stride_v = video_frame->stride(kVPlane); - int size_y = video_frame->height() * stride_y; - int size_u = stride_u * ((video_frame->height() + 1) / 2); - int size_v = stride_v * ((video_frame->height() + 1) / 2); - int ret = _captureFrame.CreateFrame(size_y, video_frame->buffer(kYPlane), - size_u, video_frame->buffer(kUPlane), - size_v, video_frame->buffer(kVPlane), - video_frame->width(), video_frame->height(), - stride_y, stride_u, stride_v); - - if (ret < 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, - "Failed to create I420VideoFrame"); - return -1; - } - - DeliverCapturedFrame(_captureFrame, captureTime); - +int32_t DesktopCaptureImpl::SetCaptureRotation(VideoRotation rotation) { + CriticalSectionScoped cs(&_apiCs); + CriticalSectionScoped cs2(&_callBackCs); + _rotateFrame = rotation; return 0; } -int32_t DesktopCaptureImpl::SetCaptureRotation(VideoCaptureRotation rotation) { - CriticalSectionScoped cs(&_apiCs); - CriticalSectionScoped cs2(&_callBackCs); - switch (rotation) { - case kCameraRotate0: - _rotateFrame = kRotateNone; - break; - case kCameraRotate90: - _rotateFrame = kRotate90; - break; - case kCameraRotate180: - _rotateFrame = kRotate180; - break; - case kCameraRotate270: - _rotateFrame = kRotate270; - break; - } - return 0; +bool DesktopCaptureImpl::SetApplyRotation(bool enable) { + return true; } void DesktopCaptureImpl::EnableFrameRateCallback(const bool enable) { @@ -817,15 +776,14 @@ uint32_t DesktopCaptureImpl::CalculateFrameRate(const TickTime& now) { int32_t DesktopCaptureImpl::StartCapture(const VideoCaptureCapability& capability) { _requestedCapability = capability; - desktop_capturer_cursor_composer_->Start(this); - unsigned int t_id =0; - capturer_thread_.Start(t_id); - #if defined(_WIN32) uint32_t maxFPSNeeded = 1000/_requestedCapability.maxFPS; - capturer_thread_.RequestCallbackTimer(maxFPSNeeded); + capturer_thread_->RequestCallbackTimer(maxFPSNeeded); #endif + desktop_capturer_cursor_composer_->Start(this); + capturer_thread_->Start(); + return 0; } @@ -852,7 +810,7 @@ void DesktopCaptureImpl::OnCaptureCompleted(DesktopFrame* frame) { // combine cursor in frame // Latest WebRTC already support it by DesktopFrameWithCursor/DesktopAndCursorComposer. - int32_t videoFrameLength = frameInfo.width * frameInfo.height * DesktopFrame::kBytesPerPixel; + size_t videoFrameLength = frameInfo.width * frameInfo.height * DesktopFrame::kBytesPerPixel; IncomingFrame(videoFrame, videoFrameLength, frameInfo); delete frame; //handled it, so we need delete it } @@ -878,7 +836,7 @@ void DesktopCaptureImpl::process() { const uint32_t maxFPSNeeded = 1000/_requestedCapability.maxFPS; const float sleepTimeFactor = (100.0f / kMaxDesktopCaptureCpuUsage) - 1.0f; const uint32_t sleepTime = sleepTimeFactor * processTime; - time_event_.Wait(std::max(maxFPSNeeded, sleepTime)); + time_event_->Wait(std::max(maxFPSNeeded, sleepTime)); #endif } diff --git a/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.h b/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.h index 681a67ed85..dfa7a6465c 100644 --- a/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.h +++ b/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.h @@ -71,10 +71,10 @@ public: const VideoCaptureCapability& requested, VideoCaptureCapability& resulting); virtual int32_t GetOrientation(const char* deviceUniqueIdUTF8, - VideoCaptureRotation& orientation); + VideoRotation& orientation); protected: int32_t _id; - scoped_ptr desktop_device_info_; + rtc::scoped_ptr desktop_device_info_; }; @@ -109,10 +109,10 @@ public: const VideoCaptureCapability& requested, VideoCaptureCapability& resulting); virtual int32_t GetOrientation(const char* deviceUniqueIdUTF8, - VideoCaptureRotation& orientation); + VideoRotation& orientation); protected: int32_t _id; - scoped_ptr desktop_device_info_; + rtc::scoped_ptr desktop_device_info_; }; class WindowDeviceInfoImpl : public VideoCaptureModule::DeviceInfo { @@ -146,10 +146,10 @@ public: const VideoCaptureCapability& requested, VideoCaptureCapability& resulting); virtual int32_t GetOrientation(const char* deviceUniqueIdUTF8, - VideoCaptureRotation& orientation); + VideoRotation& orientation); protected: int32_t _id; - scoped_ptr desktop_device_info_; + rtc::scoped_ptr desktop_device_info_; }; @@ -168,48 +168,45 @@ public: static VideoCaptureModule::DeviceInfo* CreateDeviceInfo(const int32_t id, const CaptureDeviceType type); int32_t Init(const char* uniqueId, const CaptureDeviceType type); - // Implements Module declared functions. - virtual int32_t ChangeUniqueId(const int32_t id) OVERRIDE; //Call backs - virtual void RegisterCaptureDataCallback(VideoCaptureDataCallback& dataCallback) OVERRIDE; - virtual void DeRegisterCaptureDataCallback() OVERRIDE; - virtual void RegisterCaptureCallback(VideoCaptureFeedBack& callBack) OVERRIDE; - virtual void DeRegisterCaptureCallback() OVERRIDE; + virtual void RegisterCaptureDataCallback(VideoCaptureDataCallback& dataCallback) override; + virtual void DeRegisterCaptureDataCallback() override; + virtual void RegisterCaptureCallback(VideoCaptureFeedBack& callBack) override; + virtual void DeRegisterCaptureCallback() override; - virtual void SetCaptureDelay(int32_t delayMS) OVERRIDE; - virtual int32_t CaptureDelay() OVERRIDE; - virtual int32_t SetCaptureRotation(VideoCaptureRotation rotation) OVERRIDE; + virtual void SetCaptureDelay(int32_t delayMS) override; + virtual int32_t CaptureDelay() override; + virtual int32_t SetCaptureRotation(VideoRotation rotation) override; + virtual bool SetApplyRotation(bool enable) override; + virtual bool GetApplyRotation() { return true; } - virtual void EnableFrameRateCallback(const bool enable) OVERRIDE; - virtual void EnableNoPictureAlarm(const bool enable) OVERRIDE; + virtual void EnableFrameRateCallback(const bool enable) override; + virtual void EnableNoPictureAlarm(const bool enable) override; - virtual const char* CurrentDeviceName() const OVERRIDE; + virtual const char* CurrentDeviceName() const override; // Module handling - virtual int32_t TimeUntilNextProcess() OVERRIDE; - virtual int32_t Process() OVERRIDE; + virtual int64_t TimeUntilNextProcess() override; + virtual int32_t Process() override; // Implement VideoCaptureExternal // |capture_time| must be specified in the NTP time format in milliseconds. virtual int32_t IncomingFrame(uint8_t* videoFrame, - int32_t videoFrameLength, + size_t videoFrameLength, const VideoCaptureCapability& frameInfo, - int64_t captureTime = 0) OVERRIDE; - virtual int32_t IncomingI420VideoFrame( - I420VideoFrame* video_frame, - int64_t captureTime = 0) OVERRIDE; + int64_t captureTime = 0) override; // Platform dependent - virtual int32_t StartCapture(const VideoCaptureCapability& capability) OVERRIDE; - virtual int32_t StopCapture() OVERRIDE; - virtual bool CaptureStarted() OVERRIDE; - virtual int32_t CaptureSettings(VideoCaptureCapability& settings) OVERRIDE; - VideoCaptureEncodeInterface* GetEncodeInterface(const VideoCodec& codec) OVERRIDE { return NULL; } + virtual int32_t StartCapture(const VideoCaptureCapability& capability) override; + virtual int32_t StopCapture() override; + virtual bool CaptureStarted() override; + virtual int32_t CaptureSettings(VideoCaptureCapability& settings) override; + VideoCaptureEncodeInterface* GetEncodeInterface(const VideoCodec& codec) override { return NULL; } //ScreenCapturer::Callback - virtual SharedMemory* CreateSharedMemory(size_t size) OVERRIDE; - virtual void OnCaptureCompleted(DesktopFrame* frame) OVERRIDE; + virtual SharedMemory* CreateSharedMemory(size_t size) override; + virtual void OnCaptureCompleted(DesktopFrame* frame) override; protected: DesktopCaptureImpl(const int32_t id); @@ -243,10 +240,9 @@ private: TickTime _lastProcessFrameCount; TickTime _incomingFrameTimes[kFrameRateCountHistorySize];// timestamp for local captured frames - VideoRotationMode _rotateFrame; //Set if the frame should be rotated by the capture module. + VideoRotation _rotateFrame; //Set if the frame should be rotated by the capture module. I420VideoFrame _captureFrame; - VideoFrame _capture_encoded_frame; // Used to make sure incoming timestamp is increasing for every frame. int64_t last_capture_time_; @@ -262,9 +258,9 @@ public: void process(); private: - scoped_ptr desktop_capturer_cursor_composer_; - EventWrapper& time_event_; - ThreadWrapper& capturer_thread_; + rtc::scoped_ptr desktop_capturer_cursor_composer_; + rtc::scoped_ptr time_event_; + rtc::scoped_ptr capturer_thread_; }; } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/encoder_state_feedback.h b/media/webrtc/trunk/webrtc/video_engine/encoder_state_feedback.h index a58532ce7f..998793a254 100644 --- a/media/webrtc/trunk/webrtc/video_engine/encoder_state_feedback.h +++ b/media/webrtc/trunk/webrtc/video_engine/encoder_state_feedback.h @@ -17,7 +17,7 @@ #include #include "webrtc/base/constructormagic.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -54,10 +54,10 @@ class EncoderStateFeedback { private: typedef std::map SsrcEncoderMap; - scoped_ptr crit_; + rtc::scoped_ptr crit_; // Instance registered at the class requesting new key frames. - scoped_ptr observer_; + rtc::scoped_ptr observer_; // Maps a unique ssrc to the given encoder. SsrcEncoderMap encoders_; diff --git a/media/webrtc/trunk/webrtc/video_engine/encoder_state_feedback_unittest.cc b/media/webrtc/trunk/webrtc/video_engine/encoder_state_feedback_unittest.cc index 4e15752fde..eab33d407a 100644 --- a/media/webrtc/trunk/webrtc/video_engine/encoder_state_feedback_unittest.cc +++ b/media/webrtc/trunk/webrtc/video_engine/encoder_state_feedback_unittest.cc @@ -15,10 +15,13 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/common.h" +#include "webrtc/modules/pacing/include/paced_sender.h" +#include "webrtc/modules/pacing/include/packet_router.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" #include "webrtc/modules/utility/interface/mock/mock_process_thread.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/video_engine/payload_router.h" #include "webrtc/video_engine/vie_encoder.h" using ::testing::NiceMock; @@ -27,8 +30,8 @@ namespace webrtc { class MockVieEncoder : public ViEEncoder { public: - explicit MockVieEncoder(ProcessThread* process_thread) - : ViEEncoder(1, 1, 1, config_, *process_thread, NULL) {} + explicit MockVieEncoder(ProcessThread* process_thread, PacedSender* pacer) + : ViEEncoder(1, 1, config_, *process_thread, pacer, NULL, NULL, false) {} ~MockVieEncoder() {} MOCK_METHOD1(OnReceivedIntraFrameRequest, @@ -45,17 +48,26 @@ class MockVieEncoder : public ViEEncoder { class VieKeyRequestTest : public ::testing::Test { protected: + VieKeyRequestTest() + : pacer_(Clock::GetRealTimeClock(), + &router_, + BitrateController::kDefaultStartBitrateKbps, + PacedSender::kDefaultPaceMultiplier * + BitrateController::kDefaultStartBitrateKbps, + 0) {} virtual void SetUp() { process_thread_.reset(new NiceMock); encoder_state_feedback_.reset(new EncoderStateFeedback()); } - scoped_ptr process_thread_; - scoped_ptr encoder_state_feedback_; + rtc::scoped_ptr process_thread_; + rtc::scoped_ptr encoder_state_feedback_; + PacketRouter router_; + PacedSender pacer_; }; TEST_F(VieKeyRequestTest, CreateAndTriggerRequests) { const int ssrc = 1234; - MockVieEncoder encoder(process_thread_.get()); + MockVieEncoder encoder(process_thread_.get(), &pacer_); EXPECT_TRUE(encoder_state_feedback_->AddEncoder(ssrc, &encoder)); EXPECT_CALL(encoder, OnReceivedIntraFrameRequest(ssrc)) @@ -83,8 +95,8 @@ TEST_F(VieKeyRequestTest, CreateAndTriggerRequests) { TEST_F(VieKeyRequestTest, MultipleEncoders) { const int ssrc_1 = 1234; const int ssrc_2 = 5678; - MockVieEncoder encoder_1(process_thread_.get()); - MockVieEncoder encoder_2(process_thread_.get()); + MockVieEncoder encoder_1(process_thread_.get(), &pacer_); + MockVieEncoder encoder_2(process_thread_.get(), &pacer_); EXPECT_TRUE(encoder_state_feedback_->AddEncoder(ssrc_1, &encoder_1)); EXPECT_TRUE(encoder_state_feedback_->AddEncoder(ssrc_2, &encoder_2)); @@ -129,7 +141,7 @@ TEST_F(VieKeyRequestTest, MultipleEncoders) { TEST_F(VieKeyRequestTest, AddTwiceError) { const int ssrc = 1234; - MockVieEncoder encoder(process_thread_.get()); + MockVieEncoder encoder(process_thread_.get(), &pacer_); EXPECT_TRUE(encoder_state_feedback_->AddEncoder(ssrc, &encoder)); EXPECT_FALSE(encoder_state_feedback_->AddEncoder(ssrc, &encoder)); encoder_state_feedback_->RemoveEncoder(&encoder); diff --git a/media/webrtc/trunk/webrtc/video_engine/include/vie_base.h b/media/webrtc/trunk/webrtc/video_engine/include/vie_base.h index 203a5c0ab1..4e0b15355b 100644 --- a/media/webrtc/trunk/webrtc/video_engine/include/vie_base.h +++ b/media/webrtc/trunk/webrtc/video_engine/include/vie_base.h @@ -29,6 +29,8 @@ namespace webrtc { class Config; class VoiceEngine; +class ReceiveStatisticsProxy; +class SendStatisticsProxy; // CpuOveruseObserver is called when a system overuse is detected and // VideoEngine cannot keep up the encoding frequency. @@ -45,12 +47,12 @@ class CpuOveruseObserver { struct CpuOveruseOptions { CpuOveruseOptions() - : enable_capture_jitter_method(true), + : enable_capture_jitter_method(false), low_capture_jitter_threshold_ms(20.0f), high_capture_jitter_threshold_ms(30.0f), - enable_encode_usage_method(false), - low_encode_usage_threshold_percent(60), - high_encode_usage_threshold_percent(90), + enable_encode_usage_method(true), + low_encode_usage_threshold_percent(55), + high_encode_usage_threshold_percent(85), low_encode_time_rsd_threshold(-1), high_encode_time_rsd_threshold(-1), enable_extended_processing_usage(true), @@ -114,7 +116,6 @@ struct CpuOveruseMetrics { : capture_jitter_ms(-1), avg_encode_time_ms(-1), encode_usage_percent(-1), - encode_rsd(-1), capture_queue_delay_ms_per_s(-1) {} int capture_jitter_ms; // The current estimated jitter in ms based on @@ -122,14 +123,18 @@ struct CpuOveruseMetrics { int avg_encode_time_ms; // The average encode time in ms. int encode_usage_percent; // The average encode time divided by the average // time difference between incoming captured frames. - // TODO(asapersson): Remove metric, not used. - int encode_rsd; // The relative std dev of encode time of frames. int capture_queue_delay_ms_per_s; // The current time delay between an // incoming captured frame until the frame // is being processed. The delay is // expressed in ms delay per second. }; +class CpuOveruseMetricsObserver { + public: + virtual ~CpuOveruseMetricsObserver() {} + virtual void CpuOveruseMetricsUpdated(const CpuOveruseMetrics& metrics) = 0; +}; + class WEBRTC_DLLEXPORT VideoEngine { public: // Creates a VideoEngine object, which can then be used to acquire sub‐APIs. @@ -191,6 +196,9 @@ class WEBRTC_DLLEXPORT ViEBase { virtual int CreateChannel(int& video_channel, int original_channel) = 0; + virtual int CreateChannelWithoutDefaultEncoder(int& video_channel, + int original_channel) = 0; + // Creates a new channel grouped together with |original_channel|. The channel // can only receive video and it is assumed the remote end-point is the same // as for |original_channel|. @@ -212,6 +220,9 @@ class WEBRTC_DLLEXPORT ViEBase { // Gets cpu overuse measures. virtual int GetCpuOveruseMetrics(int channel, CpuOveruseMetrics* metrics) = 0; + virtual void RegisterCpuOveruseMetricsObserver( + int channel, + CpuOveruseMetricsObserver* observer) = 0; // Registers a callback which is called when send-side delay statistics has // been updated. @@ -251,6 +262,14 @@ class WEBRTC_DLLEXPORT ViEBase { // Returns the last VideoEngine error code. virtual int LastError() = 0; + virtual void RegisterSendStatisticsProxy( + int channel, + SendStatisticsProxy* send_statistics_proxy) = 0; + + virtual void RegisterReceiveStatisticsProxy( + int channel, + ReceiveStatisticsProxy* receive_statistics_proxy) = 0; + protected: ViEBase() {} virtual ~ViEBase() {} diff --git a/media/webrtc/trunk/webrtc/video_engine/include/vie_capture.h b/media/webrtc/trunk/webrtc/video_engine/include/vie_capture.h index 8150725a88..3c722b0af2 100644 --- a/media/webrtc/trunk/webrtc/video_engine/include/vie_capture.h +++ b/media/webrtc/trunk/webrtc/video_engine/include/vie_capture.h @@ -20,6 +20,7 @@ #include "webrtc/common_types.h" #include "webrtc/common_video/interface/i420_video_frame.h" +#include "webrtc/common_video/rotation.h" namespace webrtc { @@ -74,37 +75,6 @@ enum CaptureAlarm { AlarmCleared = 1 }; -enum RotateCapturedFrame { - RotateCapturedFrame_0 = 0, - RotateCapturedFrame_90 = 90, - RotateCapturedFrame_180 = 180, - RotateCapturedFrame_270 = 270 -}; - -struct ViEVideoFrameI420 { - ViEVideoFrameI420() { - y_plane = NULL; - u_plane = NULL; - v_plane = NULL; - y_pitch = 0; - u_pitch = 0; - v_pitch = 0; - width = 0; - height = 0; - } - - unsigned char* y_plane; - unsigned char* u_plane; - unsigned char* v_plane; - - int y_pitch; - int u_pitch; - int v_pitch; - - unsigned short width; - unsigned short height; -}; - // This class declares an abstract interface to be used when implementing // a user-defined capture device. This interface is not meant to be // implemented by the user. Instead, the user should call AllocateCaptureDevice @@ -118,22 +88,7 @@ class WEBRTC_DLLEXPORT ViEExternalCapture { // This method is called by the user to deliver a new captured frame to // VideoEngine. - // |capture_time| must be specified in the NTP time format in milliseconds. - virtual int IncomingFrame(unsigned char* video_frame, - unsigned int video_frame_length, - unsigned short width, - unsigned short height, - RawVideoType video_type, - unsigned long long capture_time = 0) = 0; - - // This method is specifically for delivering a new captured I420 frame to - // VideoEngine. - // |capture_time| must be specified in the NTP time format in milliseconds. - virtual int IncomingFrameI420( - const ViEVideoFrameI420& video_frame, - unsigned long long capture_time = 0) = 0; - - virtual void SwapFrame(I420VideoFrame* frame) {} + virtual void IncomingFrame(const I420VideoFrame& frame) = 0; }; // This class declares an abstract interface for a user defined observer. It is @@ -217,8 +172,8 @@ class WEBRTC_DLLEXPORT ViECapture { // Rotates captured frames before encoding and sending. // Used on mobile devices with rotates cameras. - virtual int SetRotateCapturedFrames(const int capture_id, - const RotateCapturedFrame rotation) = 0; + virtual int SetVideoRotation(const int capture_id, + const VideoRotation rotation) = 0; // This function sets the expected delay from when a video frame is captured // to when that frame is delivered to VideoEngine. @@ -251,7 +206,7 @@ class WEBRTC_DLLEXPORT ViECapture { // order to display the frames correctly if the display is rotated in its // natural orientation. virtual int GetOrientation(const char* unique_id_utf8, - RotateCapturedFrame& orientation) = 0; + VideoRotation& orientation) = 0; // Enables brightness alarm detection and the brightness alarm callback. virtual int EnableBrightnessAlarm(const int capture_id, diff --git a/media/webrtc/trunk/webrtc/video_engine/include/vie_codec.h b/media/webrtc/trunk/webrtc/video_engine/include/vie_codec.h index bf4869892e..dbdbde91cb 100644 --- a/media/webrtc/trunk/webrtc/video_engine/include/vie_codec.h +++ b/media/webrtc/trunk/webrtc/video_engine/include/vie_codec.h @@ -147,6 +147,8 @@ class WEBRTC_DLLEXPORT ViECodec { virtual int GetReceiveSideDelay(const int video_channel, int* delay_ms) const = 0; + // Current target bitrate for this channel. + virtual uint32_t GetLastObservedBitrateBps(int video_channel) const = 0; // Gets the bitrate targeted by the video codec rate control in kbit/s. virtual int GetCodecTargetBitrate(const int video_channel, unsigned int* bitrate) const = 0; diff --git a/media/webrtc/trunk/webrtc/video_engine/include/vie_external_codec.h b/media/webrtc/trunk/webrtc/video_engine/include/vie_external_codec.h index 536995ee0a..99018dbcd2 100644 --- a/media/webrtc/trunk/webrtc/video_engine/include/vie_external_codec.h +++ b/media/webrtc/trunk/webrtc/video_engine/include/vie_external_codec.h @@ -34,7 +34,7 @@ class WEBRTC_DLLEXPORT ViEExternalCodec { const unsigned char pl_type) = 0; virtual int RegisterExternalReceiveCodec(const int video_channel, - const unsigned int pl_type, + const unsigned char pl_type, VideoDecoder* decoder, bool decoder_render = false, int render_delay = 0) = 0; diff --git a/media/webrtc/trunk/webrtc/video_engine/include/vie_image_process.h b/media/webrtc/trunk/webrtc/video_engine/include/vie_image_process.h index 8bb895fb58..adf0c199c9 100644 --- a/media/webrtc/trunk/webrtc/video_engine/include/vie_image_process.h +++ b/media/webrtc/trunk/webrtc/video_engine/include/vie_image_process.h @@ -32,7 +32,7 @@ class WEBRTC_DLLEXPORT ViEEffectFilter { public: // This method is called with an I420 video frame allowing the user to // modify the video frame. - virtual int Transform(int size, + virtual int Transform(size_t size, unsigned char* frame_buffer, int64_t ntp_time_ms, unsigned int timestamp, diff --git a/media/webrtc/trunk/webrtc/video_engine/include/vie_network.h b/media/webrtc/trunk/webrtc/video_engine/include/vie_network.h index bb368182cf..e962e729aa 100644 --- a/media/webrtc/trunk/webrtc/video_engine/include/vie_network.h +++ b/media/webrtc/trunk/webrtc/video_engine/include/vie_network.h @@ -47,6 +47,11 @@ class WEBRTC_DLLEXPORT ViENetwork { // for all sub-API:s before the VideoEngine object can be safely deleted. virtual int Release() = 0; + virtual void SetBitrateConfig(int video_channel, + int min_bitrate_bps, + int start_bitrate_bps, + int max_bitrate_bps) = 0; + // Inform the engine about if the network adapter is currently transmitting // packets or not. virtual void SetNetworkTransmissionState(const int video_channel, @@ -65,14 +70,14 @@ class WEBRTC_DLLEXPORT ViENetwork { // the RTP header and payload. virtual int ReceivedRTPPacket(const int video_channel, const void* data, - const int length, + const size_t length, const PacketTime& packet_time) = 0; // When using external transport for a channel, received RTCP packets should // be passed to VideoEngine using this function. virtual int ReceivedRTCPPacket(const int video_channel, const void* data, - const int length) = 0; + const size_t length) = 0; // This function sets the Maximum Transition Unit (MTU) for a channel. The // RTP packet will be packetized based on this MTU to optimize performance @@ -82,17 +87,10 @@ class WEBRTC_DLLEXPORT ViENetwork { // Forward (audio) packet to bandwidth estimator for the given video channel, // for aggregated audio+video BWE. virtual int ReceivedBWEPacket(const int video_channel, - int64_t arrival_time_ms, int payload_size, const RTPHeader& header) { + int64_t arrival_time_ms, size_t payload_size, const RTPHeader& header) { return 0; } - // TODO(holmer): Remove the default implementation when this has been fixed - // in fakewebrtcvideoengine.cc. - virtual bool SetBandwidthEstimationConfig(int video_channel, - const webrtc::Config& config) { - return false; - } - protected: ViENetwork() {} virtual ~ViENetwork() {} diff --git a/media/webrtc/trunk/webrtc/video_engine/include/vie_render.h b/media/webrtc/trunk/webrtc/video_engine/include/vie_render.h index 2c9b0f55b3..8d3f2b5a1a 100644 --- a/media/webrtc/trunk/webrtc/video_engine/include/vie_render.h +++ b/media/webrtc/trunk/webrtc/video_engine/include/vie_render.h @@ -20,6 +20,7 @@ namespace webrtc { +class I420VideoFrame; class VideoEngine; class VideoRender; class VideoRenderCallback; @@ -36,7 +37,7 @@ class ExternalRenderer { // This method is called when a new frame should be rendered. virtual int DeliverFrame(unsigned char* buffer, - int buffer_size, + size_t buffer_size, // RTP timestamp in 90kHz. uint32_t timestamp, // NTP time of the capture time in local timebase @@ -47,6 +48,9 @@ class ExternalRenderer { // Handle of the underlying video frame. void* handle) = 0; + // Alternative interface for I420 frames. + virtual int DeliverI420Frame(const webrtc::I420VideoFrame& webrtc_frame) = 0; + // Returns true if the renderer supports textures. DeliverFrame can be called // with NULL |buffer| and non-NULL |handle|. virtual bool IsTextureSupported() = 0; @@ -104,24 +108,11 @@ class ViERender { const float right, const float bottom) = 0; - // This function mirrors the rendered stream left and right or up and down. - virtual int MirrorRenderStream(const int render_id, - const bool enable, - const bool mirror_xaxis, - const bool mirror_yaxis) = 0; - // External render. virtual int AddRenderer(const int render_id, RawVideoType video_input_format, ExternalRenderer* renderer) = 0; - // Propagating VideoRenderCallback down to the VideoRender module for new API. - // Contains default-implementation not to break code mocking this interface. - // (Ugly, but temporary.) - virtual int AddRenderCallback(int render_id, VideoRenderCallback* callback) { - return 0; - } - protected: ViERender() {} virtual ~ViERender() {} diff --git a/media/webrtc/trunk/webrtc/video_engine/include/vie_rtp_rtcp.h b/media/webrtc/trunk/webrtc/video_engine/include/vie_rtp_rtcp.h index 5cd799225e..3898d5b1fe 100644 --- a/media/webrtc/trunk/webrtc/video_engine/include/vie_rtp_rtcp.h +++ b/media/webrtc/trunk/webrtc/video_engine/include/vie_rtp_rtcp.h @@ -69,25 +69,6 @@ class WEBRTC_DLLEXPORT ViERTPObserver { virtual ~ViERTPObserver() {} }; -// This class declares an abstract interface for a user defined observer. It is -// up to the VideoEngine user to implement a derived class which implements the -// observer class. The observer is registered using RegisterRTCPObserver() and -// deregistered using DeregisterRTCPObserver(). - -class WEBRTC_DLLEXPORT ViERTCPObserver { - public: - // This method is called if a application-defined RTCP packet has been - // received. - virtual void OnApplicationDataReceived( - const int video_channel, - const unsigned char sub_type, - const unsigned int name, - const char* data, - const unsigned short data_length_in_bytes) = 0; - protected: - virtual ~ViERTCPObserver() {} -}; - struct SenderInfo; class WEBRTC_DLLEXPORT ViERTP_RTCP { @@ -137,15 +118,6 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP { virtual int SetRtxSendPayloadType(const int video_channel, const uint8_t payload_type) = 0; - // This enables sending redundant payloads when padding up the bitrate instead - // of sending dummy padding packets. This feature is off by default and will - // only have an effect if RTX is also enabled. - // TODO(holmer): Remove default implementation once this has been implemented - // in libjingle. - virtual int SetPadWithRedundantPayloads(int video_channel, bool enable) { - return 0; - } - virtual int SetRtxReceivePayloadType(const int video_channel, const uint8_t payload_type) = 0; @@ -285,6 +257,14 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP { bool enable, int id) = 0; + virtual int SetSendVideoRotationStatus(int video_channel, + bool enable, + int id) = 0; + + virtual int SetReceiveVideoRotationStatus(int video_channel, + bool enable, + int id) = 0; + // Enables/disables RTCP Receiver Reference Time Report Block extension/ // DLRR Report Block extension (RFC 3611). virtual int SetRtcpXrRrtrStatus(int video_channel, bool enable) = 0; @@ -315,7 +295,7 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP { // stream. virtual int GetReceiveChannelRtcpStatistics(const int video_channel, RtcpStatistics& basic_stats, - int& rtt_ms) const = 0; + int64_t& rtt_ms) const = 0; // This function returns statistics reported by the remote client in RTCP // report blocks. If several streams are reported, the statistics will be @@ -324,16 +304,16 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP { // and will always be set to 0. virtual int GetSendChannelRtcpStatistics(const int video_channel, RtcpStatistics& basic_stats, - int& rtt_ms) const = 0; + int64_t& rtt_ms) const = 0; // TODO(sprang): Temporary hacks to prevent libjingle build from failing, // remove when libjingle has been lifted to support webrtc issue 2589 virtual int GetReceivedRTCPStatistics(const int video_channel, - unsigned short& fraction_lost, - unsigned int& cumulative_lost, - unsigned int& extended_max, - unsigned int& jitter, - int& rtt_ms) const { + unsigned short& fraction_lost, + unsigned int& cumulative_lost, + unsigned int& extended_max, + unsigned int& jitter, + int64_t& rtt_ms) const { RtcpStatistics stats; int ret_code = GetReceiveChannelRtcpStatistics(video_channel, stats, @@ -345,11 +325,11 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP { return ret_code; } virtual int GetSentRTCPStatistics(const int video_channel, - unsigned short& fraction_lost, - unsigned int& cumulative_lost, - unsigned int& extended_max, - unsigned int& jitter, - int& rtt_ms) const { + unsigned short& fraction_lost, + unsigned int& cumulative_lost, + unsigned int& extended_max, + unsigned int& jitter, + int64_t& rtt_ms) const { RtcpStatistics stats; int ret_code = GetSendChannelRtcpStatistics(video_channel, stats, @@ -382,17 +362,17 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP { // TODO(sprang): Temporary hacks to prevent libjingle build from failing, // remove when libjingle has been lifted to support webrtc issue 2589 virtual int GetRTPStatistics(const int video_channel, - unsigned int& bytes_sent, + size_t& bytes_sent, unsigned int& packets_sent, - unsigned int& bytes_received, + size_t& bytes_received, unsigned int& packets_received) const { StreamDataCounters sent; StreamDataCounters received; int ret_code = GetRtpStatistics(video_channel, sent, received); - bytes_sent = sent.bytes; - packets_sent = sent.packets; - bytes_received = received.bytes; - packets_received = received.packets; + bytes_sent = sent.transmitted.payload_bytes; + packets_sent = sent.transmitted.packets; + bytes_received = received.transmitted.payload_bytes; + packets_received = received.transmitted.packets; return ret_code; } @@ -409,12 +389,14 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP { int video_channel, StreamDataCountersCallback* callback) = 0; - // Gets sent and received RTCP packet types. - // TODO(asapersson): Remove default implementation. - virtual int GetRtcpPacketTypeCounters( + // Gets RTCP packet type statistics from a sent/received stream. + virtual int GetSendRtcpPacketTypeCounter( int video_channel, - RtcpPacketTypeCounter* packets_sent, - RtcpPacketTypeCounter* packets_received) const { return -1; } + RtcpPacketTypeCounter* packet_counter) const = 0; + + virtual int GetReceiveRtcpPacketTypeCounter( + int video_channel, + RtcpPacketTypeCounter* packet_counter) const = 0; // Gets the sender info part of the last received RTCP Sender Report (SR) virtual int GetRemoteRTCPSenderInfo(const int video_channel, @@ -450,17 +432,10 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP { const int video_channel, unsigned int* estimated_bandwidth) const = 0; - // This function gets the receive-side bandwidth esitmator statistics. - // TODO(jiayl): remove the default impl when libjingle's FakeWebRtcVideoEngine - // is updated. - virtual int GetReceiveBandwidthEstimatorStats( - const int video_channel, - ReceiveBandwidthEstimatorStats* output) const { return -1; } - // This function gets the PacedSender queuing delay for the last sent frame. // TODO(jiayl): remove the default impl when libjingle is updated. virtual int GetPacerQueuingDelayMs( - const int video_channel, int* delay_ms) const { + const int video_channel, int64_t* delay_ms) const { return -1; } @@ -484,13 +459,6 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP { // Removes a registered instance of ViERTPObserver. virtual int DeregisterRTPObserver(const int video_channel) = 0; - // Registers an instance of a user implementation of the ViERTCPObserver. - virtual int RegisterRTCPObserver(const int video_channel, - ViERTCPObserver& observer) = 0; - - // Removes a registered instance of ViERTCPObserver. - virtual int DeregisterRTCPObserver(const int video_channel) = 0; - // Registers and instance of a user implementation of ViEFrameCountObserver virtual int RegisterSendFrameCountObserver( int video_channel, FrameCountObserver* observer) = 0; @@ -499,6 +467,12 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP { virtual int DeregisterSendFrameCountObserver( int video_channel, FrameCountObserver* observer) = 0; + // Called when RTCP packet type counters might have been changed. User has to + // filter on SSRCs to determine whether it's status sent or received. + virtual int RegisterRtcpPacketTypeCounterObserver( + int video_channel, + RtcpPacketTypeCounterObserver* observer) = 0; + protected: virtual ~ViERTP_RTCP() {} }; diff --git a/media/webrtc/trunk/webrtc/video_engine/mock/mock_vie_frame_provider_base.h b/media/webrtc/trunk/webrtc/video_engine/mock/mock_vie_frame_provider_base.h index d4e17f4d27..a59fdbfddb 100644 --- a/media/webrtc/trunk/webrtc/video_engine/mock/mock_vie_frame_provider_base.h +++ b/media/webrtc/trunk/webrtc/video_engine/mock/mock_vie_frame_provider_base.h @@ -17,11 +17,10 @@ namespace webrtc { class MockViEFrameCallback : public ViEFrameCallback { public: - MOCK_METHOD4(DeliverFrame, + MOCK_METHOD3(DeliverFrame, void(int id, I420VideoFrame* video_frame, - int num_csrcs, - const uint32_t CSRC[kRtpCsrcSize])); + const std::vector& csrcs)); MOCK_METHOD2(DelayChanged, void(int id, int frame_delay)); MOCK_METHOD3(GetPreferedFrameSettings, int(int* width, int* height, int* frame_rate)); diff --git a/media/webrtc/trunk/webrtc/video_engine/overuse_frame_detector.cc b/media/webrtc/trunk/webrtc/video_engine/overuse_frame_detector.cc index 32b0d2554e..88d5d052bc 100644 --- a/media/webrtc/trunk/webrtc/video_engine/overuse_frame_detector.cc +++ b/media/webrtc/trunk/webrtc/video_engine/overuse_frame_detector.cc @@ -17,9 +17,9 @@ #include #include +#include "webrtc/base/checks.h" #include "webrtc/base/exp_filter.h" #include "webrtc/system_wrappers/interface/clock.h" -#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/logging.h" namespace webrtc { @@ -135,7 +135,7 @@ class OveruseFrameDetector::EncodeTimeAvg { private: const float kWeightFactor; const float kInitialAvgEncodeTimeMs; - scoped_ptr filtered_encode_time_ms_; + rtc::scoped_ptr filtered_encode_time_ms_; }; // Class for calculating the processing usage on the send-side (the average @@ -208,8 +208,8 @@ class OveruseFrameDetector::SendProcessingUsage { const float kMaxSampleDiffMs; uint64_t count_; CpuOveruseOptions options_; - scoped_ptr filtered_processing_ms_; - scoped_ptr filtered_frame_diff_ms_; + rtc::scoped_ptr filtered_processing_ms_; + rtc::scoped_ptr filtered_frame_diff_ms_; }; // Class for calculating the processing time of frames. @@ -314,12 +314,14 @@ class OveruseFrameDetector::CaptureQueueDelay { const float kWeightFactor; std::list frames_; int delay_ms_; - scoped_ptr filtered_delay_ms_per_s_; + rtc::scoped_ptr filtered_delay_ms_per_s_; }; -OveruseFrameDetector::OveruseFrameDetector(Clock* clock) - : crit_(CriticalSectionWrapper::CreateCriticalSection()), - observer_(NULL), +OveruseFrameDetector::OveruseFrameDetector( + Clock* clock, + CpuOveruseMetricsObserver* metrics_observer) + : observer_(NULL), + metrics_observer_(metrics_observer), clock_(clock), next_process_time_(clock_->TimeInMilliseconds()), num_process_times_(0), @@ -337,19 +339,21 @@ OveruseFrameDetector::OveruseFrameDetector(Clock* clock) frame_queue_(new FrameQueue()), last_sample_time_ms_(0), capture_queue_delay_(new CaptureQueueDelay()) { + DCHECK(metrics_observer != nullptr); + processing_thread_.DetachFromThread(); } OveruseFrameDetector::~OveruseFrameDetector() { } void OveruseFrameDetector::SetObserver(CpuOveruseObserver* observer) { - CriticalSectionScoped cs(crit_.get()); + rtc::CritScope cs(&crit_); observer_ = observer; } void OveruseFrameDetector::SetOptions(const CpuOveruseOptions& options) { assert(options.min_frame_samples > 0); - CriticalSectionScoped cs(crit_.get()); + rtc::CritScope cs(&crit_); if (options_.Equals(options)) { return; } @@ -360,32 +364,31 @@ void OveruseFrameDetector::SetOptions(const CpuOveruseOptions& options) { } int OveruseFrameDetector::CaptureQueueDelayMsPerS() const { - CriticalSectionScoped cs(crit_.get()); + rtc::CritScope cs(&crit_); return capture_queue_delay_->delay_ms(); } int OveruseFrameDetector::LastProcessingTimeMs() const { - CriticalSectionScoped cs(crit_.get()); + rtc::CritScope cs(&crit_); return frame_queue_->last_processing_time_ms(); } int OveruseFrameDetector::FramesInQueue() const { - CriticalSectionScoped cs(crit_.get()); + rtc::CritScope cs(&crit_); return frame_queue_->NumFrames(); } -void OveruseFrameDetector::GetCpuOveruseMetrics( - CpuOveruseMetrics* metrics) const { - CriticalSectionScoped cs(crit_.get()); - metrics->capture_jitter_ms = static_cast(capture_deltas_.StdDev() + 0.5); - metrics->avg_encode_time_ms = encode_time_->Value(); - metrics->encode_rsd = 0; - metrics->encode_usage_percent = usage_->Value(); - metrics->capture_queue_delay_ms_per_s = capture_queue_delay_->Value(); +void OveruseFrameDetector::UpdateCpuOveruseMetrics() { + metrics_.capture_jitter_ms = static_cast(capture_deltas_.StdDev() + 0.5); + metrics_.avg_encode_time_ms = encode_time_->Value(); + metrics_.encode_usage_percent = usage_->Value(); + metrics_.capture_queue_delay_ms_per_s = capture_queue_delay_->Value(); + + metrics_observer_->CpuOveruseMetricsUpdated(metrics_); } -int32_t OveruseFrameDetector::TimeUntilNextProcess() { - CriticalSectionScoped cs(crit_.get()); +int64_t OveruseFrameDetector::TimeUntilNextProcess() { + DCHECK(processing_thread_.CalledOnValidThread()); return next_process_time_ - clock_->TimeInMilliseconds(); } @@ -411,12 +414,13 @@ void OveruseFrameDetector::ResetAll(int num_pixels) { capture_queue_delay_->ClearFrames(); last_capture_time_ = 0; num_process_times_ = 0; + UpdateCpuOveruseMetrics(); } void OveruseFrameDetector::FrameCaptured(int width, int height, int64_t capture_time_ms) { - CriticalSectionScoped cs(crit_.get()); + rtc::CritScope cs(&crit_); int64_t now = clock_->TimeInMilliseconds(); if (FrameSizeChanged(width * height) || FrameTimeoutDetected(now)) { @@ -434,15 +438,16 @@ void OveruseFrameDetector::FrameCaptured(int width, if (options_.enable_extended_processing_usage) { frame_queue_->Start(capture_time_ms, now); } + UpdateCpuOveruseMetrics(); } void OveruseFrameDetector::FrameProcessingStarted() { - CriticalSectionScoped cs(crit_.get()); + rtc::CritScope cs(&crit_); capture_queue_delay_->FrameProcessingStarted(clock_->TimeInMilliseconds()); } void OveruseFrameDetector::FrameEncoded(int encode_time_ms) { - CriticalSectionScoped cs(crit_.get()); + rtc::CritScope cs(&crit_); int64_t now = clock_->TimeInMilliseconds(); if (last_encode_sample_ms_ != 0) { int64_t diff_ms = now - last_encode_sample_ms_; @@ -453,10 +458,11 @@ void OveruseFrameDetector::FrameEncoded(int encode_time_ms) { if (!options_.enable_extended_processing_usage) { AddProcessingTime(encode_time_ms); } + UpdateCpuOveruseMetrics(); } void OveruseFrameDetector::FrameSent(int64_t capture_time_ms) { - CriticalSectionScoped cs(crit_.get()); + rtc::CritScope cs(&crit_); if (!options_.enable_extended_processing_usage) { return; } @@ -465,6 +471,7 @@ void OveruseFrameDetector::FrameSent(int64_t capture_time_ms) { if (delay_ms > 0) { AddProcessingTime(delay_ms); } + UpdateCpuOveruseMetrics(); } void OveruseFrameDetector::AddProcessingTime(int elapsed_ms) { @@ -477,7 +484,7 @@ void OveruseFrameDetector::AddProcessingTime(int elapsed_ms) { } int32_t OveruseFrameDetector::Process() { - CriticalSectionScoped cs(crit_.get()); + DCHECK(processing_thread_.CalledOnValidThread()); int64_t now = clock_->TimeInMilliseconds(); @@ -487,9 +494,12 @@ int32_t OveruseFrameDetector::Process() { int64_t diff_ms = now - next_process_time_ + kProcessIntervalMs; next_process_time_ = now + kProcessIntervalMs; + + rtc::CritScope cs(&crit_); ++num_process_times_; capture_queue_delay_->CalculateDelayChange(diff_ms); + UpdateCpuOveruseMetrics(); if (num_process_times_ <= options_.min_process_count) { return 0; @@ -535,6 +545,7 @@ int32_t OveruseFrameDetector::Process() { << " encode usage " << usage_->Value() << " overuse detections " << num_overuse_detections_ << " rampup delay " << rampup_delay; + return 0; } diff --git a/media/webrtc/trunk/webrtc/video_engine/overuse_frame_detector.h b/media/webrtc/trunk/webrtc/video_engine/overuse_frame_detector.h index f90a4f8250..7c04cf7752 100644 --- a/media/webrtc/trunk/webrtc/video_engine/overuse_frame_detector.h +++ b/media/webrtc/trunk/webrtc/video_engine/overuse_frame_detector.h @@ -12,16 +12,18 @@ #define WEBRTC_VIDEO_ENGINE_OVERUSE_FRAME_DETECTOR_H_ #include "webrtc/base/constructormagic.h" +#include "webrtc/base/criticalsection.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/base/exp_filter.h" +#include "webrtc/base/thread_annotations.h" +#include "webrtc/base/thread_checker.h" #include "webrtc/modules/interface/module.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/video_engine/include/vie_base.h" namespace webrtc { class Clock; class CpuOveruseObserver; -class CriticalSectionWrapper; // TODO(pbos): Move this somewhere appropriate. class Statistics { @@ -43,14 +45,15 @@ class Statistics { float sum_; uint64_t count_; CpuOveruseOptions options_; - scoped_ptr filtered_samples_; - scoped_ptr filtered_variance_; + rtc::scoped_ptr filtered_samples_; + rtc::scoped_ptr filtered_variance_; }; // Use to detect system overuse based on jitter in incoming frames. class OveruseFrameDetector : public Module { public: - explicit OveruseFrameDetector(Clock* clock); + OveruseFrameDetector(Clock* clock, + CpuOveruseMetricsObserver* metrics_observer); ~OveruseFrameDetector(); // Registers an observer receiving overuse and underuse callbacks. Set @@ -72,34 +75,14 @@ class OveruseFrameDetector : public Module { // Called for each sent frame. void FrameSent(int64_t capture_time_ms); - // Accessors. - - // Returns CpuOveruseMetrics where - // capture_jitter_ms: The estimated jitter based on incoming captured frames. - // avg_encode_time_ms: Running average of reported encode time - // (FrameEncoded()). Only used for stats. - // TODO(asapersson): Rename metric. - // encode_usage_percent: The average processing time of a frame on the - // send-side divided by the average time difference - // between incoming captured frames. - // capture_queue_delay_ms_per_s: The current time delay between an incoming - // captured frame (FrameCaptured()) until the - // frame is being processed - // (FrameProcessingStarted()). (Note: if a new - // frame is received before an old frame has - // been processed, the old frame is skipped). - // The delay is expressed in ms delay per sec. - // Only used for stats. - void GetCpuOveruseMetrics(CpuOveruseMetrics* metrics) const; - // Only public for testing. int CaptureQueueDelayMsPerS() const; int LastProcessingTimeMs() const; int FramesInQueue() const; // Implements Module. - virtual int32_t TimeUntilNextProcess() OVERRIDE; - virtual int32_t Process() OVERRIDE; + int64_t TimeUntilNextProcess() override; + int32_t Process() override; private: class EncodeTimeAvg; @@ -107,31 +90,47 @@ class OveruseFrameDetector : public Module { class CaptureQueueDelay; class FrameQueue; - void AddProcessingTime(int elapsed_ms); + void UpdateCpuOveruseMetrics() EXCLUSIVE_LOCKS_REQUIRED(crit_); - bool IsOverusing(); - bool IsUnderusing(int64_t time_now); + // TODO(asapersson): This method is only used on one thread, so it shouldn't + // need a guard. + void AddProcessingTime(int elapsed_ms) EXCLUSIVE_LOCKS_REQUIRED(crit_); - bool FrameTimeoutDetected(int64_t now) const; - bool FrameSizeChanged(int num_pixels) const; + // TODO(asapersson): This method is always called on the processing thread. + // If locking is required, consider doing that locking inside the + // implementation and reduce scope as much as possible. We should also + // see if we can avoid calling out to other methods while holding the lock. + bool IsOverusing() EXCLUSIVE_LOCKS_REQUIRED(crit_); + bool IsUnderusing(int64_t time_now) EXCLUSIVE_LOCKS_REQUIRED(crit_); - void ResetAll(int num_pixels); + bool FrameTimeoutDetected(int64_t now) const EXCLUSIVE_LOCKS_REQUIRED(crit_); + bool FrameSizeChanged(int num_pixels) const EXCLUSIVE_LOCKS_REQUIRED(crit_); - // Protecting all members. - scoped_ptr crit_; + void ResetAll(int num_pixels) EXCLUSIVE_LOCKS_REQUIRED(crit_); + + // Protecting all members except const and those that are only accessed on the + // processing thread. + // TODO(asapersson): See if we can reduce locking. As is, video frame + // processing contends with reading stats and the processing thread. + mutable rtc::CriticalSection crit_; // Observer getting overuse reports. - CpuOveruseObserver* observer_; + CpuOveruseObserver* observer_ GUARDED_BY(crit_); - CpuOveruseOptions options_; + CpuOveruseOptions options_ GUARDED_BY(crit_); - Clock* clock_; - int64_t next_process_time_; - int64_t num_process_times_; + // Stats metrics. + CpuOveruseMetricsObserver* const metrics_observer_; + CpuOveruseMetrics metrics_ GUARDED_BY(crit_); - Statistics capture_deltas_; - int64_t last_capture_time_; + Clock* const clock_; + int64_t next_process_time_; // Only accessed on the processing thread. + int64_t num_process_times_ GUARDED_BY(crit_); + Statistics capture_deltas_ GUARDED_BY(crit_); + int64_t last_capture_time_ GUARDED_BY(crit_); + + // These six members are only accessed on the processing thread. int64_t last_overuse_time_; int checks_above_threshold_; int num_overuse_detections_; @@ -141,15 +140,22 @@ class OveruseFrameDetector : public Module { int current_rampup_delay_ms_; // Number of pixels of last captured frame. - int num_pixels_; + int num_pixels_ GUARDED_BY(crit_); - int64_t last_encode_sample_ms_; - scoped_ptr encode_time_; - scoped_ptr usage_; - scoped_ptr frame_queue_; - int64_t last_sample_time_ms_; + int64_t last_encode_sample_ms_; // Only accessed by one thread. - scoped_ptr capture_queue_delay_; + // TODO(asapersson): Can these be regular members (avoid separate heap + // allocs)? + const rtc::scoped_ptr encode_time_ GUARDED_BY(crit_); + const rtc::scoped_ptr usage_ GUARDED_BY(crit_); + const rtc::scoped_ptr frame_queue_ GUARDED_BY(crit_); + + int64_t last_sample_time_ms_; // Only accessed by one thread. + + const rtc::scoped_ptr capture_queue_delay_ + GUARDED_BY(crit_); + + rtc::ThreadChecker processing_thread_; DISALLOW_COPY_AND_ASSIGN(OveruseFrameDetector); }; diff --git a/media/webrtc/trunk/webrtc/video_engine/overuse_frame_detector_unittest.cc b/media/webrtc/trunk/webrtc/video_engine/overuse_frame_detector_unittest.cc index e2361695b3..cfb7f01d4f 100644 --- a/media/webrtc/trunk/webrtc/video_engine/overuse_frame_detector_unittest.cc +++ b/media/webrtc/trunk/webrtc/video_engine/overuse_frame_detector_unittest.cc @@ -11,8 +11,8 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/system_wrappers/interface/clock.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/video_engine/include/vie_base.h" #include "webrtc/video_engine/overuse_frame_detector.h" @@ -47,12 +47,13 @@ class CpuOveruseObserverImpl : public CpuOveruseObserver { int normaluse_; }; -class OveruseFrameDetectorTest : public ::testing::Test { +class OveruseFrameDetectorTest : public ::testing::Test, + public CpuOveruseMetricsObserver { protected: virtual void SetUp() { clock_.reset(new SimulatedClock(1234)); observer_.reset(new MockCpuOveruseObserver()); - overuse_detector_.reset(new OveruseFrameDetector(clock_.get())); + overuse_detector_.reset(new OveruseFrameDetector(clock_.get(), this)); options_.low_capture_jitter_threshold_ms = 10.0f; options_.high_capture_jitter_threshold_ms = 15.0f; @@ -61,6 +62,10 @@ class OveruseFrameDetectorTest : public ::testing::Test { overuse_detector_->SetObserver(observer_.get()); } + void CpuOveruseMetricsUpdated(const CpuOveruseMetrics& metrics) override { + metrics_ = metrics; + } + int InitialJitter() { return ((options_.low_capture_jitter_threshold_ms + options_.high_capture_jitter_threshold_ms) / 2.0f) + 0.5; @@ -124,40 +129,37 @@ class OveruseFrameDetectorTest : public ::testing::Test { overuse_detector_->Process(); } - int CaptureJitterMs() { - CpuOveruseMetrics metrics; - overuse_detector_->GetCpuOveruseMetrics(&metrics); - return metrics.capture_jitter_ms; - } + int CaptureJitterMs() { return metrics_.capture_jitter_ms; } - int AvgEncodeTimeMs() { - CpuOveruseMetrics metrics; - overuse_detector_->GetCpuOveruseMetrics(&metrics); - return metrics.avg_encode_time_ms; - } + int AvgEncodeTimeMs() { return metrics_.avg_encode_time_ms; } - int UsagePercent() { - CpuOveruseMetrics metrics; - overuse_detector_->GetCpuOveruseMetrics(&metrics); - return metrics.encode_usage_percent; - } + int UsagePercent() { return metrics_.encode_usage_percent; } CpuOveruseOptions options_; - scoped_ptr clock_; - scoped_ptr observer_; - scoped_ptr overuse_detector_; + rtc::scoped_ptr clock_; + rtc::scoped_ptr observer_; + rtc::scoped_ptr overuse_detector_; + CpuOveruseMetrics metrics_; }; // enable_capture_jitter_method = true; // CaptureJitterMs() > high_capture_jitter_threshold_ms => overuse. // CaptureJitterMs() < low_capture_jitter_threshold_ms => underuse. TEST_F(OveruseFrameDetectorTest, TriggerOveruse) { + options_.enable_capture_jitter_method = true; + options_.enable_encode_usage_method = false; + options_.enable_extended_processing_usage = false; + overuse_detector_->SetOptions(options_); // capture_jitter > high => overuse EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); TriggerOveruse(options_.high_threshold_consecutive_count); } TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) { + options_.enable_capture_jitter_method = true; + options_.enable_encode_usage_method = false; + options_.enable_extended_processing_usage = false; + overuse_detector_->SetOptions(options_); // capture_jitter > high => overuse EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); TriggerOveruse(options_.high_threshold_consecutive_count); @@ -167,6 +169,10 @@ TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) { } TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) { + options_.enable_capture_jitter_method = true; + options_.enable_encode_usage_method = false; + options_.enable_extended_processing_usage = false; + overuse_detector_->SetOptions(options_); overuse_detector_->SetObserver(NULL); EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); TriggerOveruse(options_.high_threshold_consecutive_count); @@ -177,6 +183,7 @@ TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) { TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithMethodDisabled) { options_.enable_capture_jitter_method = false; options_.enable_encode_usage_method = false; + options_.enable_extended_processing_usage = false; overuse_detector_->SetOptions(options_); EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); TriggerOveruse(options_.high_threshold_consecutive_count); @@ -185,6 +192,10 @@ TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithMethodDisabled) { } TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) { + options_.enable_capture_jitter_method = true; + options_.enable_encode_usage_method = false; + options_.enable_extended_processing_usage = false; + overuse_detector_->SetOptions(options_); EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(2); TriggerOveruse(options_.high_threshold_consecutive_count); TriggerOveruse(options_.high_threshold_consecutive_count); @@ -193,6 +204,9 @@ TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) { } TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) { + options_.enable_capture_jitter_method = true; + options_.enable_encode_usage_method = false; + options_.enable_extended_processing_usage = false; CpuOveruseObserverImpl overuse_observer_; overuse_detector_->SetObserver(&overuse_observer_); options_.min_process_count = 1; @@ -206,6 +220,10 @@ TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) { } TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) { + options_.enable_capture_jitter_method = true; + options_.enable_encode_usage_method = false; + options_.enable_extended_processing_usage = false; + overuse_detector_->SetOptions(options_); EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(64); for(size_t i = 0; i < 64; ++i) { @@ -214,6 +232,9 @@ TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) { } TEST_F(OveruseFrameDetectorTest, ConsecutiveCountTriggersOveruse) { + options_.enable_capture_jitter_method = true; + options_.enable_encode_usage_method = false; + options_.enable_extended_processing_usage = false; EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); options_.high_threshold_consecutive_count = 2; overuse_detector_->SetOptions(options_); @@ -221,22 +242,15 @@ TEST_F(OveruseFrameDetectorTest, ConsecutiveCountTriggersOveruse) { } TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) { + options_.enable_capture_jitter_method = true; + options_.enable_encode_usage_method = false; + options_.enable_extended_processing_usage = false; EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); options_.high_threshold_consecutive_count = 2; overuse_detector_->SetOptions(options_); TriggerOveruse(1); } -TEST_F(OveruseFrameDetectorTest, GetCpuOveruseMetrics) { - CpuOveruseMetrics metrics; - overuse_detector_->GetCpuOveruseMetrics(&metrics); - EXPECT_GT(metrics.capture_jitter_ms, 0); - EXPECT_GT(metrics.avg_encode_time_ms, 0); - EXPECT_GT(metrics.encode_usage_percent, 0); - EXPECT_GE(metrics.capture_queue_delay_ms_per_s, 0); - EXPECT_GE(metrics.encode_rsd, 0); -} - TEST_F(OveruseFrameDetectorTest, CaptureJitter) { EXPECT_EQ(InitialJitter(), CaptureJitterMs()); InsertFramesWithInterval(1000, kFrameInterval33ms, kWidth, kHeight); diff --git a/media/webrtc/trunk/webrtc/video_engine/payload_router.cc b/media/webrtc/trunk/webrtc/video_engine/payload_router.cc new file mode 100644 index 0000000000..958cdd869c --- /dev/null +++ b/media/webrtc/trunk/webrtc/video_engine/payload_router.cc @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/video_engine/payload_router.h" + +#include "webrtc/base/checks.h" +#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" +#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" + +namespace webrtc { + +PayloadRouter::PayloadRouter() + : crit_(CriticalSectionWrapper::CreateCriticalSection()), + active_(false) {} + +PayloadRouter::~PayloadRouter() {} + +size_t PayloadRouter::DefaultMaxPayloadLength() { + const size_t kIpUdpSrtpLength = 44; + return IP_PACKET_SIZE - kIpUdpSrtpLength; +} + +void PayloadRouter::SetSendingRtpModules( + const std::list& rtp_modules) { + CriticalSectionScoped cs(crit_.get()); + rtp_modules_.clear(); + rtp_modules_.reserve(rtp_modules.size()); + for (auto* rtp_module : rtp_modules) { + rtp_modules_.push_back(rtp_module); + } +} + +void PayloadRouter::set_active(bool active) { + CriticalSectionScoped cs(crit_.get()); + active_ = active; +} + +bool PayloadRouter::active() { + CriticalSectionScoped cs(crit_.get()); + return active_ && !rtp_modules_.empty(); +} + +bool PayloadRouter::RoutePayload(FrameType frame_type, + int8_t payload_type, + uint32_t time_stamp, + int64_t capture_time_ms, + const uint8_t* payload_data, + size_t payload_length, + const RTPFragmentationHeader* fragmentation, + const RTPVideoHeader* rtp_video_hdr) { + CriticalSectionScoped cs(crit_.get()); + if (!active_ || rtp_modules_.empty()) + return false; + + // The simulcast index might actually be larger than the number of modules in + // case the encoder was processing a frame during a codec reconfig. + if (rtp_video_hdr != NULL && + rtp_video_hdr->simulcastIdx >= rtp_modules_.size()) + return false; + + int stream_idx = 0; + if (rtp_video_hdr != NULL) + stream_idx = rtp_video_hdr->simulcastIdx; + return rtp_modules_[stream_idx]->SendOutgoingData( + frame_type, payload_type, time_stamp, capture_time_ms, payload_data, + payload_length, fragmentation, rtp_video_hdr) == 0 ? true : false; +} + +void PayloadRouter::SetTargetSendBitrates( + const std::vector& stream_bitrates) { + CriticalSectionScoped cs(crit_.get()); + if (stream_bitrates.size() < rtp_modules_.size()) { + // There can be a size mis-match during codec reconfiguration. + return; + } + int idx = 0; + for (auto* rtp_module : rtp_modules_) { + rtp_module->SetTargetSendBitrate(stream_bitrates[idx++]); + } +} + +size_t PayloadRouter::MaxPayloadLength() const { + size_t min_payload_length = DefaultMaxPayloadLength(); + CriticalSectionScoped cs(crit_.get()); + for (auto* rtp_module : rtp_modules_) { + size_t module_payload_length = rtp_module->MaxDataPayloadLength(); + if (module_payload_length < min_payload_length) + min_payload_length = module_payload_length; + } + return min_payload_length; +} + +} // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/payload_router.h b/media/webrtc/trunk/webrtc/video_engine/payload_router.h new file mode 100644 index 0000000000..b96defd5e3 --- /dev/null +++ b/media/webrtc/trunk/webrtc/video_engine/payload_router.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_VIDEO_ENGINE_PAYLOAD_ROUTER_H_ +#define WEBRTC_VIDEO_ENGINE_PAYLOAD_ROUTER_H_ + +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/scoped_ptr.h" +#include "webrtc/base/thread_annotations.h" +#include "webrtc/common_types.h" +#include "webrtc/system_wrappers/interface/atomic32.h" + +namespace webrtc { + +class CriticalSectionWrapper; +class RTPFragmentationHeader; +class RtpRtcp; +struct RTPVideoHeader; + +// PayloadRouter routes outgoing data to the correct sending RTP module, based +// on the simulcast layer in RTPVideoHeader. +class PayloadRouter { + public: + PayloadRouter(); + ~PayloadRouter(); + + static size_t DefaultMaxPayloadLength(); + + // Rtp modules are assumed to be sorted in simulcast index order. + void SetSendingRtpModules(const std::list& rtp_modules); + + // PayloadRouter will only route packets if being active, all packets will be + // dropped otherwise. + void set_active(bool active); + bool active(); + + // Input parameters according to the signature of RtpRtcp::SendOutgoingData. + // Returns true if the packet was routed / sent, false otherwise. + bool RoutePayload(FrameType frame_type, + int8_t payload_type, + uint32_t time_stamp, + int64_t capture_time_ms, + const uint8_t* payload_data, + size_t payload_size, + const RTPFragmentationHeader* fragmentation, + const RTPVideoHeader* rtp_video_hdr); + + // Configures current target bitrate per module. 'stream_bitrates' is assumed + // to be in the same order as 'SetSendingRtpModules'. + void SetTargetSendBitrates(const std::vector& stream_bitrates); + + // Returns the maximum allowed data payload length, given the configured MTU + // and RTP headers. + size_t MaxPayloadLength() const; + + void AddRef() { ++ref_count_; } + void Release() { if (--ref_count_ == 0) { delete this; } } + + private: + // TODO(mflodman): When the new video API has launched, remove crit_ and + // assume rtp_modules_ will never change during a call. + rtc::scoped_ptr crit_; + + // Active sending RTP modules, in layer order. + std::vector rtp_modules_ GUARDED_BY(crit_.get()); + bool active_ GUARDED_BY(crit_.get()); + + Atomic32 ref_count_; + + DISALLOW_COPY_AND_ASSIGN(PayloadRouter); +}; + +} // namespace webrtc + +#endif // WEBRTC_VIDEO_ENGINE_PAYLOAD_ROUTER_H_ diff --git a/media/webrtc/trunk/webrtc/video_engine/payload_router_unittest.cc b/media/webrtc/trunk/webrtc/video_engine/payload_router_unittest.cc new file mode 100644 index 0000000000..de391576d8 --- /dev/null +++ b/media/webrtc/trunk/webrtc/video_engine/payload_router_unittest.cc @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + + +#include + +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/scoped_ptr.h" +#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" +#include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h" +#include "webrtc/video_engine/payload_router.h" + +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::NiceMock; +using ::testing::Return; + +namespace webrtc { + +class PayloadRouterTest : public ::testing::Test { + protected: + virtual void SetUp() { + payload_router_.reset(new PayloadRouter()); + } + rtc::scoped_ptr payload_router_; +}; + +TEST_F(PayloadRouterTest, SendOnOneModule) { + MockRtpRtcp rtp; + std::list modules(1, &rtp); + + payload_router_->SetSendingRtpModules(modules); + + uint8_t payload = 'a'; + FrameType frame_type = kVideoFrameKey; + int8_t payload_type = 96; + + EXPECT_CALL(rtp, SendOutgoingData(frame_type, payload_type, 0, 0, _, 1, NULL, + NULL)) + .Times(0); + EXPECT_FALSE(payload_router_->RoutePayload(frame_type, payload_type, 0, 0, + &payload, 1, NULL, NULL)); + + payload_router_->set_active(true); + EXPECT_CALL(rtp, SendOutgoingData(frame_type, payload_type, 0, 0, _, 1, NULL, + NULL)) + .Times(1); + EXPECT_TRUE(payload_router_->RoutePayload(frame_type, payload_type, 0, 0, + &payload, 1, NULL, NULL)); + + payload_router_->set_active(false); + EXPECT_CALL(rtp, SendOutgoingData(frame_type, payload_type, 0, 0, _, 1, NULL, + NULL)) + .Times(0); + EXPECT_FALSE(payload_router_->RoutePayload(frame_type, payload_type, 0, 0, + &payload, 1, NULL, NULL)); + + payload_router_->set_active(true); + EXPECT_CALL(rtp, SendOutgoingData(frame_type, payload_type, 0, 0, _, 1, NULL, + NULL)) + .Times(1); + EXPECT_TRUE(payload_router_->RoutePayload(frame_type, payload_type, 0, 0, + &payload, 1, NULL, NULL)); + + modules.clear(); + payload_router_->SetSendingRtpModules(modules); + EXPECT_CALL(rtp, SendOutgoingData(frame_type, payload_type, 0, 0, _, 1, NULL, + NULL)) + .Times(0); + EXPECT_FALSE(payload_router_->RoutePayload(frame_type, payload_type, 0, 0, + &payload, 1, NULL, NULL)); +} + +TEST_F(PayloadRouterTest, SendSimulcast) { + MockRtpRtcp rtp_1; + MockRtpRtcp rtp_2; + std::list modules; + modules.push_back(&rtp_1); + modules.push_back(&rtp_2); + + payload_router_->SetSendingRtpModules(modules); + + uint8_t payload_1 = 'a'; + FrameType frame_type_1 = kVideoFrameKey; + int8_t payload_type_1 = 96; + RTPVideoHeader rtp_hdr_1; + rtp_hdr_1.simulcastIdx = 0; + + payload_router_->set_active(true); + EXPECT_CALL(rtp_1, SendOutgoingData(frame_type_1, payload_type_1, 0, 0, _, 1, + NULL, &rtp_hdr_1)) + .Times(1); + EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _)) + .Times(0); + EXPECT_TRUE(payload_router_->RoutePayload(frame_type_1, payload_type_1, 0, 0, + &payload_1, 1, NULL, &rtp_hdr_1)); + + uint8_t payload_2 = 'b'; + FrameType frame_type_2 = kVideoFrameDelta; + int8_t payload_type_2 = 97; + RTPVideoHeader rtp_hdr_2; + rtp_hdr_2.simulcastIdx = 1; + EXPECT_CALL(rtp_2, SendOutgoingData(frame_type_2, payload_type_2, 0, 0, _, 1, + NULL, &rtp_hdr_2)) + .Times(1); + EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _)) + .Times(0); + EXPECT_TRUE(payload_router_->RoutePayload(frame_type_2, payload_type_2, 0, 0, + &payload_2, 1, NULL, &rtp_hdr_2)); + + // Inactive. + payload_router_->set_active(false); + EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _)) + .Times(0); + EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _)) + .Times(0); + EXPECT_FALSE(payload_router_->RoutePayload(frame_type_1, payload_type_1, 0, 0, + &payload_1, 1, NULL, &rtp_hdr_1)); + EXPECT_FALSE(payload_router_->RoutePayload(frame_type_2, payload_type_2, 0, 0, + &payload_2, 1, NULL, &rtp_hdr_2)); + + // Invalid simulcast index. + payload_router_->set_active(true); + EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _)) + .Times(0); + EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _)) + .Times(0); + rtp_hdr_1.simulcastIdx = 2; + EXPECT_FALSE(payload_router_->RoutePayload(frame_type_1, payload_type_1, 0, 0, + &payload_1, 1, NULL, &rtp_hdr_1)); +} + +TEST_F(PayloadRouterTest, MaxPayloadLength) { + // Without any limitations from the modules, verify we get the max payload + // length for IP/UDP/SRTP with a MTU of 150 bytes. + const size_t kDefaultMaxLength = 1500 - 20 - 8 - 12 - 4; + EXPECT_EQ(kDefaultMaxLength, payload_router_->DefaultMaxPayloadLength()); + EXPECT_EQ(kDefaultMaxLength, payload_router_->MaxPayloadLength()); + + MockRtpRtcp rtp_1; + MockRtpRtcp rtp_2; + std::list modules; + modules.push_back(&rtp_1); + modules.push_back(&rtp_2); + payload_router_->SetSendingRtpModules(modules); + + // Modules return a higher length than the default value. + EXPECT_CALL(rtp_1, MaxDataPayloadLength()) + .Times(1) + .WillOnce(Return(kDefaultMaxLength + 10)); + EXPECT_CALL(rtp_2, MaxDataPayloadLength()) + .Times(1) + .WillOnce(Return(kDefaultMaxLength + 10)); + EXPECT_EQ(kDefaultMaxLength, payload_router_->MaxPayloadLength()); + + // The modules return a value lower than default. + const size_t kTestMinPayloadLength = 1001; + EXPECT_CALL(rtp_1, MaxDataPayloadLength()) + .Times(1) + .WillOnce(Return(kTestMinPayloadLength + 10)); + EXPECT_CALL(rtp_2, MaxDataPayloadLength()) + .Times(1) + .WillOnce(Return(kTestMinPayloadLength)); + EXPECT_EQ(kTestMinPayloadLength, payload_router_->MaxPayloadLength()); +} + +TEST_F(PayloadRouterTest, SetTargetSendBitrates) { + MockRtpRtcp rtp_1; + MockRtpRtcp rtp_2; + std::list modules; + modules.push_back(&rtp_1); + modules.push_back(&rtp_2); + payload_router_->SetSendingRtpModules(modules); + + const uint32_t bitrate_1 = 10000; + const uint32_t bitrate_2 = 76543; + std::vector bitrates (2, bitrate_1); + bitrates[1] = bitrate_2; + EXPECT_CALL(rtp_1, SetTargetSendBitrate(bitrate_1)) + .Times(1); + EXPECT_CALL(rtp_2, SetTargetSendBitrate(bitrate_2)) + .Times(1); + payload_router_->SetTargetSendBitrates(bitrates); + + bitrates.resize(1); + EXPECT_CALL(rtp_1, SetTargetSendBitrate(bitrate_1)) + .Times(0); + EXPECT_CALL(rtp_2, SetTargetSendBitrate(bitrate_2)) + .Times(0); + payload_router_->SetTargetSendBitrates(bitrates); + + bitrates.resize(3); + bitrates[1] = bitrate_2; + bitrates[2] = bitrate_1 + bitrate_2; + EXPECT_CALL(rtp_1, SetTargetSendBitrate(bitrate_1)) + .Times(1); + EXPECT_CALL(rtp_2, SetTargetSendBitrate(bitrate_2)) + .Times(1); + payload_router_->SetTargetSendBitrates(bitrates); +} +} // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/report_block_stats.cc b/media/webrtc/trunk/webrtc/video_engine/report_block_stats.cc new file mode 100644 index 0000000000..ea18e830e3 --- /dev/null +++ b/media/webrtc/trunk/webrtc/video_engine/report_block_stats.cc @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/video_engine/report_block_stats.h" + +namespace webrtc { + +namespace { +int FractionLost(uint32_t num_lost_sequence_numbers, + uint32_t num_sequence_numbers) { + if (num_sequence_numbers == 0) { + return 0; + } + return ((num_lost_sequence_numbers * 255) + (num_sequence_numbers / 2)) / + num_sequence_numbers; +} +} // namespace + + +// Helper class for rtcp statistics. +ReportBlockStats::ReportBlockStats() + : num_sequence_numbers_(0), + num_lost_sequence_numbers_(0) { +} + +void ReportBlockStats::Store(const RtcpStatistics& rtcp_stats, + uint32_t remote_ssrc, + uint32_t source_ssrc) { + RTCPReportBlock block; + block.cumulativeLost = rtcp_stats.cumulative_lost; + block.fractionLost = rtcp_stats.fraction_lost; + block.extendedHighSeqNum = rtcp_stats.extended_max_sequence_number; + block.jitter = rtcp_stats.jitter; + block.remoteSSRC = remote_ssrc; + block.sourceSSRC = source_ssrc; + uint32_t num_sequence_numbers = 0; + uint32_t num_lost_sequence_numbers = 0; + StoreAndAddPacketIncrement( + block, &num_sequence_numbers, &num_lost_sequence_numbers); +} + +RTCPReportBlock ReportBlockStats::AggregateAndStore( + const ReportBlockVector& report_blocks) { + RTCPReportBlock aggregate; + if (report_blocks.empty()) { + return aggregate; + } + uint32_t num_sequence_numbers = 0; + uint32_t num_lost_sequence_numbers = 0; + ReportBlockVector::const_iterator report_block = report_blocks.begin(); + for (; report_block != report_blocks.end(); ++report_block) { + aggregate.cumulativeLost += report_block->cumulativeLost; + aggregate.jitter += report_block->jitter; + StoreAndAddPacketIncrement(*report_block, + &num_sequence_numbers, + &num_lost_sequence_numbers); + } + + if (report_blocks.size() == 1) { + // No aggregation needed. + return report_blocks[0]; + } + // Fraction lost since previous report block. + aggregate.fractionLost = + FractionLost(num_lost_sequence_numbers, num_sequence_numbers); + aggregate.jitter = + (aggregate.jitter + report_blocks.size() / 2) / report_blocks.size(); + return aggregate; +} + +void ReportBlockStats::StoreAndAddPacketIncrement( + const RTCPReportBlock& report_block, + uint32_t* num_sequence_numbers, + uint32_t* num_lost_sequence_numbers) { + // Get diff with previous report block. + ReportBlockMap::iterator prev_report_block = prev_report_blocks_.find( + report_block.sourceSSRC); + if (prev_report_block != prev_report_blocks_.end()) { + int seq_num_diff = report_block.extendedHighSeqNum - + prev_report_block->second.extendedHighSeqNum; + int cum_loss_diff = report_block.cumulativeLost - + prev_report_block->second.cumulativeLost; + if (seq_num_diff >= 0 && cum_loss_diff >= 0) { + *num_sequence_numbers += seq_num_diff; + *num_lost_sequence_numbers += cum_loss_diff; + // Update total number of packets/lost packets. + num_sequence_numbers_ += seq_num_diff; + num_lost_sequence_numbers_ += cum_loss_diff; + } + } + // Store current report block. + prev_report_blocks_[report_block.sourceSSRC] = report_block; +} + +int ReportBlockStats::FractionLostInPercent() const { + if (num_sequence_numbers_ == 0) { + return -1; + } + return FractionLost( + num_lost_sequence_numbers_, num_sequence_numbers_) * 100 / 255; +} + +} // namespace webrtc + diff --git a/media/webrtc/trunk/webrtc/video_engine/report_block_stats.h b/media/webrtc/trunk/webrtc/video_engine/report_block_stats.h new file mode 100644 index 0000000000..dadcc9d410 --- /dev/null +++ b/media/webrtc/trunk/webrtc/video_engine/report_block_stats.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_VIDEO_ENGINE_REPORT_BLOCK_STATS_H_ +#define WEBRTC_VIDEO_ENGINE_REPORT_BLOCK_STATS_H_ + +#include +#include + +#include "webrtc/common_types.h" +#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" + +namespace webrtc { + +// Helper class for rtcp statistics. +class ReportBlockStats { + public: + typedef std::map ReportBlockMap; + typedef std::vector ReportBlockVector; + ReportBlockStats(); + ~ReportBlockStats() {} + + // Updates stats and stores report blocks. + // Returns an aggregate of the |report_blocks|. + RTCPReportBlock AggregateAndStore(const ReportBlockVector& report_blocks); + + // Updates stats and stores report block. + void Store(const RtcpStatistics& rtcp_stats, + uint32_t remote_ssrc, + uint32_t source_ssrc); + + // Returns the total fraction of lost packets (or -1 if less than two report + // blocks have been stored). + int FractionLostInPercent() const; + + private: + // Updates the total number of packets/lost packets. + // Stores the report block. + // Returns the number of packets/lost packets since previous report block. + void StoreAndAddPacketIncrement(const RTCPReportBlock& report_block, + uint32_t* num_sequence_numbers, + uint32_t* num_lost_sequence_numbers); + + // The total number of packets/lost packets. + uint32_t num_sequence_numbers_; + uint32_t num_lost_sequence_numbers_; + + // Map holding the last stored report block (mapped by the source SSRC). + ReportBlockMap prev_report_blocks_; +}; + +} // namespace webrtc + +#endif // WEBRTC_VIDEO_ENGINE_REPORT_BLOCK_STATS_H_ + diff --git a/media/webrtc/trunk/webrtc/video_engine/report_block_stats_unittest.cc b/media/webrtc/trunk/webrtc/video_engine/report_block_stats_unittest.cc new file mode 100644 index 0000000000..13b7af5ba2 --- /dev/null +++ b/media/webrtc/trunk/webrtc/video_engine/report_block_stats_unittest.cc @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "testing/gtest/include/gtest/gtest.h" + +#include "webrtc/video_engine/report_block_stats.h" + +namespace webrtc { + +class ReportBlockStatsTest : public ::testing::Test { + protected: + ReportBlockStatsTest() : kSsrc1(0x12345), kSsrc2(0x23456) {} + + void SetUp() override { + // kSsrc1: block 1-3. + block1_1_.cumulativeLost = 10; + block1_1_.fractionLost = 123; + block1_1_.extendedHighSeqNum = 24000; + block1_1_.jitter = 777; + block1_1_.sourceSSRC = kSsrc1; + block1_2_.cumulativeLost = 15; + block1_2_.fractionLost = 0; + block1_2_.extendedHighSeqNum = 24100; + block1_2_.jitter = 222; + block1_2_.sourceSSRC = kSsrc1; + block1_3_.cumulativeLost = 50; + block1_3_.fractionLost = 0; + block1_3_.extendedHighSeqNum = 24200; + block1_3_.jitter = 333; + block1_3_.sourceSSRC = kSsrc1; + // kSsrc2: block 1,2. + block2_1_.cumulativeLost = 111; + block2_1_.fractionLost = 222; + block2_1_.extendedHighSeqNum = 8500; + block2_1_.jitter = 555; + block2_1_.sourceSSRC = kSsrc2; + block2_2_.cumulativeLost = 136; + block2_2_.fractionLost = 0; + block2_2_.extendedHighSeqNum = 8800; + block2_2_.jitter = 888; + block2_2_.sourceSSRC = kSsrc2; + + ssrc1block1_.push_back(block1_1_); + ssrc1block2_.push_back(block1_2_); + ssrc12block1_.push_back(block1_1_); + ssrc12block1_.push_back(block2_1_); + ssrc12block2_.push_back(block1_2_); + ssrc12block2_.push_back(block2_2_); + } + + RtcpStatistics RtcpReportBlockToRtcpStatistics( + const RTCPReportBlock& stats) { + RtcpStatistics block; + block.cumulative_lost = stats.cumulativeLost; + block.fraction_lost = stats.fractionLost; + block.extended_max_sequence_number = stats.extendedHighSeqNum; + block.jitter = stats.jitter; + return block; + } + + const uint32_t kSsrc1; + const uint32_t kSsrc2; + RTCPReportBlock block1_1_; + RTCPReportBlock block1_2_; + RTCPReportBlock block1_3_; + RTCPReportBlock block2_1_; + RTCPReportBlock block2_2_; + std::vector ssrc1block1_; + std::vector ssrc1block2_; + std::vector ssrc12block1_; + std::vector ssrc12block2_; +}; + +TEST_F(ReportBlockStatsTest, AggregateAndStore_NoSsrc) { + ReportBlockStats stats; + std::vector empty; + RTCPReportBlock aggregated = stats.AggregateAndStore(empty); + EXPECT_EQ(0U, aggregated.fractionLost); + EXPECT_EQ(0U, aggregated.cumulativeLost); + EXPECT_EQ(0U, aggregated.jitter); + EXPECT_EQ(0U, aggregated.extendedHighSeqNum); +} + +TEST_F(ReportBlockStatsTest, AggregateAndStore_OneSsrc) { + ReportBlockStats stats; + RTCPReportBlock aggregated = stats.AggregateAndStore(ssrc1block1_); + // One ssrc, no aggregation done. + EXPECT_EQ(123U, aggregated.fractionLost); + EXPECT_EQ(10U, aggregated.cumulativeLost); + EXPECT_EQ(777U, aggregated.jitter); + EXPECT_EQ(24000U, aggregated.extendedHighSeqNum); + + aggregated = stats.AggregateAndStore(ssrc1block2_); + EXPECT_EQ(0U, aggregated.fractionLost); + EXPECT_EQ(15U, aggregated.cumulativeLost); + EXPECT_EQ(222U, aggregated.jitter); + EXPECT_EQ(24100U, aggregated.extendedHighSeqNum); + + // fl: 100 * (15-10) / (24100-24000) = 5% + EXPECT_EQ(5, stats.FractionLostInPercent()); +} + +TEST_F(ReportBlockStatsTest, AggregateAndStore_TwoSsrcs) { + ReportBlockStats stats; + RTCPReportBlock aggregated = stats.AggregateAndStore(ssrc12block1_); + EXPECT_EQ(0U, aggregated.fractionLost); + EXPECT_EQ(10U + 111U, aggregated.cumulativeLost); + EXPECT_EQ((777U + 555U) / 2, aggregated.jitter); + EXPECT_EQ(0U, aggregated.extendedHighSeqNum); + + aggregated = stats.AggregateAndStore(ssrc12block2_); + // fl: 255 * ((15-10) + (136-111)) / ((24100-24000) + (8800-8500)) = 19 + EXPECT_EQ(19U, aggregated.fractionLost); + EXPECT_EQ(15U + 136U, aggregated.cumulativeLost); + EXPECT_EQ((222U + 888U) / 2, aggregated.jitter); + EXPECT_EQ(0U, aggregated.extendedHighSeqNum); + + // fl: 100 * ((15-10) + (136-111)) / ((24100-24000) + (8800-8500)) = 7% + EXPECT_EQ(7, stats.FractionLostInPercent()); +} + +TEST_F(ReportBlockStatsTest, StoreAndGetFractionLost) { + const uint32_t kRemoteSsrc = 1; + ReportBlockStats stats; + EXPECT_EQ(-1, stats.FractionLostInPercent()); + + // First block. + stats.Store(RtcpReportBlockToRtcpStatistics(block1_1_), kRemoteSsrc, kSsrc1); + EXPECT_EQ(-1, stats.FractionLostInPercent()); + // fl: 100 * (15-10) / (24100-24000) = 5% + stats.Store(RtcpReportBlockToRtcpStatistics(block1_2_), kRemoteSsrc, kSsrc1); + EXPECT_EQ(5, stats.FractionLostInPercent()); + // fl: 100 * (50-10) / (24200-24000) = 20% + stats.Store(RtcpReportBlockToRtcpStatistics(block1_3_), kRemoteSsrc, kSsrc1); + EXPECT_EQ(20, stats.FractionLostInPercent()); +} + +} // namespace webrtc + diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/automated/vie_extended_integration_test.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/automated/vie_extended_integration_test.cc index e43fc751b0..4508d8e791 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/automated/vie_extended_integration_test.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/automated/vie_extended_integration_test.cc @@ -52,9 +52,4 @@ TEST_F(DISABLED_ON_MAC(ViEExtendedIntegrationTest), tests_->ViERenderExtendedTest(); } -TEST_F(DISABLED_ON_MAC(ViEExtendedIntegrationTest), - DISABLED_RunsRtpRtcpTestWithoutErrors) { - tests_->ViERtpRtcpExtendedTest(); -} - } // namespace diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/automated/vie_network_test.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/automated/vie_network_test.cc index 206d055524..4fd2422a9c 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/automated/vie_network_test.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/automated/vie_network_test.cc @@ -25,13 +25,13 @@ class RtcpCollectorTransport : public webrtc::Transport { RtcpCollectorTransport() : packets_() {} virtual ~RtcpCollectorTransport() {} - virtual int SendPacket(int /*channel*/, - const void* /*data*/, - int /*len*/) OVERRIDE { + int SendPacket(int /*channel*/, + const void* /*data*/, + size_t /*len*/) override { EXPECT_TRUE(false); return 0; } - virtual int SendRTCPPacket(int channel, const void* data, int len) OVERRIDE { + int SendRTCPPacket(int channel, const void* data, size_t len) override { const uint8_t* buf = static_cast(data); webrtc::RtpUtility::RtpHeaderParser parser(buf, len); if (parser.RTCP()) { @@ -39,7 +39,7 @@ class RtcpCollectorTransport : public webrtc::Transport { p.channel = channel; p.length = len; if (parser.ParseRtcp(&p.header)) { - if (p.header.payloadType == 201) { + if (p.header.payloadType == 201 && len >= 20) { buf += 20; len -= 20; } else { @@ -68,20 +68,20 @@ class RtcpCollectorTransport : public webrtc::Transport { struct Packet { Packet() : channel(-1), length(0), header(), remb_bitrate(0), remb_ssrc() {} int channel; - int length; + size_t length; webrtc::RTPHeader header; double remb_bitrate; std::vector remb_ssrc; }; - bool TryParseREMB(const uint8_t* buf, int length, Packet* p) { + bool TryParseREMB(const uint8_t* buf, size_t length, Packet* p) { if (length < 8) { return false; } if (buf[0] != 'R' || buf[1] != 'E' || buf[2] != 'M' || buf[3] != 'B') { return false; } - uint8_t ssrcs = buf[4]; + size_t ssrcs = buf[4]; uint8_t exp = buf[5] >> 2; uint32_t mantissa = ((buf[5] & 0x03) << 16) + (buf[6] << 8) + buf[7]; double bitrate = mantissa * static_cast(1 << exp); @@ -91,7 +91,7 @@ class RtcpCollectorTransport : public webrtc::Transport { return false; } buf += 8; - for (uint8_t i = 0; i < ssrcs; ++i) { + for (size_t i = 0; i < ssrcs; ++i) { uint32_t ssrc = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3]; p->remb_ssrc.push_back(ssrc); buf += 4; @@ -107,13 +107,13 @@ class ViENetworkTest : public testing::Test { ViENetworkTest() : vie_("ViENetworkTest"), channel_(-1), transport() {} virtual ~ViENetworkTest() {} - virtual void SetUp() OVERRIDE { + void SetUp() override { EXPECT_EQ(0, vie_.base->CreateChannel(channel_)); EXPECT_EQ(0, vie_.rtp_rtcp->SetRembStatus(channel_, false, true)); EXPECT_EQ(0, vie_.network->RegisterSendTransport(channel_, transport)); } - virtual void TearDown() OVERRIDE { + void TearDown() override { EXPECT_EQ(0, vie_.network->DeregisterSendTransport(channel_)); } diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/interface/vie_autotest.h b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/interface/vie_autotest.h index 7a83637860..0ee26a5732 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/interface/vie_autotest.h +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/interface/vie_autotest.h @@ -100,7 +100,6 @@ public: // vie_autotest_rtp_rtcp.cc void ViERtpRtcpStandardTest(); - void ViERtpRtcpExtendedTest(); void ViERtpRtcpAPITest(); private: @@ -113,6 +112,13 @@ private: TbVideoChannel* video_channel, TbCaptureDevice* capture_device); + // Stops rendering into the two windows as was set up by a call to + // RenderCaptureDeviceAndOutputStream. + void StopRenderCaptureDeviceAndOutputStream( + TbInterfaces* video_engine, + TbVideoChannel* video_channel, + TbCaptureDevice* capture_device); + void* _window1; void* _window2; diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/interface/vie_autotest_windows.h b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/interface/vie_autotest_windows.h index 5a735e53b4..fffd9484fe 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/interface/vie_autotest_windows.h +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/interface/vie_autotest_windows.h @@ -12,6 +12,7 @@ #define WEBRTC_VIDEO_ENGINE_MAIN_TEST_AUTOTEST_INTERFACE_VIE_AUTOTEST_WINDOWS_H_ #include "webrtc/engine_configurations.h" +#include "webrtc/system_wrappers/interface/thread_wrapper.h" #include "webrtc/video_engine/test/auto_test/interface/vie_autotest_window_manager_interface.h" #include @@ -19,7 +20,6 @@ // Forward declaration namespace webrtc { -class ThreadWrapper; class CriticalSectionWrapper; } @@ -48,7 +48,7 @@ private: void* _window2; bool _terminate; - webrtc::ThreadWrapper& _eventThread; + rtc::scoped_ptr _eventThread; webrtc::CriticalSectionWrapper& _crit; HWND _hwndMain; HWND _hwnd1; diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/framedrop_primitives.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/framedrop_primitives.cc index e623ced297..e9ff5378e9 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/framedrop_primitives.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/framedrop_primitives.cc @@ -40,7 +40,7 @@ class LocalRendererEffectFilter : public webrtc::ExternalRendererEffectFilter { FrameDropDetector* frame_drop_detector) : ExternalRendererEffectFilter(renderer), frame_drop_detector_(frame_drop_detector) {} - int Transform(int size, + int Transform(size_t size, unsigned char* frame_buffer, int64_t ntp_time_ms, unsigned int timestamp, @@ -100,7 +100,7 @@ class DecodedTimestampEffectFilter : public webrtc::ViEEffectFilter { explicit DecodedTimestampEffectFilter(FrameDropDetector* frame_drop_detector) : frame_drop_detector_(frame_drop_detector) {} virtual ~DecodedTimestampEffectFilter() {} - virtual int Transform(int size, + virtual int Transform(size_t size, unsigned char* frame_buffer, int64_t ntp_time_ms, unsigned int timestamp, @@ -593,8 +593,17 @@ int FrameDropDetector::GetNumberOfFramesDroppedAt(State state) { } int FrameDropMonitoringRemoteFileRenderer::DeliverFrame( - unsigned char *buffer, int buffer_size, uint32_t time_stamp, + unsigned char *buffer, size_t buffer_size, uint32_t time_stamp, int64_t ntp_time_ms, int64_t render_time, void* /*handle*/) { + ReportFrameStats(time_stamp, render_time); + return ViEToFileRenderer::DeliverFrame(buffer, buffer_size, + time_stamp, ntp_time_ms, + render_time, NULL); +} + +void FrameDropMonitoringRemoteFileRenderer::ReportFrameStats( + uint32_t time_stamp, + int64_t render_time) { // |render_time| provides the ideal render time for this frame. If that time // has already passed we will render it immediately. int64_t report_render_time_us = render_time * 1000; @@ -605,9 +614,12 @@ int FrameDropMonitoringRemoteFileRenderer::DeliverFrame( // Register that this frame has been rendered. frame_drop_detector_->ReportFrameState(FrameDropDetector::kRendered, time_stamp, report_render_time_us); - return ViEToFileRenderer::DeliverFrame(buffer, buffer_size, - time_stamp, ntp_time_ms, - render_time, NULL); +} + +int FrameDropMonitoringRemoteFileRenderer::DeliverI420Frame( + const webrtc::I420VideoFrame& webrtc_frame) { + ReportFrameStats(webrtc_frame.timestamp(), webrtc_frame.render_time_ms()); + return ViEToFileRenderer::DeliverI420Frame(webrtc_frame); } int FrameDropMonitoringRemoteFileRenderer::FrameSizeChange( diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/framedrop_primitives.h b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/framedrop_primitives.h index 1dd2f58d48..92d7bcc33d 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/framedrop_primitives.h +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/framedrop_primitives.h @@ -222,14 +222,20 @@ class FrameDropMonitoringRemoteFileRenderer : public ViEToFileRenderer { virtual ~FrameDropMonitoringRemoteFileRenderer() {} // Implementation of ExternalRenderer: - int FrameSizeChange(unsigned int width, unsigned int height, - unsigned int number_of_streams) OVERRIDE; - int DeliverFrame(unsigned char* buffer, int buffer_size, + int FrameSizeChange(unsigned int width, + unsigned int height, + unsigned int number_of_streams) override; + int DeliverFrame(unsigned char* buffer, + size_t buffer_size, uint32_t time_stamp, int64_t ntp_time_ms, int64_t render_time, - void* handle) OVERRIDE; + void* handle) override; + int DeliverI420Frame(const webrtc::I420VideoFrame& webrtc_frame) override; + private: + void ReportFrameStats(uint32_t time_stamp, int64_t render_time); + FrameDropDetector* frame_drop_detector_; }; diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/general_primitives.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/general_primitives.cc index 5b2c6b45a9..908345d14e 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/general_primitives.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/general_primitives.cc @@ -65,6 +65,12 @@ void RenderInWindow(webrtc::ViERender* video_render_interface, EXPECT_EQ(0, video_render_interface->StartRender(frame_provider_id)); } +void StopRenderInWindow(webrtc::ViERender* video_render_interface, + int frame_provider_id) { + EXPECT_EQ(0, video_render_interface->StopRender(frame_provider_id)); + EXPECT_EQ(0, video_render_interface->RemoveRenderer(frame_provider_id)); +} + void RenderToFile(webrtc::ViERender* renderer_interface, int frame_provider_id, ViEToFileRenderer *to_file_renderer) { diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/general_primitives.h b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/general_primitives.h index 0c3ebdeeee..cb55eb610a 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/general_primitives.h +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/primitives/general_primitives.h @@ -48,11 +48,17 @@ void FindCaptureDeviceOnSystem(webrtc::ViECapture* capture, // (See vie_window_manager_factory.h for more details on how to make one of // those). The frame provider id is a source of video frames, for instance // a capture device or a video channel. +// NOTE: A call to StopRenderInWindow needs to be done in order to clear +// up the configuration applied by this function. void RenderInWindow(webrtc::ViERender* video_render_interface, - int frame_provider_id, + int frame_provider_id, void* os_window, float z_index); +// Stops rendering into a window as previously set up by calling RenderInWindow. +void StopRenderInWindow(webrtc::ViERender* video_render_interface, + int frame_provider_id); + // Similar in function to RenderInWindow, this function instead renders to // a file using a to-file-renderer. The frame provider id is a source of // video frames, for instance a capture device or a video channel. diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest.cc index 41fafaef08..9ae4d4fce7 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest.cc @@ -76,7 +76,6 @@ void ViEAutoTest::ViEExtendedTest() ViECodecExtendedTest(); ViEImageProcessExtendedTest(); ViERenderExtendedTest(); - ViERtpRtcpExtendedTest(); } void ViEAutoTest::ViEAPITest() @@ -139,7 +138,7 @@ void ViEAutoTest::PrintAudioCodec(const webrtc::CodecInst audioCodec) ViETest::Log("\t: %u", audioCodec.pacsize); ViETest::Log("\t: %u", audioCodec.plfreq); ViETest::Log("\t: %s", audioCodec.plname); - ViETest::Log("\t: %u", audioCodec.pltype); + ViETest::Log("\t: %d", audioCodec.pltype); ViETest::Log("\t: %u", audioCodec.rate); ViETest::Log(""); } @@ -153,3 +152,11 @@ void ViEAutoTest::RenderCaptureDeviceAndOutputStream( RenderInWindow( video_engine->render, video_channel->videoChannel, _window2, 1); } + +void ViEAutoTest::StopRenderCaptureDeviceAndOutputStream( + TbInterfaces* video_engine, + TbVideoChannel* video_channel, + TbCaptureDevice* capture_device) { + StopRenderInWindow(video_engine->render, capture_device->captureId); + StopRenderInWindow(video_engine->render, video_channel->videoChannel); +} diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_android.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_android.cc index ced235f6b5..e69a3ebc9f 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_android.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_android.cc @@ -27,7 +27,7 @@ int ViEAutoTestAndroid::RunAutotest(int testSelection, int subTestSelection, webrtc::SetRenderAndroidVM(javaVM); #ifndef WEBRTC_ANDROID_OPENSLES // voice engine calls into ADM directly - webrtc::VoiceEngine::SetAndroidObjects(javaVM, env, context); + webrtc::VoiceEngine::SetAndroidObjects(javaVM, context); #endif if (subTestSelection == 0) { @@ -150,7 +150,8 @@ int ViEAutoTestAndroid::RunAutotest(int testSelection, int subTestSelection, break; case 8: // RTP/RTCP - vieAutoTest.ViERtpRtcpExtendedTest(); + // Note that this test is removed. It hasn't been properly cleaned up + // because this hopefully going away soon. break; default: diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_base.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_base.cc index 4d032ef5d8..3a94e051be 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_base.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_base.cc @@ -73,6 +73,7 @@ void ViEAutoTest::ViEBaseStandardTest() { // *************************************************************** // Testing finished. Tear down Video Engine // *************************************************************** + EXPECT_EQ(0, capture_interface->DisconnectCaptureDevice(video_channel)); EXPECT_EQ(0, capture_interface->StopCapture(capture_id)); EXPECT_EQ(0, base_interface->StopReceive(video_channel)); diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_capture.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_capture.cc index 4fd601264a..68b1afda02 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_capture.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_capture.cc @@ -83,7 +83,7 @@ class CaptureEffectFilter : public webrtc::ViEEffectFilter { } // Implements video_engineEffectFilter. - virtual int Transform(int size, + virtual int Transform(size_t size, unsigned char* frame_buffer, int64_t ntp_time_ms, unsigned int timestamp, @@ -360,26 +360,26 @@ void ViEAutoTest::ViECaptureAPITest() { EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError()); // Test GetOrientation. - webrtc::VideoCaptureRotation orientation; + webrtc::VideoRotation orientation; char dummy_name[5]; EXPECT_NE(0, dev_info->GetOrientation(dummy_name, orientation)); // Test SetRotation. - EXPECT_NE(0, video_engine.capture->SetRotateCapturedFrames( - capture_id, webrtc::RotateCapturedFrame_90)); + EXPECT_NE(0, video_engine.capture->SetVideoRotation( + capture_id, webrtc::kVideoRotation_90)); EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError()); // Allocate capture device. EXPECT_EQ(0, video_engine.capture->AllocateCaptureDevice(*vcpm, capture_id)); - EXPECT_EQ(0, video_engine.capture->SetRotateCapturedFrames( - capture_id, webrtc::RotateCapturedFrame_0)); - EXPECT_EQ(0, video_engine.capture->SetRotateCapturedFrames( - capture_id, webrtc::RotateCapturedFrame_90)); - EXPECT_EQ(0, video_engine.capture->SetRotateCapturedFrames( - capture_id, webrtc::RotateCapturedFrame_180)); - EXPECT_EQ(0, video_engine.capture->SetRotateCapturedFrames( - capture_id, webrtc::RotateCapturedFrame_270)); + EXPECT_EQ(0, video_engine.capture->SetVideoRotation( + capture_id, webrtc::kVideoRotation_0)); + EXPECT_EQ(0, video_engine.capture->SetVideoRotation( + capture_id, webrtc::kVideoRotation_90)); + EXPECT_EQ(0, video_engine.capture->SetVideoRotation( + capture_id, webrtc::kVideoRotation_180)); + EXPECT_EQ(0, video_engine.capture->SetVideoRotation( + capture_id, webrtc::kVideoRotation_270)); // Release the capture device EXPECT_EQ(0, video_engine.capture->ReleaseCaptureDevice(capture_id)); @@ -445,7 +445,7 @@ void ViEAutoTest::ViECaptureExternalCaptureTest() { /// ************************************************************** // Engine ready. Begin testing class /// ************************************************************** - const unsigned int video_frame_length = (176 * 144 * 3) / 2; + const size_t video_frame_length = (176 * 144 * 3) / 2; unsigned char* video_frame = new unsigned char[video_frame_length]; memset(video_frame, 128, 176 * 144); diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_codec.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_codec.cc index 93738c2a17..f5ff771a70 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_codec.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_codec.cc @@ -8,10 +8,10 @@ * be found in the AUTHORS file in the root of the source tree. */ +#include "webrtc/base/scoped_ptr.h" #include "webrtc/common_types.h" #include "webrtc/engine_configurations.h" #include "webrtc/modules/video_coding/codecs/i420/main/interface/i420.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/test/channel_transport/include/channel_transport.h" #include "webrtc/video_engine/include/vie_base.h" #include "webrtc/video_engine/include/vie_capture.h" @@ -100,7 +100,7 @@ class TestCodecObserver : public webrtc::ViEEncoderObserver, last_outgoing_bitrate_ += bitrate; } - virtual void SuspendChange(int video_channel, bool is_suspended) OVERRIDE { + void SuspendChange(int video_channel, bool is_suspended) override { suspend_change_called_++; } @@ -122,7 +122,7 @@ class RenderFilter : public webrtc::ViEEffectFilter { virtual ~RenderFilter() { } - virtual int Transform(int size, + virtual int Transform(size_t size, unsigned char* frame_buffer, int64_t ntp_time_ms, unsigned int timestamp, @@ -190,9 +190,8 @@ void ViEAutoTest::ViECodecStandardTest() { const char* ip_address = "127.0.0.1"; const uint16_t rtp_port = 6000; - webrtc::scoped_ptr - video_channel_transport( - new webrtc::test::VideoChannelTransport(network, video_channel)); + rtc::scoped_ptr video_channel_transport( + new webrtc::test::VideoChannelTransport(network, video_channel)); ASSERT_EQ(0, video_channel_transport->SetSendDestination(ip_address, rtp_port)); @@ -336,7 +335,7 @@ void ViEAutoTest::ViECodecExtendedTest() { const char* ip_address = "127.0.0.1"; const uint16_t rtp_port = 6000; - webrtc::scoped_ptr + rtc::scoped_ptr video_channel_transport( new webrtc::test::VideoChannelTransport(network, video_channel)); @@ -387,7 +386,7 @@ void ViEAutoTest::ViECodecExtendedTest() { uint16_t rtp_port_1 = 12000; uint16_t rtp_port_2 = 13000; - webrtc::scoped_ptr + rtc::scoped_ptr video_channel_transport_1( new webrtc::test::VideoChannelTransport(network, video_channel_1)); @@ -395,7 +394,7 @@ void ViEAutoTest::ViECodecExtendedTest() { rtp_port_1)); ASSERT_EQ(0, video_channel_transport_1->SetLocalReceiver(rtp_port_1)); - webrtc::scoped_ptr + rtc::scoped_ptr video_channel_transport_2( new webrtc::test::VideoChannelTransport(network, video_channel_2)); @@ -515,7 +514,9 @@ void ViEAutoTest::ViECodecAPITest() { video_codec.startBitrate = 50; EXPECT_EQ(0, codec->SetSendCodec(video_channel, video_codec)); EXPECT_EQ(0, codec->GetSendCodec(video_channel, video_codec)); - EXPECT_EQ(kMinBitrate, video_codec.startBitrate); + // We don't allow allocated start bitrate to be decreased via SetSendCodec, + // and the default bitrate available in the allocator is 300. + EXPECT_EQ(300u, video_codec.startBitrate); memset(&video_codec, 0, sizeof(video_codec)); EXPECT_EQ(0, codec->GetSendCodec(video_channel, video_codec)); diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_custom_call.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_custom_call.cc index e7994d3eda..1a6633232a 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_custom_call.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_custom_call.cc @@ -15,7 +15,7 @@ #include #include "gflags/gflags.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/test/channel_transport/include/channel_transport.h" #include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h" #include "webrtc/video_engine/test/auto_test/interface/vie_autotest_defines.h" @@ -73,7 +73,7 @@ class ViEAutotestEncoderObserver : public webrtc::ViEEncoderObserver { << " BR: " << bitrate << std::endl; } - virtual void SuspendChange(int video_channel, bool is_suspended) OVERRIDE { + void SuspendChange(int video_channel, bool is_suspended) override { std::cout << "SuspendChange: " << is_suspended << std::endl; } }; @@ -283,10 +283,8 @@ int ViEAutoTest::ViECustomCall() { int buffer_delay_ms = 0; bool is_image_scale_enabled = false; bool remb = true; - webrtc::scoped_ptr - video_channel_transport; - webrtc::scoped_ptr - voice_channel_transport; + rtc::scoped_ptr video_channel_transport; + rtc::scoped_ptr voice_channel_transport; while (!start_call) { // Get the IP address to use from call. @@ -1510,7 +1508,7 @@ void PrintRTCCPStatistics(webrtc::ViERTP_RTCP* vie_rtp_rtcp, int error = 0; int number_of_errors = 0; webrtc::RtcpStatistics rtcp_stats; - int rtt_ms = 0; + int64_t rtt_ms = 0; switch (stat_type) { case kReceivedStatistic: @@ -1564,13 +1562,13 @@ void PrintRTPStatistics(webrtc::ViERTP_RTCP* vie_rtp_rtcp, "ERROR: %s at line %d", __FUNCTION__, __LINE__); std::cout << "\tRTP bytes sent: " - << sent.bytes << std::endl; + << sent.transmitted.payload_bytes << std::endl; std::cout << "\tRTP packets sent: " - << sent.packets << std::endl; + << sent.transmitted.packets << std::endl; std::cout << "\tRTP bytes received: " - << received.bytes << std::endl; + << received.transmitted.payload_bytes << std::endl; std::cout << "\tRTP packets received: " - << received.packets << std::endl; + << received.transmitted.packets << std::endl; } void PrintBandwidthUsage(webrtc::ViERTP_RTCP* vie_rtp_rtcp, diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_image_process.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_image_process.cc index c6f0a05981..de8d2d1dea 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_image_process.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_image_process.cc @@ -28,7 +28,7 @@ public: ~MyEffectFilter() {} - virtual int Transform(int size, + virtual int Transform(size_t size, unsigned char* frame_buffer, int64_t ntp_time_ms, unsigned int timestamp, @@ -48,7 +48,7 @@ void ViEAutoTest::ViEImageProcessStandardTest() //*************************************************************** int rtpPort = 6000; // Create VIE - TbInterfaces ViE("ViEImageProcessAPITest"); + TbInterfaces ViE("ViEImageProcessStandardTest"); // Create a video channel TbVideoChannel tbChannel(ViE, webrtc::kVideoCodecVP8); // Create a capture device @@ -89,8 +89,9 @@ void ViEAutoTest::ViEImageProcessStandardTest() ViETest::Log("Only Window 2 should be black and white"); AutoTestSleep(kAutoTestSleepTimeMs); - EXPECT_EQ(0, ViE.render->StopRender(tbCapture.captureId)); - EXPECT_EQ(0, ViE.render->RemoveRenderer(tbCapture.captureId)); + StopRenderCaptureDeviceAndOutputStream(&ViE, &tbChannel, &tbCapture); + + tbCapture.Disconnect(tbChannel.videoChannel); int rtpPort2 = rtpPort + 100; // Create a video channel @@ -130,6 +131,10 @@ void ViEAutoTest::ViEImageProcessStandardTest() EXPECT_EQ(0, ViE.image_process->DeregisterSendEffectFilter( tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.render->RemoveRenderer(tbChannel2.videoChannel)); + + tbCapture.Disconnect(tbChannel2.videoChannel); + //*************************************************************** // Testing finished. Tear down Video Engine //*************************************************************** @@ -222,4 +227,6 @@ void ViEAutoTest::ViEImageProcessAPITest() tbChannel.videoChannel, false)); EXPECT_NE(0, ViE.image_process->EnableColorEnhancement( tbCapture.captureId, true)); + + tbCapture.Disconnect(tbChannel.videoChannel); } diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_linux.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_linux.cc index fd9cf8156f..337bf8a656 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_linux.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_linux.cc @@ -17,7 +17,6 @@ #include "webrtc/engine_configurations.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" -#include "webrtc/system_wrappers/interface/thread_wrapper.h" #include "webrtc/video_engine/test/auto_test/interface/vie_autotest_defines.h" #include "webrtc/video_engine/test/auto_test/interface/vie_autotest_main.h" diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_loopback.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_loopback.cc index 03a82b4ca0..ffc9757984 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_loopback.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_loopback.cc @@ -21,9 +21,9 @@ #include +#include "webrtc/base/scoped_ptr.h" #include "webrtc/common_types.h" #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/test/channel_transport/include/channel_transport.h" #include "webrtc/video_engine/include/vie_base.h" #include "webrtc/video_engine/include/vie_capture.h" @@ -427,13 +427,17 @@ int VideoEngineSampleCode(void* window1, void* window2) // Set number of temporal layers. std::cout << std::endl; - std::cout << "Choose number of temporal layers (1 to 4)."; - std::cout << "Press enter for default: \n"; + std::cout << "Choose number of temporal layers for VP8 (1 to 4). "; + std::cout << "Press enter for default (=1) for other codecs: \n"; std::getline(std::cin, str); int numTemporalLayers = atoi(str.c_str()); - if(numTemporalLayers != 0) - { - videoCodec.codecSpecific.VP8.numberOfTemporalLayers = numTemporalLayers; + if (numTemporalLayers != 0 && + videoCodec.codecType == webrtc::kVideoCodecVP8) { + videoCodec.codecSpecific.VP8.numberOfTemporalLayers = numTemporalLayers; + } else if (videoCodec.codecType == webrtc::kVideoCodecVP9) { + // Temporal layers for vp9 not yet supported in webrtc. + numTemporalLayers = 1; + videoCodec.codecSpecific.VP9.numberOfTemporalLayers = 1; } // Set start bit rate diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_record.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_record.cc index 89575ceea9..947939309b 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_record.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_record.cc @@ -156,9 +156,8 @@ int VideoEngineSampleRecordCode(void* window1, void* window2) { audio_channel = voe_base->CreateChannel(); - webrtc::scoped_ptr - voice_channel_transport( - new webrtc::test::VoiceChannelTransport(voe_network, audio_channel)); + rtc::scoped_ptr voice_channel_transport( + new webrtc::test::VoiceChannelTransport(voe_network, audio_channel)); voice_channel_transport->SetSendDestination(ipAddress, audio_tx_port); voice_channel_transport->SetLocalReceiver(audio_rx_port); diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_render.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_render.cc index 1e9155f99f..c30fbf32a4 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_render.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_render.cc @@ -12,6 +12,7 @@ // vie_autotest_render.cc // +#include "webrtc/base/format_macros.h" #include "webrtc/engine_configurations.h" #include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h" #include "webrtc/video_engine/test/auto_test/interface/vie_autotest_defines.h" @@ -57,19 +58,25 @@ public: } virtual int DeliverFrame(unsigned char* buffer, - int bufferSize, + size_t bufferSize, uint32_t time_stamp, int64_t ntp_time_ms, int64_t render_time, void* /*handle*/) { if (bufferSize != CalcBufferSize(webrtc::kI420, _width, _height)) { - ViETest::Log("Incorrect render buffer received, of length = %d\n", - bufferSize); + ViETest::Log("Incorrect render buffer received, of length = %" PRIuS + "\n", bufferSize); return 0; } return 0; } + virtual int DeliverI420Frame(const webrtc::I420VideoFrame& webrtc_frame) { + EXPECT_EQ(webrtc_frame.width(), _width); + EXPECT_EQ(webrtc_frame.height(), _height); + return 0; + } + virtual bool IsTextureSupported() { return false; } public: @@ -213,29 +220,6 @@ void ViEAutoTest::ViERenderExtendedTest() AutoTestSleep(kAutoTestSleepTimeMs); #endif - ViETest::Log("Mirroring Local Preview (Window1) Left-Right"); - EXPECT_EQ(0, ViE.render->MirrorRenderStream( - tbCapture.captureId, true, false, true)); - AutoTestSleep(kAutoTestSleepTimeMs); - - ViETest::Log("\nMirroring Local Preview (Window1) Left-Right and Up-Down"); - EXPECT_EQ(0, ViE.render->MirrorRenderStream( - tbCapture.captureId, true, true, true)); - AutoTestSleep(kAutoTestSleepTimeMs); - - ViETest::Log("\nMirroring Remote Window(Window2) Up-Down"); - EXPECT_EQ(0, ViE.render->MirrorRenderStream( - tbChannel.videoChannel, true, true, false)); - AutoTestSleep(kAutoTestSleepTimeMs); - - ViETest::Log("Disabling Mirroing on Window1 and Window2"); - EXPECT_EQ(0, ViE.render->MirrorRenderStream( - tbCapture.captureId, false, false, false)); - AutoTestSleep(kAutoTestSleepTimeMs); - EXPECT_EQ(0, ViE.render->MirrorRenderStream( - tbChannel.videoChannel, false, false, false)); - AutoTestSleep(kAutoTestSleepTimeMs); - ViETest::Log("\nEnabling Full Screen render in 5 sec"); EXPECT_EQ(0, ViE.render->RemoveRenderer(tbCapture.captureId)); @@ -313,6 +297,7 @@ void ViEAutoTest::ViERenderAPITest() { // Already started. EXPECT_EQ(-1, ViE.render->SetExpectedRenderDelay(tbChannel.videoChannel, 50)); EXPECT_EQ(0, ViE.render->StopRender(tbChannel.videoChannel)); + // Invalid values. EXPECT_EQ(-1, ViE.render->SetExpectedRenderDelay(tbChannel.videoChannel, 9)); EXPECT_EQ(-1, ViE.render->SetExpectedRenderDelay(tbChannel.videoChannel, @@ -320,4 +305,8 @@ void ViEAutoTest::ViERenderAPITest() { // Valid values. EXPECT_EQ(0, ViE.render->SetExpectedRenderDelay(tbChannel.videoChannel, 11)); EXPECT_EQ(0, ViE.render->SetExpectedRenderDelay(tbChannel.videoChannel, 499)); + + EXPECT_EQ(0, ViE.render->RemoveRenderer(tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.render->RemoveRenderer(tbCapture.captureId)); + tbCapture.Disconnect(tbChannel.videoChannel); } diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc index b7d02156c2..47dbae4e42 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc @@ -40,52 +40,6 @@ public: } }; -class ViERtcpObserver: public webrtc::ViERTCPObserver -{ -public: - int _channel; - unsigned char _subType; - unsigned int _name; - char* _data; - unsigned short _dataLength; - - ViERtcpObserver() : - _channel(-1), - _subType(0), - _name(0), - _data(NULL), - _dataLength(0) - { - } - ~ViERtcpObserver() - { - if (_data) - { - delete[] _data; - } - } - virtual void OnApplicationDataReceived( - const int videoChannel, const unsigned char subType, - const unsigned int name, const char* data, - const unsigned short dataLengthInBytes) - { - _channel = videoChannel; - _subType = subType; - _name = name; - if (dataLengthInBytes > _dataLength) - { - delete[] _data; - _data = NULL; - } - if (_data == NULL) - { - _data = new char[dataLengthInBytes]; - } - memcpy(_data, data, dataLengthInBytes); - _dataLength = dataLengthInBytes; - } -}; - void ViEAutoTest::ViERtpRtcpStandardTest() { // *************************************************************** @@ -166,7 +120,7 @@ void ViEAutoTest::ViERtpRtcpStandardTest() // Pacing // webrtc::RtcpStatistics received; - int recRttMs = 0; + int64_t recRttMs = 0; unsigned int sentTotalBitrate = 0; unsigned int sentVideoBitrate = 0; unsigned int sentFecBitrate = 0; @@ -286,7 +240,7 @@ void ViEAutoTest::ViERtpRtcpStandardTest() EXPECT_EQ(0, ViE.base->StartSend(tbChannel.videoChannel)); webrtc::RtcpStatistics sent; - int sentRttMs = 0; + int64_t sentRttMs = 0; // Fraction lost is a transient value that can get reset after a new rtcp // report block. Make regular polls to make sure it is propagated. @@ -542,21 +496,24 @@ void ViEAutoTest::ViERtpRtcpStandardTest() EXPECT_EQ(0, ViE.rtp_rtcp->GetRtpStatistics(tbChannel.videoChannel, sent_after, received_after)); if (FLAGS_include_timing_dependent_tests) { - EXPECT_GT(received_after.bytes, received_before.bytes); + EXPECT_GT(received_after.transmitted.payload_bytes, + received_before.transmitted.payload_bytes); } // Simulate lost reception and verify that nothing is sent during that time. ViE.network->SetNetworkTransmissionState(tbChannel.videoChannel, false); // Allow the encoder to finish the current frame before we expect that no // additional packets will be sent. AutoTestSleep(kAutoTestSleepTimeMs); - received_before.bytes = received_after.bytes; + received_before.transmitted.payload_bytes = + received_after.transmitted.payload_bytes; ViETest::Log("Network Down...\n"); AutoTestSleep(kAutoTestSleepTimeMs); EXPECT_EQ(0, ViE.rtp_rtcp->GetRtpStatistics(tbChannel.videoChannel, sent_before, received_before)); if (FLAGS_include_timing_dependent_tests) { - EXPECT_EQ(received_before.bytes, received_after.bytes); + EXPECT_EQ(received_before.transmitted.payload_bytes, + received_after.transmitted.payload_bytes); } // Network reception back. Video should now be sent. @@ -567,9 +524,11 @@ void ViEAutoTest::ViERtpRtcpStandardTest() sent_before, received_before)); if (FLAGS_include_timing_dependent_tests) { - EXPECT_GT(received_before.bytes, received_after.bytes); + EXPECT_GT(received_before.transmitted.payload_bytes, + received_after.transmitted.payload_bytes); } - received_after.bytes = received_before.bytes; + received_after.transmitted.payload_bytes = + received_before.transmitted.payload_bytes; // Buffering mode. EXPECT_EQ(0, ViE.base->StopSend(tbChannel.videoChannel)); EXPECT_EQ(0, ViE.base->StopReceive(tbChannel.videoChannel)); @@ -593,15 +552,18 @@ void ViEAutoTest::ViERtpRtcpStandardTest() sent_before, received_before)); if (FLAGS_include_timing_dependent_tests) { - EXPECT_GT(received_before.bytes, received_after.bytes); + EXPECT_GT(received_before.transmitted.payload_bytes, + received_after.transmitted.payload_bytes); } - received_after.bytes = received_before.bytes; + received_after.transmitted.payload_bytes = + received_before.transmitted.payload_bytes; AutoTestSleep(kAutoTestSleepTimeMs); EXPECT_EQ(0, ViE.rtp_rtcp->GetRtpStatistics(tbChannel.videoChannel, sent_before, received_before)); if (FLAGS_include_timing_dependent_tests) { - EXPECT_EQ(received_after.bytes, received_before.bytes); + EXPECT_EQ(received_after.transmitted.payload_bytes, + received_before.transmitted.payload_bytes); } // Network reception back. Video should now be sent. ViETest::Log("Network Up...\n"); @@ -611,7 +573,8 @@ void ViEAutoTest::ViERtpRtcpStandardTest() sent_before, received_before)); if (FLAGS_include_timing_dependent_tests) { - EXPECT_GT(received_before.bytes, received_after.bytes); + EXPECT_GT(received_before.transmitted.payload_bytes, + received_after.transmitted.payload_bytes); } // TODO(holmer): Verify that the decoded framerate doesn't decrease on an // outage when in buffering mode. This isn't currently possible because we @@ -630,70 +593,6 @@ void ViEAutoTest::ViERtpRtcpStandardTest() //*************************************************************** } -void ViEAutoTest::ViERtpRtcpExtendedTest() -{ - //*************************************************************** - // Begin create/initialize WebRTC Video Engine for testing - //*************************************************************** - // Create VIE - TbInterfaces ViE("ViERtpRtcpExtendedTest"); - // Create a video channel - TbVideoChannel tbChannel(ViE, webrtc::kVideoCodecVP8); - // Create a capture device - TbCaptureDevice tbCapture(ViE); - tbCapture.ConnectTo(tbChannel.videoChannel); - - //tbChannel.StartReceive(rtpPort); - //tbChannel.StartSend(rtpPort); - TbExternalTransport myTransport(*(ViE.network), tbChannel.videoChannel, - NULL); - - EXPECT_EQ(0, ViE.network->DeregisterSendTransport(tbChannel.videoChannel)); - EXPECT_EQ(0, ViE.network->RegisterSendTransport( - tbChannel.videoChannel, myTransport)); - EXPECT_EQ(0, ViE.base->StartReceive(tbChannel.videoChannel)); - EXPECT_EQ(0, ViE.base->StartSend(tbChannel.videoChannel)); - - //*************************************************************** - // Engine ready. Begin testing class - //*************************************************************** - - // - // Application specific RTCP - // - // - - ViERtcpObserver rtcpObserver; - EXPECT_EQ(0, ViE.rtp_rtcp->RegisterRTCPObserver( - tbChannel.videoChannel, rtcpObserver)); - - unsigned char subType = 3; - unsigned int name = static_cast (0x41424344); // 'ABCD'; - const char* data = "ViEAutoTest Data of length 32 -\0"; - const unsigned short numBytes = 32; - - EXPECT_EQ(0, ViE.rtp_rtcp->SendApplicationDefinedRTCPPacket( - tbChannel.videoChannel, subType, name, data, numBytes)); - - ViETest::Log("Sending RTCP application data...\n"); - AutoTestSleep(kAutoTestSleepTimeMs); - - EXPECT_EQ(subType, rtcpObserver._subType); - EXPECT_STRCASEEQ(data, rtcpObserver._data); - EXPECT_EQ(name, rtcpObserver._name); - EXPECT_EQ(numBytes, rtcpObserver._dataLength); - - ViETest::Log("\t RTCP application data received\n"); - - //*************************************************************** - // Testing finished. Tear down Video Engine - //*************************************************************** - EXPECT_EQ(0, ViE.base->StopReceive(tbChannel.videoChannel)); - EXPECT_EQ(0, ViE.base->StopSend(tbChannel.videoChannel)); - - EXPECT_EQ(0, ViE.network->DeregisterSendTransport(tbChannel.videoChannel)); -} - void ViEAutoTest::ViERtpRtcpAPITest() { //*************************************************************** @@ -853,16 +752,6 @@ void ViEAutoTest::ViERtpRtcpAPITest() tbChannel.videoChannel)); EXPECT_NE(0, ViE.rtp_rtcp->DeregisterRTPObserver( tbChannel.videoChannel)); - - ViERtcpObserver rtcpObserver; - EXPECT_EQ(0, ViE.rtp_rtcp->RegisterRTCPObserver( - tbChannel.videoChannel, rtcpObserver)); - EXPECT_NE(0, ViE.rtp_rtcp->RegisterRTCPObserver( - tbChannel.videoChannel, rtcpObserver)); - EXPECT_EQ(0, ViE.rtp_rtcp->DeregisterRTCPObserver( - tbChannel.videoChannel)); - EXPECT_NE(0, ViE.rtp_rtcp->DeregisterRTCPObserver( - tbChannel.videoChannel)); } // // PLI diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_win.cc b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_win.cc index 98e37a4171..6e2bac3f9f 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_win.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/source/vie_autotest_win.cc @@ -19,7 +19,6 @@ #include "webrtc/engine_configurations.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" -#include "webrtc/system_wrappers/interface/thread_wrapper.h" #include @@ -47,9 +46,8 @@ ViEAutoTestWindowManager::ViEAutoTestWindowManager() : _window1(NULL), _window2(NULL), _terminate(false), - _eventThread(*webrtc::ThreadWrapper::CreateThread( - EventProcess, this, webrtc::kNormalPriority, - "ViEAutotestEventThread")), + _eventThread(webrtc::ThreadWrapper::CreateThread( + EventProcess, this, "ViEAutotestEventThread")), _crit(*webrtc::CriticalSectionWrapper::CreateCriticalSection()), _hwnd1(NULL), _hwnd2(NULL), @@ -86,8 +84,7 @@ int ViEAutoTestWindowManager::CreateWindows(AutoTestRect window1Size, memcpy(_hwnd1Title, window1Title, TITLE_LENGTH); memcpy(_hwnd2Title, window2Title, TITLE_LENGTH); - unsigned int tId = 0; - _eventThread.Start(tId); + _eventThread->Start(); do { _crit.Enter(); @@ -102,14 +99,11 @@ int ViEAutoTestWindowManager::CreateWindows(AutoTestRect window1Size, } int ViEAutoTestWindowManager::TerminateWindows() { - _eventThread.SetNotAlive(); - _terminate = true; - if (_eventThread.Stop()) { - _crit.Enter(); - delete &_eventThread; - _crit.Leave(); - } + _eventThread->Stop(); + _crit.Enter(); + _eventThread.reset(); + _crit.Leave(); return 0; } diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/vie_auto_test.gypi b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/vie_auto_test.gypi index c8886d8f5e..e52b301651 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/vie_auto_test.gypi +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/vie_auto_test.gypi @@ -12,8 +12,9 @@ 'target_name': 'vie_auto_test', 'type': 'executable', 'dependencies': [ - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:metrics_default', + '<(webrtc_root)/common.gyp:webrtc_common', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:metrics_default', '<(webrtc_root)/modules/modules.gyp:video_capture_module_internal_impl', '<(webrtc_root)/modules/modules.gyp:video_render_module_internal_impl', '<(webrtc_root)/voice_engine/voice_engine.gyp:voice_engine', diff --git a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/vie_auto_test.isolate b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/vie_auto_test.isolate index da09a6e5b7..2579a20b20 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/auto_test/vie_auto_test.isolate +++ b/media/webrtc/trunk/webrtc/video_engine/test/auto_test/vie_auto_test.isolate @@ -7,14 +7,6 @@ # be found in the AUTHORS file in the root of the source tree. { 'conditions': [ - ['OS=="android"', { - 'variables': { - 'files': [ - '<(DEPTH)/data/', - '<(DEPTH)/resources/', - ], - }, - }], ['OS=="linux" or OS=="mac" or OS=="win"', { 'variables': { 'command': [ diff --git a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/helpers/vie_fake_camera.cc b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/helpers/vie_fake_camera.cc index 8699f04aeb..1c18d498e0 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/helpers/vie_fake_camera.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/helpers/vie_fake_camera.cc @@ -11,7 +11,6 @@ #include -#include "webrtc/system_wrappers/interface/thread_wrapper.h" #include "webrtc/video_engine/include/vie_capture.h" #include "webrtc/video_engine/test/libvietest/include/vie_file_capture_device.h" @@ -34,7 +33,6 @@ bool StreamVideoFileRepeatedlyIntoCaptureDevice(void* data) { ViEFakeCamera::ViEFakeCamera(webrtc::ViECapture* capture_interface) : capture_interface_(capture_interface), capture_id_(-1), - camera_thread_(NULL), file_capture_device_(NULL) { } @@ -63,9 +61,9 @@ bool ViEFakeCamera::StartCameraInNewThread( // Set up a thread which runs the fake camera. The capturer object is // thread-safe. camera_thread_ = webrtc::ThreadWrapper::CreateThread( - StreamVideoFileRepeatedlyIntoCaptureDevice, file_capture_device_); - unsigned int id; - camera_thread_->Start(id); + StreamVideoFileRepeatedlyIntoCaptureDevice, file_capture_device_, + "StreamVideoFileRepeatedlyIntoCaptureDevice"); + camera_thread_->Start(); return true; } @@ -78,7 +76,7 @@ bool ViEFakeCamera::StopCamera() { int result = capture_interface_->ReleaseCaptureDevice(capture_id_); - delete camera_thread_; + camera_thread_.reset(); delete file_capture_device_; camera_thread_ = NULL; file_capture_device_ = NULL; diff --git a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/helpers/vie_file_capture_device.cc b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/helpers/vie_file_capture_device.cc index b86ff0926a..4f2db75498 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/helpers/vie_file_capture_device.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/helpers/vie_file_capture_device.cc @@ -80,14 +80,15 @@ void ViEFileCaptureDevice::ReadFileFor(uint64_t time_slice_ms, while (elapsed_ms < time_slice_ms) { FramePacemaker pacemaker(max_fps); - int read = fread(frame_buffer, 1, frame_length_, input_file_); + size_t read = fread(frame_buffer, 1, frame_length_, input_file_); - if (feof(input_file_)) { + if (feof(input_file_) || read != frame_length_) { rewind(input_file_); } - input_sink_->IncomingFrame(frame_buffer, read, width_, height_, - webrtc::kVideoI420, - webrtc::TickTime::MillisecondTimestamp()); + webrtc::I420VideoFrame frame; + frame.CreateFrame(frame_buffer, width_, height_, webrtc::kVideoRotation_0); + frame.set_render_time_ms(webrtc::TickTime::MillisecondTimestamp()); + input_sink_->IncomingFrame(frame); pacemaker.SleepIfNecessary(sleeper); elapsed_ms = webrtc::TickTime::MillisecondTimestamp() - start_time_ms; diff --git a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/helpers/vie_to_file_renderer.cc b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/helpers/vie_to_file_renderer.cc index 16c73f4e6f..d0aee84bd6 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/helpers/vie_to_file_renderer.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/helpers/vie_to_file_renderer.cc @@ -12,6 +12,7 @@ #include +#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/event_wrapper.h" #include "webrtc/system_wrappers/interface/thread_wrapper.h" @@ -19,19 +20,10 @@ namespace test { struct Frame { public: - Frame(unsigned char* buffer, - int buffer_size, - uint32_t timestamp, - int64_t render_time) - : buffer(new unsigned char[buffer_size]), - buffer_size(buffer_size), - timestamp(timestamp), - render_time(render_time) { - memcpy(this->buffer.get(), buffer, buffer_size); - } + Frame() : buffer(nullptr), buffer_size(0), timestamp(0), render_time(0) {} - webrtc::scoped_ptr buffer; - int buffer_size; + rtc::scoped_ptr buffer; + size_t buffer_size; uint32_t timestamp; int64_t render_time; @@ -45,8 +37,7 @@ ViEToFileRenderer::ViEToFileRenderer() output_path_(), output_filename_(), thread_(webrtc::ThreadWrapper::CreateThread( - ViEToFileRenderer::RunRenderThread, - this, webrtc::kNormalPriority, "ViEToFileRendererThread")), + ViEToFileRenderer::RunRenderThread, this, "ViEToFileRendererThread")), frame_queue_cs_(webrtc::CriticalSectionWrapper::CreateCriticalSection()), frame_render_event_(webrtc::EventWrapper::Create()), render_queue_(), @@ -73,14 +64,12 @@ bool ViEToFileRenderer::PrepareForRendering( output_filename_ = output_filename; output_path_ = output_path; - unsigned int tid; - return thread_->Start(tid); + return thread_->Start(); } void ViEToFileRenderer::StopRendering() { assert(output_file_ != NULL); if (thread_.get() != NULL) { - thread_->SetNotAlive(); // Signal that a frame is ready to be written to file. frame_render_event_->Set(); // Call Stop() repeatedly, waiting for ProcessRenderQueue() to finish. @@ -120,28 +109,54 @@ void ViEToFileRenderer::ForgetOutputFile() { output_path_ = ""; } +test::Frame* ViEToFileRenderer::NewFrame(size_t buffer_size) { + test::Frame* frame; + if (free_frame_queue_.empty()) { + frame = new test::Frame(); + } else { + // Reuse an already allocated frame. + frame = free_frame_queue_.front(); + free_frame_queue_.pop_front(); + } + if (frame->buffer_size < buffer_size) { + frame->buffer.reset(new unsigned char[buffer_size]); + frame->buffer_size = buffer_size; + } + return frame; +} + int ViEToFileRenderer::DeliverFrame(unsigned char *buffer, - int buffer_size, + size_t buffer_size, uint32_t time_stamp, int64_t ntp_time_ms, int64_t render_time, void* /*handle*/) { webrtc::CriticalSectionScoped lock(frame_queue_cs_.get()); - test::Frame* frame; - if (free_frame_queue_.empty()) { - frame = new test::Frame(buffer, buffer_size, time_stamp, render_time); - } else { - // Reuse an already allocated frame. - frame = free_frame_queue_.front(); - free_frame_queue_.pop_front(); - if (frame->buffer_size < buffer_size) { - frame->buffer.reset(new unsigned char[buffer_size]); - } - memcpy(frame->buffer.get(), buffer, buffer_size); - frame->buffer_size = buffer_size; - frame->timestamp = time_stamp; - frame->render_time = render_time; - } + test::Frame* frame = NewFrame(buffer_size); + memcpy(frame->buffer.get(), buffer, buffer_size); + frame->timestamp = time_stamp; + frame->render_time = render_time; + + render_queue_.push_back(frame); + // Signal that a frame is ready to be written to file. + frame_render_event_->Set(); + return 0; +} + +int ViEToFileRenderer::DeliverI420Frame( + const webrtc::I420VideoFrame& input_frame) { + const size_t buffer_size = + CalcBufferSize(webrtc::kI420, input_frame.width(), input_frame.height()); + webrtc::CriticalSectionScoped lock(frame_queue_cs_.get()); + test::Frame* frame = NewFrame(buffer_size); + const int length = + ExtractBuffer(input_frame, frame->buffer_size, frame->buffer.get()); + assert(static_cast(length) == buffer_size); + if (length < 0) + return -1; + frame->timestamp = input_frame.timestamp(); + frame->render_time = input_frame.render_time_ms(); + render_queue_.push_back(frame); // Signal that a frame is ready to be written to file. frame_render_event_->Set(); @@ -174,8 +189,8 @@ bool ViEToFileRenderer::ProcessRenderQueue() { // the renderer. frame_queue_cs_->Leave(); assert(output_file_); - int written = fwrite(frame->buffer.get(), sizeof(unsigned char), - frame->buffer_size, output_file_); + size_t written = fwrite(frame->buffer.get(), sizeof(unsigned char), + frame->buffer_size, output_file_); frame_queue_cs_->Enter(); // Return the frame. free_frame_queue_.push_front(frame); diff --git a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/tb_I420_codec.h b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/tb_I420_codec.h index 2037ba910d..918edf96c3 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/tb_I420_codec.h +++ b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/tb_I420_codec.h @@ -24,28 +24,28 @@ public: TbI420Encoder(); virtual ~TbI420Encoder(); - virtual int32_t InitEncode(const webrtc::VideoCodec* codecSettings, - int32_t numberOfCores, - uint32_t maxPayloadSize) OVERRIDE; + int32_t InitEncode(const webrtc::VideoCodec* codecSettings, + int32_t numberOfCores, + size_t maxPayloadSize) override; - virtual int32_t Encode( + int32_t Encode( const webrtc::I420VideoFrame& inputImage, const webrtc::CodecSpecificInfo* codecSpecificInfo, - const std::vector* frameTypes) OVERRIDE; + const std::vector* frameTypes) override; - virtual int32_t RegisterEncodeCompleteCallback( - webrtc::EncodedImageCallback* callback) OVERRIDE; + int32_t RegisterEncodeCompleteCallback( + webrtc::EncodedImageCallback* callback) override; - virtual int32_t Release() OVERRIDE; + int32_t Release() override; - virtual int32_t SetChannelParameters(uint32_t packetLoss, int rtt) OVERRIDE; + int32_t SetChannelParameters(uint32_t packetLoss, int64_t rtt) override; - virtual int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) OVERRIDE; + int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) override; - virtual int32_t SetPeriodicKeyFrames(bool enable) OVERRIDE; + int32_t SetPeriodicKeyFrames(bool enable) override; - virtual int32_t CodecConfigParameters(uint8_t* /*buffer*/, - int32_t /*size*/) OVERRIDE; + int32_t CodecConfigParameters(uint8_t* /*buffer*/, + int32_t /*size*/) override; struct FunctionCalls { @@ -81,19 +81,18 @@ public: TbI420Decoder(); virtual ~TbI420Decoder(); - virtual int32_t InitDecode(const webrtc::VideoCodec* inst, - int32_t numberOfCores) OVERRIDE; - virtual int32_t Decode( - const webrtc::EncodedImage& inputImage, - bool missingFrames, - const webrtc::RTPFragmentationHeader* fragmentation, - const webrtc::CodecSpecificInfo* codecSpecificInfo = NULL, - int64_t renderTimeMs = -1) OVERRIDE; + int32_t InitDecode(const webrtc::VideoCodec* inst, + int32_t numberOfCores) override; + int32_t Decode(const webrtc::EncodedImage& inputImage, + bool missingFrames, + const webrtc::RTPFragmentationHeader* fragmentation, + const webrtc::CodecSpecificInfo* codecSpecificInfo = NULL, + int64_t renderTimeMs = -1) override; - virtual int32_t RegisterDecodeCompleteCallback( - webrtc::DecodedImageCallback* callback) OVERRIDE; - virtual int32_t Release() OVERRIDE; - virtual int32_t Reset() OVERRIDE; + int32_t RegisterDecodeCompleteCallback( + webrtc::DecodedImageCallback* callback) override; + int32_t Release() override; + int32_t Reset() override; struct FunctionCalls { diff --git a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/tb_external_transport.h b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/tb_external_transport.h index b4518a3fb0..e11c02d181 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/tb_external_transport.h +++ b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/tb_external_transport.h @@ -19,12 +19,12 @@ #include #include "webrtc/common_types.h" +#include "webrtc/system_wrappers/interface/thread_wrapper.h" namespace webrtc { class CriticalSectionWrapper; class EventWrapper; -class ThreadWrapper; class ViENetwork; } @@ -85,8 +85,8 @@ public: TbExternalTransport::SsrcChannelMap* receive_channels); ~TbExternalTransport(void); - virtual int SendPacket(int channel, const void *data, int len) OVERRIDE; - virtual int SendRTCPPacket(int channel, const void *data, int len) OVERRIDE; + int SendPacket(int channel, const void* data, size_t len) override; + int SendRTCPPacket(int channel, const void* data, size_t len) override; // Should only be called before/after traffic is being processed. // Only one observer can be set (multiple calls will overwrite each other). @@ -139,7 +139,7 @@ private: typedef struct { int8_t packetBuffer[KMaxPacketSize]; - int32_t length; + size_t length; int32_t channel; int64_t receiveTime; } VideoPacket; @@ -147,7 +147,7 @@ private: int sender_channel_; SsrcChannelMap* receive_channels_; webrtc::ViENetwork& _vieNetwork; - webrtc::ThreadWrapper& _thread; + rtc::scoped_ptr _thread; webrtc::EventWrapper& _event; webrtc::CriticalSectionWrapper& _crit; webrtc::CriticalSectionWrapper& _statCrit; diff --git a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/tb_video_channel.h b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/tb_video_channel.h index 0409cf3e1b..7d2557e4ad 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/tb_video_channel.h +++ b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/tb_video_channel.h @@ -11,7 +11,7 @@ #ifndef WEBRTC_VIDEO_ENGINE_MAIN_TEST_AUTOTEST_INTERFACE_TB_VIDEO_CHANNEL_H_ #define WEBRTC_VIDEO_ENGINE_MAIN_TEST_AUTOTEST_INTERFACE_TB_VIDEO_CHANNEL_H_ -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/video_engine/test/libvietest/include/tb_interfaces.h" namespace webrtc { @@ -44,7 +44,7 @@ class TbVideoChannel { private: TbInterfaces& ViE; - webrtc::scoped_ptr channel_transport_; + rtc::scoped_ptr channel_transport_; }; diff --git a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/vie_external_render_filter.h b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/vie_external_render_filter.h index 039a1fd0fb..057f6c8011 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/vie_external_render_filter.h +++ b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/vie_external_render_filter.h @@ -24,7 +24,7 @@ class ExternalRendererEffectFilter : public webrtc::ViEEffectFilter { explicit ExternalRendererEffectFilter(webrtc::ExternalRenderer* renderer) : width_(0), height_(0), renderer_(renderer) {} virtual ~ExternalRendererEffectFilter() {} - virtual int Transform(int size, + virtual int Transform(size_t size, unsigned char* frame_buffer, int64_t ntp_time_ms, unsigned int timestamp, diff --git a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/vie_fake_camera.h b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/vie_fake_camera.h index abc5d40cf4..afb2752a91 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/vie_fake_camera.h +++ b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/vie_fake_camera.h @@ -11,10 +11,10 @@ #define SRC_VIDEO_ENGINE_MAIN_TEST_AUTOTEST_HELPERS_VIE_FAKE_CAMERA_H_ #include +#include "webrtc/system_wrappers/interface/thread_wrapper.h" namespace webrtc { class ViECapture; -class ThreadWrapper; } class ViEFileCaptureDevice; @@ -43,7 +43,7 @@ class ViEFakeCamera { webrtc::ViECapture* capture_interface_; int capture_id_; - webrtc::ThreadWrapper* camera_thread_; + rtc::scoped_ptr camera_thread_; ViEFileCaptureDevice* file_capture_device_; }; diff --git a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/vie_to_file_renderer.h b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/vie_to_file_renderer.h index e23dad2ad4..d873cd7a6a 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/vie_to_file_renderer.h +++ b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/include/vie_to_file_renderer.h @@ -18,7 +18,7 @@ #include #include "webrtc/base/constructormagic.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/video_engine/include/vie_render.h" namespace webrtc { @@ -54,23 +54,29 @@ class ViEToFileRenderer: public webrtc::ExternalRenderer { bool SaveOutputFile(const std::string& prefix); // Implementation of ExternalRenderer: - int FrameSizeChange(unsigned int width, unsigned int height, - unsigned int number_of_streams) OVERRIDE; + int FrameSizeChange(unsigned int width, + unsigned int height, + unsigned int number_of_streams) override; int DeliverFrame(unsigned char* buffer, - int buffer_size, + size_t buffer_size, uint32_t time_stamp, int64_t ntp_time_ms, int64_t render_time, - void* handle) OVERRIDE; + void* handle) override; - bool IsTextureSupported() OVERRIDE; + int DeliverI420Frame(const webrtc::I420VideoFrame& webrtc_frame) override; + + bool IsTextureSupported() override; const std::string GetFullOutputPath() const; private: typedef std::list FrameQueue; + // Returns a frame with the specified |buffer_size|. Tries to avoid allocating + // new frames by reusing frames from |free_frame_queue_|. + test::Frame* NewFrame(size_t buffer_size); static bool RunRenderThread(void* obj); void ForgetOutputFile(); bool ProcessRenderQueue(); @@ -78,9 +84,9 @@ class ViEToFileRenderer: public webrtc::ExternalRenderer { FILE* output_file_; std::string output_path_; std::string output_filename_; - webrtc::scoped_ptr thread_; - webrtc::scoped_ptr frame_queue_cs_; - webrtc::scoped_ptr frame_render_event_; + rtc::scoped_ptr thread_; + rtc::scoped_ptr frame_queue_cs_; + rtc::scoped_ptr frame_render_event_; FrameQueue render_queue_; FrameQueue free_frame_queue_; }; diff --git a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/libvietest.gypi b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/libvietest.gypi index 33d0b0f734..603cd4b1ea 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/libvietest.gypi +++ b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/libvietest.gypi @@ -11,7 +11,8 @@ 'target_name': 'libvietest', 'type': 'static_library', 'dependencies': [ - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', + '<(webrtc_root)/common.gyp:webrtc_common', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', '<(DEPTH)/testing/gtest.gyp:gtest', '<(webrtc_root)/test/test.gyp:test_support', 'video_engine_core', diff --git a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/testbed/tb_I420_codec.cc b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/testbed/tb_I420_codec.cc index f807fd58a1..e9cefcf84d 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/testbed/tb_I420_codec.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/testbed/tb_I420_codec.cc @@ -46,14 +46,14 @@ int32_t TbI420Encoder::Release() return WEBRTC_VIDEO_CODEC_OK; } -int32_t TbI420Encoder::SetChannelParameters(uint32_t packetLoss, int rtt) { +int32_t TbI420Encoder::SetChannelParameters(uint32_t packetLoss, int64_t rtt) { _functionCalls.SetChannelParameters++; return WEBRTC_VIDEO_CODEC_OK; } int32_t TbI420Encoder::InitEncode(const webrtc::VideoCodec* inst, int32_t /*numberOfCores*/, - uint32_t /*maxPayloadSize */) + size_t /*maxPayloadSize */) { _functionCalls.InitEncode++; if (inst == NULL) @@ -105,9 +105,9 @@ int32_t TbI420Encoder::Encode( _encodedImage._timeStamp = inputImage.timestamp(); _encodedImage._encodedHeight = inputImage.height(); _encodedImage._encodedWidth = inputImage.width(); - unsigned int reqSize = webrtc::CalcBufferSize(webrtc::kI420, - _encodedImage._encodedWidth, - _encodedImage._encodedHeight); + size_t reqSize = webrtc::CalcBufferSize(webrtc::kI420, + _encodedImage._encodedWidth, + _encodedImage._encodedHeight); if (reqSize > _encodedImage._size) { @@ -132,7 +132,7 @@ int32_t TbI420Encoder::Encode( } _encodedImage._length = reqSize; - _encodedCompleteCallback->Encoded(_encodedImage); + _encodedCompleteCallback->Encoded(_encodedImage, NULL, NULL); return WEBRTC_VIDEO_CODEC_OK; } @@ -232,14 +232,14 @@ int32_t TbI420Decoder::Decode( } // Only send complete frames. - if (static_cast(inputImage._length) != - webrtc::CalcBufferSize(webrtc::kI420,_width,_height)) { + if (webrtc::CalcBufferSize(webrtc::kI420,_width,_height) != + inputImage._length) { return WEBRTC_VIDEO_CODEC_ERROR; } - int ret = ConvertToI420(webrtc::kI420, inputImage._buffer, 0, 0, - _width, _height, - 0, webrtc::kRotateNone, &_decodedImage); + int ret = + ConvertToI420(webrtc::kI420, inputImage._buffer, 0, 0, _width, _height, + 0, webrtc::kVideoRotation_0, &_decodedImage); if (ret < 0) return WEBRTC_VIDEO_CODEC_ERROR; diff --git a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/testbed/tb_external_transport.cc b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/testbed/tb_external_transport.cc index 7ccedc2f10..d406985ef4 100644 --- a/media/webrtc/trunk/webrtc/video_engine/test/libvietest/testbed/tb_external_transport.cc +++ b/media/webrtc/trunk/webrtc/video_engine/test/libvietest/testbed/tb_external_transport.cc @@ -25,7 +25,6 @@ #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/event_wrapper.h" -#include "webrtc/system_wrappers/interface/thread_wrapper.h" #include "webrtc/system_wrappers/interface/tick_util.h" #include "webrtc/video_engine/include/vie_network.h" @@ -33,9 +32,6 @@ #pragma warning(disable: 4355) // 'this' : used in base member initializer list #endif -const uint8_t kSenderReportPayloadType = 200; -const uint8_t kReceiverReportPayloadType = 201; - TbExternalTransport::TbExternalTransport( webrtc::ViENetwork& vieNetwork, int sender_channel, @@ -44,9 +40,8 @@ TbExternalTransport::TbExternalTransport( sender_channel_(sender_channel), receive_channels_(receive_channels), _vieNetwork(vieNetwork), - _thread(*webrtc::ThreadWrapper::CreateThread( - ViEExternalTransportRun, this, webrtc::kHighPriority, - "AutotestTransport")), + _thread(webrtc::ThreadWrapper::CreateThread( + ViEExternalTransportRun, this, "AutotestTransport")), _event(*webrtc::EventWrapper::Create()), _crit(*webrtc::CriticalSectionWrapper::CreateCriticalSection()), _statCrit(*webrtc::CriticalSectionWrapper::CreateCriticalSection()), @@ -79,20 +74,17 @@ TbExternalTransport::TbExternalTransport( previous_drop_(false) { srand((int) webrtc::TickTime::MicrosecondTimestamp()); - unsigned int tId = 0; memset(&network_parameters_, 0, sizeof(NetworkParameters)); - _thread.Start(tId); + _thread->Start(); + _thread->SetPriority(webrtc::kHighPriority); } TbExternalTransport::~TbExternalTransport() { - _thread.SetNotAlive(); _event.Set(); - if (_thread.Stop()) - { - delete &_thread; - delete &_event; - } + _thread->Stop(); + delete &_event; + for (std::list::iterator it = _rtpPackets.begin(); it != _rtpPackets.end(); ++it) { delete *it; @@ -107,7 +99,7 @@ TbExternalTransport::~TbExternalTransport() delete &_statCrit; } -int TbExternalTransport::SendPacket(int channel, const void *data, int len) +int TbExternalTransport::SendPacket(int channel, const void *data, size_t len) { // Parse timestamp from RTP header according to RFC 3550, section 5.1. uint8_t* ptr = (uint8_t*)data; @@ -137,7 +129,7 @@ int TbExternalTransport::SendPacket(int channel, const void *data, int len) ssrc += ptr[11]; if (ssrc != _SSRC) { - return len; // return len to avoid error in trace file + return static_cast(len); // avoid error in trace file } } if (_temporalLayers) { @@ -182,7 +174,7 @@ int TbExternalTransport::SendPacket(int channel, const void *data, int len) } if (_currentRelayLayer < TID) { - return len; // return len to avoid error in trace file + return static_cast(len); // avoid error in trace file } if (ptr[14] & 0x80) // 2 byte PID { @@ -227,10 +219,11 @@ int TbExternalTransport::SendPacket(int channel, const void *data, int len) _statCrit.Enter(); _dropCount++; _statCrit.Leave(); - return len; + return static_cast(len); } VideoPacket* newPacket = new VideoPacket(); + assert(len <= sizeof(newPacket->packetBuffer)); memcpy(newPacket->packetBuffer, data, len); if (_temporalLayers) @@ -266,7 +259,7 @@ int TbExternalTransport::SendPacket(int channel, const void *data, int len) _rtpPackets.push_back(newPacket); _event.Set(); _crit.Leave(); - return len; + return static_cast(len); } void TbExternalTransport::RegisterSendFrameCallback( @@ -285,13 +278,16 @@ void TbExternalTransport::SetTemporalToggle(unsigned char layers) _temporalLayers = layers; } -int TbExternalTransport::SendRTCPPacket(int channel, const void *data, int len) +int TbExternalTransport::SendRTCPPacket(int channel, + const void *data, + size_t len) { _statCrit.Enter(); _rtcpCount++; _statCrit.Leave(); VideoPacket* newPacket = new VideoPacket(); + assert(len <= sizeof(newPacket->packetBuffer)); memcpy(newPacket->packetBuffer, data, len); newPacket->length = len; newPacket->channel = channel; @@ -304,7 +300,7 @@ int TbExternalTransport::SendRTCPPacket(int channel, const void *data, int len) _rtcpPackets.push_back(newPacket); _event.Set(); _crit.Leave(); - return len; + return static_cast(len); } void TbExternalTransport::SetNetworkParameters( @@ -495,8 +491,10 @@ bool TbExternalTransport::ViEExternalTransportProcess() // Send to ViE if (packet) { - uint8_t pltype = static_cast(packet->packetBuffer[1]); - if (pltype == kSenderReportPayloadType) { + uint8_t packet_type = static_cast(packet->packetBuffer[1]); + const uint8_t kSenderReportPacketType = 200; + const uint8_t kReceiverReportPacketType = 201; + if (packet_type == kSenderReportPacketType) { // Sender report. if (receive_channels_) { for (SsrcChannelMap::iterator it = receive_channels_->begin(); @@ -510,7 +508,7 @@ bool TbExternalTransport::ViEExternalTransportProcess() packet->packetBuffer, packet->length); } - } else if (pltype == kReceiverReportPayloadType) { + } else if (packet_type == kReceiverReportPacketType) { // Receiver report. _vieNetwork.ReceivedRTCPPacket(sender_channel_, packet->packetBuffer, diff --git a/media/webrtc/trunk/webrtc/video_engine/video_engine_core.gypi b/media/webrtc/trunk/webrtc/video_engine/video_engine_core.gypi index 2bfc6536d8..4dd8614e73 100644 --- a/media/webrtc/trunk/webrtc/video_engine/video_engine_core.gypi +++ b/media/webrtc/trunk/webrtc/video_engine/video_engine_core.gypi @@ -12,6 +12,7 @@ 'target_name': 'video_engine_core', 'type': 'static_library', 'dependencies': [ + '<(webrtc_root)/common.gyp:webrtc_common', # common_video '<(webrtc_root)/common_video/common_video.gyp:common_video', @@ -31,7 +32,7 @@ '<(webrtc_root)/voice_engine/voice_engine.gyp:voice_engine', # system_wrappers - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', ], 'sources': [ # interface @@ -49,6 +50,8 @@ 'call_stats.h', 'encoder_state_feedback.h', 'overuse_frame_detector.h', + 'payload_router.h', + 'report_block_stats.h', 'stream_synchronization.h', 'vie_base_impl.h', 'vie_capture_impl.h', @@ -82,6 +85,8 @@ 'call_stats.cc', 'encoder_state_feedback.cc', 'overuse_frame_detector.cc', + 'payload_router.cc', + 'report_block_stats.cc', 'stream_synchronization.cc', 'vie_base_impl.cc', 'vie_capture_impl.cc', @@ -132,6 +137,8 @@ 'call_stats_unittest.cc', 'encoder_state_feedback_unittest.cc', 'overuse_frame_detector_unittest.cc', + 'payload_router_unittest.cc', + 'report_block_stats_unittest.cc', 'stream_synchronization_unittest.cc', 'vie_capturer_unittest.cc', 'vie_codec_unittest.cc', diff --git a/media/webrtc/trunk/webrtc/video_engine/video_engine_core_unittests.isolate b/media/webrtc/trunk/webrtc/video_engine/video_engine_core_unittests.isolate index b95d84c45c..c8d2fc9026 100644 --- a/media/webrtc/trunk/webrtc/video_engine/video_engine_core_unittests.isolate +++ b/media/webrtc/trunk/webrtc/video_engine/video_engine_core_unittests.isolate @@ -7,14 +7,6 @@ # be found in the AUTHORS file in the root of the source tree. { 'conditions': [ - ['OS=="android"', { - 'variables': { - 'files': [ - '<(DEPTH)/data/', - '<(DEPTH)/resources/', - ], - }, - }], ['OS=="linux" or OS=="mac" or OS=="win"', { 'variables': { 'command': [ diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_base_impl.cc b/media/webrtc/trunk/webrtc/video_engine/vie_base_impl.cc index 07546e9b6a..86b0d57a4b 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_base_impl.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_base_impl.cc @@ -124,6 +124,23 @@ int ViEBaseImpl::SetCpuOveruseOptions(int video_channel, return -1; } +void ViEBaseImpl::RegisterCpuOveruseMetricsObserver( + int video_channel, + CpuOveruseMetricsObserver* observer) { + ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); + ViEEncoder* vie_encoder = cs.Encoder(video_channel); + assert(vie_encoder); + + ViEInputManagerScoped is(*(shared_data_.input_manager())); + ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder); + assert(provider != NULL); + + ViECapturer* capturer = is.Capture(provider->Id()); + assert(capturer); + + capturer->RegisterCpuOveruseMetricsObserver(observer); +} + int ViEBaseImpl::GetCpuOveruseMetrics(int video_channel, CpuOveruseMetrics* metrics) { ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); @@ -173,12 +190,18 @@ int ViEBaseImpl::CreateChannel(int& video_channel, // NOLINT int ViEBaseImpl::CreateChannel(int& video_channel, // NOLINT int original_channel) { - return CreateChannel(video_channel, original_channel, true); + return CreateChannel(video_channel, original_channel, true, false); +} + +int ViEBaseImpl::CreateChannelWithoutDefaultEncoder( + int& video_channel, // NOLINT + int original_channel) { + return CreateChannel(video_channel, original_channel, true, true); } int ViEBaseImpl::CreateReceiveChannel(int& video_channel, // NOLINT int original_channel) { - return CreateChannel(video_channel, original_channel, false); + return CreateChannel(video_channel, original_channel, false, true); } int ViEBaseImpl::DeleteChannel(const int video_channel) { @@ -192,7 +215,7 @@ int ViEBaseImpl::DeleteChannel(const int video_channel) { // Deregister the ViEEncoder if no other channel is using it. ViEEncoder* vie_encoder = cs.Encoder(video_channel); - if (cs.ChannelUsingViEEncoder(video_channel) == false) { + if (!cs.ChannelUsingViEEncoder(video_channel)) { ViEInputManagerScoped is(*(shared_data_.input_manager())); ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder); if (provider) { @@ -333,7 +356,7 @@ int ViEBaseImpl::StopReceive(const int video_channel) { int ViEBaseImpl::GetVersion(char version[1024]) { assert(version != NULL); - strcpy(version, "VideoEngine 39"); + strcpy(version, "VideoEngine 42"); return 0; } @@ -342,16 +365,18 @@ int ViEBaseImpl::LastError() { } int ViEBaseImpl::CreateChannel(int& video_channel, // NOLINT - int original_channel, bool sender) { + int original_channel, + bool sender, + bool disable_default_encoder) { ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); if (!cs.Channel(original_channel)) { shared_data_.SetLastError(kViEBaseInvalidChannelId); return -1; } - if (shared_data_.channel_manager()->CreateChannel(&video_channel, - original_channel, - sender) == -1) { + if (shared_data_.channel_manager()->CreateChannel( + &video_channel, original_channel, sender, disable_default_encoder) == + -1) { video_channel = -1; shared_data_.SetLastError(kViEBaseChannelCreationFailed); return -1; @@ -362,4 +387,32 @@ int ViEBaseImpl::CreateChannel(int& video_channel, // NOLINT return 0; } +void ViEBaseImpl::RegisterSendStatisticsProxy( + int channel, + SendStatisticsProxy* send_statistics_proxy) { + LOG_F(LS_VERBOSE) << "RegisterSendStatisticsProxy on channel " << channel; + ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); + ViEChannel* vie_channel = cs.Channel(channel); + if (!vie_channel) { + shared_data_.SetLastError(kViEBaseInvalidChannelId); + return; + } + ViEEncoder* vie_encoder = cs.Encoder(channel); + assert(vie_encoder); + + vie_encoder->RegisterSendStatisticsProxy(send_statistics_proxy); +} + +void ViEBaseImpl::RegisterReceiveStatisticsProxy( + int channel, + ReceiveStatisticsProxy* receive_statistics_proxy) { + LOG_F(LS_VERBOSE) << "RegisterReceiveStatisticsProxy on channel " << channel; + ViEChannelManagerScoped cs(*(shared_data_.channel_manager())); + ViEChannel* vie_channel = cs.Channel(channel); + if (!vie_channel) { + shared_data_.SetLastError(kViEBaseInvalidChannelId); + return; + } + vie_channel->RegisterReceiveStatisticsProxy(receive_statistics_proxy); +} } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_base_impl.h b/media/webrtc/trunk/webrtc/video_engine/vie_base_impl.h index 199fb24240..9f92178462 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_base_impl.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_base_impl.h @@ -35,16 +35,22 @@ class ViEBaseImpl CpuOveruseObserver* observer); virtual int SetCpuOveruseOptions(int channel, const CpuOveruseOptions& options); + void RegisterCpuOveruseMetricsObserver( + int channel, + CpuOveruseMetricsObserver* observer) override; virtual int GetCpuOveruseMetrics(int channel, CpuOveruseMetrics* metrics); - virtual void RegisterSendSideDelayObserver(int channel, - SendSideDelayObserver* observer) OVERRIDE; + void RegisterSendSideDelayObserver(int channel, + SendSideDelayObserver* observer) override; virtual void SetLoadManager(CPULoadStateCallbackInvoker* aLoadManager); virtual int CreateChannel(int& video_channel); // NOLINT virtual int CreateChannel(int& video_channel, // NOLINT const Config* config); virtual int CreateChannel(int& video_channel, // NOLINT int original_channel); + virtual int CreateChannelWithoutDefaultEncoder(int& video_channel, // NOLINT + int original_channel); + virtual int CreateReceiveChannel(int& video_channel, // NOLINT int original_channel); virtual int DeleteChannel(const int video_channel); @@ -66,8 +72,14 @@ class ViEBaseImpl private: int CreateChannel(int& video_channel, int original_channel, // NOLINT - bool sender); + bool sender, bool disable_default_encoder); + void RegisterSendStatisticsProxy( + int channel, + SendStatisticsProxy* send_statistics_proxy) override; + void RegisterReceiveStatisticsProxy( + int channel, + ReceiveStatisticsProxy* receive_statistics_proxy) override; // ViEBaseImpl owns ViESharedData used by all interface implementations. ViESharedData shared_data_; }; diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_capture_impl.cc b/media/webrtc/trunk/webrtc/video_engine/vie_capture_impl.cc index 9581fb7f2c..aa330cc0d5 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_capture_impl.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_capture_impl.cc @@ -139,13 +139,6 @@ int ViECaptureImpl::ConnectCaptureDevice(const int capture_id, LOG(LS_INFO) << "Connect capture id " << capture_id << " to channel " << video_channel; - ViEInputManagerScoped is(*(shared_data_->input_manager())); - ViECapturer* vie_capture = is.Capture(capture_id); - if (!vie_capture) { - shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); - return -1; - } - ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEEncoder* vie_encoder = cs.Encoder(video_channel); if (!vie_encoder) { @@ -158,6 +151,13 @@ int ViECaptureImpl::ConnectCaptureDevice(const int capture_id, shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId); return -1; } + + ViEInputManagerScoped is(*(shared_data_->input_manager())); + ViECapturer* vie_capture = is.Capture(capture_id); + if (!vie_capture) { + shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); + return -1; + } // Check if the encoder already has a connected frame provider if (is.FrameProvider(vie_encoder) != NULL) { LOG(LS_ERROR) << "Channel already connected to capture device."; @@ -252,26 +252,10 @@ int ViECaptureImpl::StopCapture(const int capture_id) { return 0; } -int ViECaptureImpl::SetRotateCapturedFrames( - const int capture_id, - const RotateCapturedFrame rotation) { - int i_rotation = -1; - switch (rotation) { - case RotateCapturedFrame_0: - i_rotation = 0; - break; - case RotateCapturedFrame_90: - i_rotation = 90; - break; - case RotateCapturedFrame_180: - i_rotation = 180; - break; - case RotateCapturedFrame_270: - i_rotation = 270; - break; - } - LOG(LS_INFO) << "SetRotateCaptureFrames for " << capture_id - << ", rotation " << i_rotation; +int ViECaptureImpl::SetVideoRotation(const int capture_id, + const VideoRotation rotation) { + LOG(LS_INFO) << "SetRotateCaptureFrames for " << capture_id << ", rotation " + << static_cast(rotation); ViEInputManagerScoped is(*(shared_data_->input_manager())); ViECapturer* vie_capture = is.Capture(capture_id); @@ -279,7 +263,7 @@ int ViECaptureImpl::SetRotateCapturedFrames( shared_data_->SetLastError(kViECaptureDeviceDoesNotExist); return -1; } - if (vie_capture->SetRotateCapturedFrames(rotation) != 0) { + if (vie_capture->SetVideoRotation(rotation) != 0) { shared_data_->SetLastError(kViECaptureDeviceUnknownError); return -1; } @@ -367,7 +351,7 @@ int ViECaptureImpl::ShowCaptureSettingsDialogBox( } int ViECaptureImpl::GetOrientation(const char* unique_idUTF8, - RotateCapturedFrame& orientation) { + VideoRotation& orientation) { if (shared_data_->input_manager()->GetOrientation( unique_idUTF8, orientation) != 0) { diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_capture_impl.h b/media/webrtc/trunk/webrtc/video_engine/vie_capture_impl.h index 541f7a2473..99be9366b6 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_capture_impl.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_capture_impl.h @@ -47,8 +47,8 @@ class ViECaptureImpl const int capture_id, const CaptureCapability& capture_capability = CaptureCapability()); virtual int StopCapture(const int capture_id); - virtual int SetRotateCapturedFrames(const int capture_id, - const RotateCapturedFrame rotation); + virtual int SetVideoRotation(const int capture_id, + const VideoRotation rotation); virtual int SetCaptureDelay(const int capture_id, const unsigned int capture_delay_ms); virtual int NumberOfCapabilities(const char* unique_idUTF8, @@ -62,7 +62,7 @@ class ViECaptureImpl const char* dialog_title, void* parent_window = NULL, const unsigned int x = 200, const unsigned int y = 200); virtual int GetOrientation(const char* unique_idUTF8, - RotateCapturedFrame& orientation); + VideoRotation& orientation); virtual int EnableBrightnessAlarm(const int capture_id, const bool enable); virtual int RegisterObserver(const int capture_id, ViECaptureObserver& observer); diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_capturer.cc b/media/webrtc/trunk/webrtc/video_engine/vie_capturer.cc index e37102cd5d..7041b6b0fe 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_capturer.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_capturer.cc @@ -10,7 +10,6 @@ #include "webrtc/video_engine/vie_capturer.h" -#include "webrtc/common_video/interface/texture_video_frame.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/modules/interface/module_common_types.h" #include "webrtc/modules/utility/interface/process_thread.h" @@ -21,7 +20,7 @@ #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/event_wrapper.h" #include "webrtc/system_wrappers/interface/logging.h" -#include "webrtc/system_wrappers/interface/thread_wrapper.h" +#include "webrtc/system_wrappers/interface/tick_util.h" #include "webrtc/system_wrappers/interface/trace_event.h" #include "webrtc/video_engine/include/vie_image_process.h" #include "webrtc/video_engine/overuse_frame_detector.h" @@ -33,23 +32,52 @@ namespace webrtc { const int kThreadWaitTimeMs = 100; +class RegistrableCpuOveruseMetricsObserver : public CpuOveruseMetricsObserver { + public: + void CpuOveruseMetricsUpdated(const CpuOveruseMetrics& metrics) override { + rtc::CritScope lock(&crit_); + if (observer_) + observer_->CpuOveruseMetricsUpdated(metrics); + metrics_ = metrics; + } + + CpuOveruseMetrics GetCpuOveruseMetrics() const { + rtc::CritScope lock(&crit_); + return metrics_; + } + + void Set(CpuOveruseMetricsObserver* observer) { + rtc::CritScope lock(&crit_); + observer_ = observer; + } + + private: + mutable rtc::CriticalSection crit_; + CpuOveruseMetricsObserver* observer_ GUARDED_BY(crit_) = nullptr; + CpuOveruseMetrics metrics_ GUARDED_BY(crit_); +}; + ViECapturer::ViECapturer(int capture_id, int engine_id, const Config& config, ProcessThread& module_process_thread) : ViEFrameProviderBase(capture_id, engine_id), capture_cs_(CriticalSectionWrapper::CreateCriticalSection()), - deliver_cs_(CriticalSectionWrapper::CreateCriticalSection()), + effects_and_stats_cs_(CriticalSectionWrapper::CreateCriticalSection()), capture_module_(NULL), - external_capture_module_(NULL), + use_external_capture_(false), module_process_thread_(module_process_thread), capture_id_(capture_id), incoming_frame_cs_(CriticalSectionWrapper::CreateCriticalSection()), - capture_thread_(*ThreadWrapper::CreateThread(ViECaptureThreadFunction, - this, kHighPriority, - "ViECaptureThread")), + capture_thread_(ThreadWrapper::CreateThread( + ViECaptureThreadFunction, this, "ViECaptureThread")), capture_event_(*EventWrapper::Create()), deliver_event_(*EventWrapper::Create()), + stop_(0), + last_captured_timestamp_(0), + delta_ntp_internal_ms_( + Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() - + TickTime::MillisecondTimestamp()), effect_filter_(NULL), image_proc_module_(NULL), image_proc_module_ref_counter_(0), @@ -59,12 +87,13 @@ ViECapturer::ViECapturer(int capture_id, reported_brightness_level_(Normal), observer_cs_(CriticalSectionWrapper::CreateCriticalSection()), observer_(NULL), - overuse_detector_(new OveruseFrameDetector(Clock::GetRealTimeClock())), + cpu_overuse_metrics_observer_(new RegistrableCpuOveruseMetricsObserver()), + overuse_detector_( + new OveruseFrameDetector(Clock::GetRealTimeClock(), + cpu_overuse_metrics_observer_.get())), config_(config) { - unsigned int t_id = 0; - if (!capture_thread_.Start(t_id)) { - assert(false); - } + capture_thread_->Start(); + capture_thread_->SetPriority(kHighPriority); module_process_thread_.RegisterModule(overuse_detector_.get()); } @@ -72,12 +101,8 @@ ViECapturer::~ViECapturer() { module_process_thread_.DeRegisterModule(overuse_detector_.get()); // Stop the thread. - deliver_cs_->Enter(); - capture_cs_->Enter(); - capture_thread_.SetNotAlive(); + rtc::AtomicOps::Increment(&stop_); capture_event_.Set(); - capture_cs_->Leave(); - deliver_cs_->Leave(); // Stop the camera input. if (capture_module_) { @@ -86,14 +111,10 @@ ViECapturer::~ViECapturer() { capture_module_->Release(); capture_module_ = NULL; } - if (capture_thread_.Stop()) { - // Thread stopped. - delete &capture_thread_; - delete &capture_event_; - delete &deliver_event_; - } else { - assert(false); - } + + capture_thread_->Stop(); + delete &capture_event_; + delete &deliver_event_; if (image_proc_module_) { VideoProcessingModule::Destroy(image_proc_module_); @@ -125,10 +146,7 @@ int32_t ViECapturer::Init(VideoCaptureModule* capture_module) { capture_module_ = capture_module; capture_module_->RegisterCaptureDataCallback(*this); capture_module_->AddRef(); - if (module_process_thread_.RegisterModule(capture_module_) != 0) { - return -1; - } - + module_process_thread_.RegisterModule(capture_module_); return 0; } @@ -160,8 +178,9 @@ int32_t ViECapturer::Init(const char* device_unique_idUTF8, ViEModuleId(engine_id_, capture_id_), device_unique_idUTF8, type); #endif } else if (device_unique_idUTF8 == NULL) { - capture_module_ = VideoCaptureFactory::Create( - ViEModuleId(engine_id_, capture_id_), external_capture_module_); + use_external_capture_ = true; + // YYY: was ViEModuleId(engine_id_, capture_id_), external_capture_module_); + return 0; } else { capture_module_ = VideoCaptureFactory::Create( ViEModuleId(engine_id_, capture_id_), device_unique_idUTF8); @@ -171,14 +190,14 @@ int32_t ViECapturer::Init(const char* device_unique_idUTF8, } capture_module_->AddRef(); capture_module_->RegisterCaptureDataCallback(*this); - if (module_process_thread_.RegisterModule(capture_module_) != 0) { - return -1; - } + module_process_thread_.RegisterModule(capture_module_); return 0; } int ViECapturer::FrameCallbackChanged() { + if (use_external_capture_) + return -1; if (Started() && !CaptureCapabilityFixed()) { // Reconfigure the camera if a new size is required and the capture device // does not provide encoded frames. @@ -202,6 +221,8 @@ int ViECapturer::FrameCallbackChanged() { } int32_t ViECapturer::Start(const CaptureCapability& capture_capability) { + if (use_external_capture_) + return -1; int width; int height; int frame_rate; @@ -243,15 +264,21 @@ int32_t ViECapturer::Start(const CaptureCapability& capture_capability) { } int32_t ViECapturer::Stop() { + if (use_external_capture_) + return -1; requested_capability_ = CaptureCapability(); return capture_module_->StopCapture(); } bool ViECapturer::Started() { + if (use_external_capture_) + return false; return capture_module_->CaptureStarted(); } const char* ViECapturer::CurrentDeviceName() const { + if (use_external_capture_) + return ""; return capture_module_->CurrentDeviceName(); } @@ -263,114 +290,75 @@ void ViECapturer::SetCpuOveruseOptions(const CpuOveruseOptions& options) { overuse_detector_->SetOptions(options); } +void ViECapturer::RegisterCpuOveruseMetricsObserver( + CpuOveruseMetricsObserver* observer) { + cpu_overuse_metrics_observer_->Set(observer); +} + void ViECapturer::GetCpuOveruseMetrics(CpuOveruseMetrics* metrics) const { - overuse_detector_->GetCpuOveruseMetrics(metrics); + *metrics = cpu_overuse_metrics_observer_->GetCpuOveruseMetrics(); } int32_t ViECapturer::SetCaptureDelay(int32_t delay_ms) { + if (use_external_capture_) + return -1; capture_module_->SetCaptureDelay(delay_ms); return 0; } -int32_t ViECapturer::SetRotateCapturedFrames( - const RotateCapturedFrame rotation) { - VideoCaptureRotation converted_rotation = kCameraRotate0; - switch (rotation) { - case RotateCapturedFrame_0: - converted_rotation = kCameraRotate0; - break; - case RotateCapturedFrame_90: - converted_rotation = kCameraRotate90; - break; - case RotateCapturedFrame_180: - converted_rotation = kCameraRotate180; - break; - case RotateCapturedFrame_270: - converted_rotation = kCameraRotate270; - break; - } - return capture_module_->SetCaptureRotation(converted_rotation); +int32_t ViECapturer::SetVideoRotation(const VideoRotation rotation) { + if (use_external_capture_) + return -1; + return capture_module_->SetCaptureRotation(rotation); } -int ViECapturer::IncomingFrame(unsigned char* video_frame, - unsigned int video_frame_length, - uint16_t width, - uint16_t height, - RawVideoType video_type, - unsigned long long capture_time) { // NOLINT - if (!external_capture_module_) { - return -1; - } - VideoCaptureCapability capability; - capability.width = width; - capability.height = height; - capability.rawType = video_type; - return external_capture_module_->IncomingFrame(video_frame, - video_frame_length, - capability, capture_time); -} - -int ViECapturer::IncomingFrameI420(const ViEVideoFrameI420& video_frame, - unsigned long long capture_time) { // NOLINT - if (!external_capture_module_) { - return -1; - } - - int size_y = video_frame.height * video_frame.y_pitch; - int size_u = video_frame.u_pitch * ((video_frame.height + 1) / 2); - int size_v = video_frame.v_pitch * ((video_frame.height + 1) / 2); - CriticalSectionScoped cs(incoming_frame_cs_.get()); - int ret = incoming_frame_.CreateFrame(size_y, - video_frame.y_plane, - size_u, - video_frame.u_plane, - size_v, - video_frame.v_plane, - video_frame.width, - video_frame.height, - video_frame.y_pitch, - video_frame.u_pitch, - video_frame.v_pitch); - - if (ret < 0) { - LOG_F(LS_ERROR) << "Could not create I420Frame."; - return -1; - } - - return external_capture_module_->IncomingI420VideoFrame(&incoming_frame_, - capture_time); -} - -void ViECapturer::SwapFrame(I420VideoFrame* frame) { - external_capture_module_->IncomingI420VideoFrame(frame, - frame->render_time_ms()); - frame->set_timestamp(0); - frame->set_ntp_time_ms(0); - frame->set_render_time_ms(0); +void ViECapturer::IncomingFrame(const I420VideoFrame& frame) { + OnIncomingCapturedFrame(-1, frame); } void ViECapturer::OnIncomingCapturedFrame(const int32_t capture_id, - I420VideoFrame& video_frame) { - CriticalSectionScoped cs(capture_cs_.get()); - // Make sure we render this frame earlier since we know the render time set - // is slightly off since it's being set when the frame has been received from - // the camera, and not when the camera actually captured the frame. - video_frame.set_render_time_ms(video_frame.render_time_ms() - FrameDelay()); + const I420VideoFrame& video_frame) { + I420VideoFrame incoming_frame = video_frame; - overuse_detector_->FrameCaptured(video_frame.width(), - video_frame.height(), - video_frame.render_time_ms()); + if (incoming_frame.ntp_time_ms() != 0) { + // If a NTP time stamp is set, this is the time stamp we will use. + incoming_frame.set_render_time_ms( + incoming_frame.ntp_time_ms() - delta_ntp_internal_ms_); + } else { // NTP time stamp not set. + int64_t render_time = incoming_frame.render_time_ms() != 0 ? + incoming_frame.render_time_ms() : TickTime::MillisecondTimestamp(); + + // Make sure we render this frame earlier since we know the render time set + // is slightly off since it's being set when the frame was received + // from the camera, and not when the camera actually captured the frame. + render_time -= FrameDelay(); + incoming_frame.set_render_time_ms(render_time); + incoming_frame.set_ntp_time_ms( + render_time + delta_ntp_internal_ms_); + } + + // Convert NTP time, in ms, to RTP timestamp. + const int kMsToRtpTimestamp = 90; + incoming_frame.set_timestamp(kMsToRtpTimestamp * + static_cast(incoming_frame.ntp_time_ms())); + + CriticalSectionScoped cs(capture_cs_.get()); + if (incoming_frame.ntp_time_ms() <= last_captured_timestamp_) { + // We don't allow the same capture time for two frames, drop this one. + LOG(LS_WARNING) << "Same/old NTP timestamp for incoming frame. Dropping."; + return; + } + + captured_frame_.ShallowCopy(incoming_frame); + last_captured_timestamp_ = incoming_frame.ntp_time_ms(); + + overuse_detector_->FrameCaptured(captured_frame_.width(), + captured_frame_.height(), + captured_frame_.render_time_ms()); TRACE_EVENT_ASYNC_BEGIN1("webrtc", "Video", video_frame.render_time_ms(), "render_time", video_frame.render_time_ms()); - if (video_frame.native_handle() != NULL) { - captured_frame_.reset(video_frame.CloneFrame()); - } else { - if (captured_frame_ == NULL || captured_frame_->native_handle() != NULL) - captured_frame_.reset(new I420VideoFrame()); - captured_frame_->SwapFrame(&video_frame); - } capture_event_.Set(); } @@ -385,7 +373,7 @@ void ViECapturer::OnCaptureDelayChanged(const int32_t id, int32_t ViECapturer::RegisterEffectFilter( ViEEffectFilter* effect_filter) { - CriticalSectionScoped cs(deliver_cs_.get()); + CriticalSectionScoped cs(effects_and_stats_cs_.get()); if (effect_filter != NULL && effect_filter_ != NULL) { LOG_F(LS_ERROR) << "Effect filter already registered."; @@ -420,7 +408,7 @@ int32_t ViECapturer::DecImageProcRefCount() { } int32_t ViECapturer::EnableDeflickering(bool enable) { - CriticalSectionScoped cs(deliver_cs_.get()); + CriticalSectionScoped cs(effects_and_stats_cs_.get()); if (enable) { if (deflicker_frame_stats_) { return -1; @@ -441,7 +429,7 @@ int32_t ViECapturer::EnableDeflickering(bool enable) { } int32_t ViECapturer::EnableBrightnessAlarm(bool enable) { - CriticalSectionScoped cs(deliver_cs_.get()); + CriticalSectionScoped cs(effects_and_stats_cs_.get()); if (enable) { if (brightness_frame_stats_) { return -1; @@ -468,17 +456,24 @@ bool ViECapturer::ViECaptureThreadFunction(void* obj) { bool ViECapturer::ViECaptureProcess() { int64_t capture_time = -1; if (capture_event_.Wait(kThreadWaitTimeMs) == kEventSignaled) { + if (rtc::AtomicOps::Load(&stop_)) + return false; + overuse_detector_->FrameProcessingStarted(); int64_t encode_start_time = -1; - deliver_cs_->Enter(); - if (SwapCapturedAndDeliverFrameIfAvailable()) { - capture_time = deliver_frame_->render_time_ms(); - encode_start_time = Clock::GetRealTimeClock()->TimeInMilliseconds(); - DeliverI420Frame(deliver_frame_.get()); - if (deliver_frame_->native_handle() != NULL) - deliver_frame_.reset(); // Release the texture so it can be reused. + I420VideoFrame deliver_frame; + { + CriticalSectionScoped cs(capture_cs_.get()); + if (!captured_frame_.IsZeroSize()) { + deliver_frame = captured_frame_; + captured_frame_.Reset(); + } + } + if (!deliver_frame.IsZeroSize()) { + capture_time = deliver_frame.render_time_ms(); + encode_start_time = Clock::GetRealTimeClock()->TimeInMilliseconds(); + DeliverI420Frame(&deliver_frame); } - deliver_cs_->Leave(); if (current_brightness_level_ != reported_brightness_level_) { CriticalSectionScoped cs(observer_cs_.get()); if (observer_) { @@ -501,66 +496,57 @@ bool ViECapturer::ViECaptureProcess() { void ViECapturer::DeliverI420Frame(I420VideoFrame* video_frame) { if (video_frame->native_handle() != NULL) { - ViEFrameProviderBase::DeliverFrame(video_frame); + ViEFrameProviderBase::DeliverFrame(video_frame, std::vector()); return; } // Apply image enhancement and effect filter. - if (deflicker_frame_stats_) { - if (image_proc_module_->GetFrameStats(deflicker_frame_stats_, - *video_frame) == 0) { - image_proc_module_->Deflickering(video_frame, deflicker_frame_stats_); - } else { - LOG_F(LS_ERROR) << "Could not get frame stats."; - } - } - if (brightness_frame_stats_) { - if (image_proc_module_->GetFrameStats(brightness_frame_stats_, - *video_frame) == 0) { - int32_t brightness = image_proc_module_->BrightnessDetection( - *video_frame, *brightness_frame_stats_); - - switch (brightness) { - case VideoProcessingModule::kNoWarning: - current_brightness_level_ = Normal; - break; - case VideoProcessingModule::kDarkWarning: - current_brightness_level_ = Dark; - break; - case VideoProcessingModule::kBrightWarning: - current_brightness_level_ = Bright; - break; - default: - break; + { + CriticalSectionScoped cs(effects_and_stats_cs_.get()); + if (deflicker_frame_stats_) { + if (image_proc_module_->GetFrameStats(deflicker_frame_stats_, + *video_frame) == 0) { + image_proc_module_->Deflickering(video_frame, deflicker_frame_stats_); + } else { + LOG_F(LS_ERROR) << "Could not get frame stats."; } } - } - if (effect_filter_) { - unsigned int length = CalcBufferSize(kI420, - video_frame->width(), - video_frame->height()); - scoped_ptr video_buffer(new uint8_t[length]); - ExtractBuffer(*video_frame, length, video_buffer.get()); - effect_filter_->Transform(length, - video_buffer.get(), - video_frame->ntp_time_ms(), - video_frame->timestamp(), - video_frame->width(), - video_frame->height()); + if (brightness_frame_stats_) { + if (image_proc_module_->GetFrameStats(brightness_frame_stats_, + *video_frame) == 0) { + int32_t brightness = image_proc_module_->BrightnessDetection( + *video_frame, *brightness_frame_stats_); + + switch (brightness) { + case VideoProcessingModule::kNoWarning: + current_brightness_level_ = Normal; + break; + case VideoProcessingModule::kDarkWarning: + current_brightness_level_ = Dark; + break; + case VideoProcessingModule::kBrightWarning: + current_brightness_level_ = Bright; + break; + default: + break; + } + } + } + if (effect_filter_) { + size_t length = + CalcBufferSize(kI420, video_frame->width(), video_frame->height()); + rtc::scoped_ptr video_buffer(new uint8_t[length]); + ExtractBuffer(*video_frame, length, video_buffer.get()); + effect_filter_->Transform(length, + video_buffer.get(), + video_frame->ntp_time_ms(), + video_frame->timestamp(), + video_frame->width(), + video_frame->height()); + } } // Deliver the captured frame to all observers (channels, renderer or file). - ViEFrameProviderBase::DeliverFrame(video_frame); -} - -int ViECapturer::DeregisterFrameCallback( - const ViEFrameCallback* callbackObject) { - return ViEFrameProviderBase::DeregisterFrameCallback(callbackObject); -} - -bool ViECapturer::IsFrameCallbackRegistered( - const ViEFrameCallback* callbackObject) { - CriticalSectionScoped cs(provider_cs_.get()); - return ViEFrameProviderBase::IsFrameCallbackRegistered(callbackObject); + ViEFrameProviderBase::DeliverFrame(video_frame, std::vector()); } bool ViECapturer::CaptureCapabilityFixed() { @@ -614,24 +600,4 @@ void ViECapturer::OnNoPictureAlarm(const int32_t id, observer_->NoPictureAlarm(id, vie_alarm); } -bool ViECapturer::SwapCapturedAndDeliverFrameIfAvailable() { - CriticalSectionScoped cs(capture_cs_.get()); - if (captured_frame_ == NULL) - return false; - - if (captured_frame_->native_handle() != NULL) { - deliver_frame_.reset(captured_frame_.release()); - return true; - } - - if (captured_frame_->IsZeroSize()) - return false; - - if (deliver_frame_ == NULL) - deliver_frame_.reset(new I420VideoFrame()); - deliver_frame_->SwapFrame(captured_frame_.get()); - captured_frame_->ResetSize(); - return true; -} - } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_capturer.h b/media/webrtc/trunk/webrtc/video_engine/vie_capturer.h index 622e3e5732..ac97f56568 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_capturer.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_capturer.h @@ -13,6 +13,8 @@ #include +#include "webrtc/base/criticalsection.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/common_types.h" #include "webrtc/engine_configurations.h" @@ -20,7 +22,8 @@ #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" #include "webrtc/modules/video_coding/main/interface/video_coding.h" #include "webrtc/modules/video_processing/main/interface/video_processing.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" +#include "webrtc/system_wrappers/interface/thread_wrapper.h" #include "webrtc/typedefs.h" #include "webrtc/video_engine/include/vie_base.h" #include "webrtc/video_engine/include/vie_capture.h" @@ -36,10 +39,10 @@ class EventWrapper; class CpuOveruseObserver; class OveruseFrameDetector; class ProcessThread; -class ThreadWrapper; class ViEEffectFilter; class ViEEncoder; struct ViEPicture; +class RegistrableCpuOveruseMetricsObserver; class ViECapturer : public ViEFrameProviderBase, @@ -65,21 +68,9 @@ class ViECapturer // Implements ViEFrameProviderBase. int FrameCallbackChanged(); - virtual int DeregisterFrameCallback(const ViEFrameCallback* callbackObject); - bool IsFrameCallbackRegistered(const ViEFrameCallback* callbackObject); // Implements ExternalCapture. - virtual int IncomingFrame(unsigned char* video_frame, - unsigned int video_frame_length, - uint16_t width, - uint16_t height, - RawVideoType video_type, - unsigned long long capture_time = 0); // NOLINT - - virtual int IncomingFrameI420(const ViEVideoFrameI420& video_frame, - unsigned long long capture_time = 0); // NOLINT - - virtual void SwapFrame(I420VideoFrame* frame) OVERRIDE; + void IncomingFrame(const I420VideoFrame& frame) override; // Start/Stop. int32_t Start( @@ -91,7 +82,7 @@ class ViECapturer int32_t SetCaptureDelay(int32_t delay_ms); // Sets rotation of the incoming captured frame. - int32_t SetRotateCapturedFrames(const RotateCapturedFrame rotation); + int32_t SetVideoRotation(const VideoRotation rotation); // Effect filter. int32_t RegisterEffectFilter(ViEEffectFilter* effect_filter); @@ -108,6 +99,7 @@ class ViECapturer void RegisterCpuOveruseObserver(CpuOveruseObserver* observer); void SetCpuOveruseOptions(const CpuOveruseOptions& options); + void RegisterCpuOveruseMetricsObserver(CpuOveruseMetricsObserver* observer); void GetCpuOveruseMetrics(CpuOveruseMetrics* metrics) const; protected: @@ -122,7 +114,7 @@ class ViECapturer // Implements VideoCaptureDataCallback. virtual void OnIncomingCapturedFrame(const int32_t id, - I420VideoFrame& video_frame); + const I420VideoFrame& video_frame); virtual void OnCaptureDelayChanged(const int32_t id, const int32_t delay); @@ -146,48 +138,55 @@ class ViECapturer static bool ViECaptureThreadFunction(void* obj); bool ViECaptureProcess(); - void DeliverI420Frame(I420VideoFrame* video_frame); - void DeliverCodedFrame(VideoFrame* video_frame); - private: - bool SwapCapturedAndDeliverFrameIfAvailable(); + void DeliverI420Frame(I420VideoFrame* video_frame); - // Never take capture_cs_ before deliver_cs_! - scoped_ptr capture_cs_; - scoped_ptr deliver_cs_; + // Never take capture_cs_ before effects_and_stats_cs_! + rtc::scoped_ptr capture_cs_; + rtc::scoped_ptr effects_and_stats_cs_; VideoCaptureModule* capture_module_; - VideoCaptureExternal* external_capture_module_; + bool use_external_capture_; ProcessThread& module_process_thread_; const int capture_id_; // Frame used in IncomingFrameI420. - scoped_ptr incoming_frame_cs_; + rtc::scoped_ptr incoming_frame_cs_; I420VideoFrame incoming_frame_; // Capture thread. - ThreadWrapper& capture_thread_; + rtc::scoped_ptr capture_thread_; EventWrapper& capture_event_; EventWrapper& deliver_event_; - scoped_ptr captured_frame_; - scoped_ptr deliver_frame_; + volatile int stop_; + + I420VideoFrame captured_frame_ GUARDED_BY(capture_cs_.get()); + // Used to make sure incoming time stamp is increasing for every frame. + int64_t last_captured_timestamp_; + // Delta used for translating between NTP and internal timestamps. + const int64_t delta_ntp_internal_ms_; // Image processing. - ViEEffectFilter* effect_filter_; + ViEEffectFilter* effect_filter_ GUARDED_BY(effects_and_stats_cs_.get()); VideoProcessingModule* image_proc_module_; int image_proc_module_ref_counter_; - VideoProcessingModule::FrameStats* deflicker_frame_stats_; - VideoProcessingModule::FrameStats* brightness_frame_stats_; + VideoProcessingModule::FrameStats* deflicker_frame_stats_ + GUARDED_BY(effects_and_stats_cs_.get()); + VideoProcessingModule::FrameStats* brightness_frame_stats_ + GUARDED_BY(effects_and_stats_cs_.get()); Brightness current_brightness_level_; Brightness reported_brightness_level_; // Statistics observer. - scoped_ptr observer_cs_; + rtc::scoped_ptr observer_cs_; ViECaptureObserver* observer_ GUARDED_BY(observer_cs_.get()); CaptureCapability requested_capability_; - scoped_ptr overuse_detector_; + // Must be declared before overuse_detector_ where it's registered. + const rtc::scoped_ptr + cpu_overuse_metrics_observer_; + rtc::scoped_ptr overuse_detector_; const Config & config_; }; diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_capturer_unittest.cc b/media/webrtc/trunk/webrtc/video_engine/vie_capturer_unittest.cc index edaf13b54b..18aa49665f 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_capturer_unittest.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_capturer_unittest.cc @@ -16,15 +16,14 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/common.h" #include "webrtc/common_video/interface/native_handle.h" -#include "webrtc/common_video/interface/texture_video_frame.h" #include "webrtc/modules/utility/interface/mock/mock_process_thread.h" #include "webrtc/modules/video_capture/include/mock/mock_video_capture.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/event_wrapper.h" #include "webrtc/system_wrappers/interface/ref_count.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/scoped_vector.h" #include "webrtc/video_engine/mock/mock_vie_frame_provider_base.h" @@ -69,7 +68,7 @@ class ViECapturerTest : public ::testing::Test { virtual void SetUp() { EXPECT_CALL(*mock_capture_module_, RegisterCaptureDataCallback(_)) .WillRepeatedly(Invoke(this, &ViECapturerTest::SetCaptureDataCallback)); - EXPECT_CALL(*mock_frame_callback_, DeliverFrame(_, _, _, _)) + EXPECT_CALL(*mock_frame_callback_, DeliverFrame(_, _, _)) .WillRepeatedly( WithArg<1>(Invoke(this, &ViECapturerTest::AddOutputFrame))); @@ -81,6 +80,7 @@ class ViECapturerTest : public ::testing::Test { } virtual void TearDown() { + vie_capturer_->DeregisterFrameCallback(mock_frame_callback_.get()); // ViECapturer accesses |mock_process_thread_| in destructor and should // be deleted first. vie_capturer_.reset(); @@ -94,11 +94,10 @@ class ViECapturerTest : public ::testing::Test { data_callback_->OnIncomingCapturedFrame(0, *frame); } - void AddOutputFrame(I420VideoFrame* frame) { + void AddOutputFrame(const I420VideoFrame* frame) { if (frame->native_handle() == NULL) output_frame_ybuffers_.push_back(frame->buffer(kYPlane)); - // Clone the frames because ViECapturer owns the frames. - output_frames_.push_back(frame->CloneFrame()); + output_frames_.push_back(new I420VideoFrame(*frame)); output_frame_event_->Set(); } @@ -106,35 +105,87 @@ class ViECapturerTest : public ::testing::Test { EXPECT_EQ(kEventSignaled, output_frame_event_->Wait(FRAME_TIMEOUT_MS)); } - scoped_ptr mock_capture_module_; - scoped_ptr mock_process_thread_; - scoped_ptr mock_frame_callback_; + rtc::scoped_ptr mock_capture_module_; + rtc::scoped_ptr mock_process_thread_; + rtc::scoped_ptr mock_frame_callback_; // Used to send input capture frames to ViECapturer. VideoCaptureDataCallback* data_callback_; - scoped_ptr vie_capturer_; + rtc::scoped_ptr vie_capturer_; // Input capture frames of ViECapturer. ScopedVector input_frames_; // Indicate an output frame has arrived. - scoped_ptr output_frame_event_; + rtc::scoped_ptr output_frame_event_; // Output delivered frames of ViECaptuer. ScopedVector output_frames_; // The pointers of Y plane buffers of output frames. This is used to verify // the frame are swapped and not copied. - std::vector output_frame_ybuffers_; + std::vector output_frame_ybuffers_; }; +TEST_F(ViECapturerTest, DoesNotRetainHandleNorCopyBuffer) { + // Indicate an output frame has arrived. + rtc::scoped_ptr frame_destroyed_event(EventWrapper::Create()); + class TestBuffer : public webrtc::I420Buffer { + public: + TestBuffer(EventWrapper* event) : I420Buffer(5, 5), event_(event) {} + + private: + friend class rtc::RefCountedObject; + ~TestBuffer() override { event_->Set(); } + EventWrapper* event_; + }; + + I420VideoFrame frame( + new rtc::RefCountedObject(frame_destroyed_event.get()), 1, 1, + kVideoRotation_0); + + AddInputFrame(&frame); + WaitOutputFrame(); + + EXPECT_EQ(output_frames_[0]->video_frame_buffer().get(), + frame.video_frame_buffer().get()); + output_frames_.clear(); + frame.Reset(); + EXPECT_EQ(kEventSignaled, frame_destroyed_event->Wait(FRAME_TIMEOUT_MS)); +} + +TEST_F(ViECapturerTest, TestNtpTimeStampSetIfRenderTimeSet) { + input_frames_.push_back(CreateI420VideoFrame(static_cast(0))); + input_frames_[0]->set_render_time_ms(5); + input_frames_[0]->set_ntp_time_ms(0); + + AddInputFrame(input_frames_[0]); + WaitOutputFrame(); + EXPECT_GT(output_frames_[0]->ntp_time_ms(), + input_frames_[0]->render_time_ms()); +} + +TEST_F(ViECapturerTest, TestRtpTimeStampSet) { + input_frames_.push_back(CreateI420VideoFrame(static_cast(0))); + input_frames_[0]->set_render_time_ms(0); + input_frames_[0]->set_ntp_time_ms(1); + input_frames_[0]->set_timestamp(0); + + AddInputFrame(input_frames_[0]); + WaitOutputFrame(); + EXPECT_EQ(output_frames_[0]->timestamp(), + input_frames_[0]->ntp_time_ms() * 90); +} + TEST_F(ViECapturerTest, TestTextureFrames) { const int kNumFrame = 3; for (int i = 0 ; i < kNumFrame; ++i) { webrtc::RefCountImpl* handle = new webrtc::RefCountImpl(); - input_frames_.push_back(new TextureVideoFrame(handle, i, i, i, i)); + // Add one to |i| so that width/height > 0. + input_frames_.push_back( + new I420VideoFrame(handle, i + 1, i + 1, i + 1, i + 1)); AddInputFrame(input_frames_[i]); WaitOutputFrame(); } @@ -144,37 +195,30 @@ TEST_F(ViECapturerTest, TestTextureFrames) { TEST_F(ViECapturerTest, TestI420Frames) { const int kNumFrame = 4; - ScopedVector copied_input_frames; - std::vector ybuffer_pointers; + std::vector ybuffer_pointers; for (int i = 0; i < kNumFrame; ++i) { input_frames_.push_back(CreateI420VideoFrame(static_cast(i + 1))); - ybuffer_pointers.push_back(input_frames_[i]->buffer(kYPlane)); - // Copy input frames because the buffer data will be swapped. - copied_input_frames.push_back(input_frames_[i]->CloneFrame()); + const I420VideoFrame* const_input_frame = input_frames_[i]; + ybuffer_pointers.push_back(const_input_frame->buffer(kYPlane)); AddInputFrame(input_frames_[i]); WaitOutputFrame(); } - EXPECT_TRUE(EqualFramesVector(copied_input_frames, output_frames_)); - // Make sure the buffer is swapped and not copied. + EXPECT_TRUE(EqualFramesVector(input_frames_, output_frames_)); + // Make sure the buffer is not copied. for (int i = 0; i < kNumFrame; ++i) EXPECT_EQ(ybuffer_pointers[i], output_frame_ybuffers_[i]); - // The pipeline should be filled with frames with allocated buffers. Check - // the last input frame has the same allocated size after swapping. - EXPECT_EQ(input_frames_.back()->allocated_size(kYPlane), - copied_input_frames.back()->allocated_size(kYPlane)); } TEST_F(ViECapturerTest, TestI420FrameAfterTextureFrame) { webrtc::RefCountImpl* handle = new webrtc::RefCountImpl(); - input_frames_.push_back(new TextureVideoFrame(handle, 1, 1, 1, 1)); + input_frames_.push_back(new I420VideoFrame(handle, 1, 1, 1, 1)); AddInputFrame(input_frames_[0]); WaitOutputFrame(); - input_frames_.push_back(CreateI420VideoFrame(1)); - scoped_ptr copied_input_frame(input_frames_[1]->CloneFrame()); - AddInputFrame(copied_input_frame.get()); + input_frames_.push_back(CreateI420VideoFrame(2)); + AddInputFrame(input_frames_[1]); WaitOutputFrame(); EXPECT_TRUE(EqualFramesVector(input_frames_, output_frames_)); @@ -182,13 +226,12 @@ TEST_F(ViECapturerTest, TestI420FrameAfterTextureFrame) { TEST_F(ViECapturerTest, TestTextureFrameAfterI420Frame) { input_frames_.push_back(CreateI420VideoFrame(1)); - scoped_ptr copied_input_frame(input_frames_[0]->CloneFrame()); - AddInputFrame(copied_input_frame.get()); + AddInputFrame(input_frames_[0]); WaitOutputFrame(); webrtc::RefCountImpl* handle = new webrtc::RefCountImpl(); - input_frames_.push_back(new TextureVideoFrame(handle, 1, 1, 1, 1)); + input_frames_.push_back(new I420VideoFrame(handle, 1, 1, 2, 2)); AddInputFrame(input_frames_[1]); WaitOutputFrame(); @@ -207,7 +250,6 @@ bool EqualTextureFrames(const I420VideoFrame& frame1, return ((frame1.native_handle() == frame2.native_handle()) && (frame1.width() == frame2.width()) && (frame1.height() == frame2.height()) && - (frame1.timestamp() == frame2.timestamp()) && (frame1.render_time_ms() == frame2.render_time_ms())); } @@ -218,8 +260,6 @@ bool EqualBufferFrames(const I420VideoFrame& frame1, (frame1.stride(kYPlane) == frame2.stride(kYPlane)) && (frame1.stride(kUPlane) == frame2.stride(kUPlane)) && (frame1.stride(kVPlane) == frame2.stride(kVPlane)) && - (frame1.timestamp() == frame2.timestamp()) && - (frame1.ntp_time_ms() == frame2.ntp_time_ms()) && (frame1.render_time_ms() == frame2.render_time_ms()) && (frame1.allocated_size(kYPlane) == frame2.allocated_size(kYPlane)) && (frame1.allocated_size(kUPlane) == frame2.allocated_size(kUPlane)) && @@ -248,14 +288,11 @@ I420VideoFrame* CreateI420VideoFrame(uint8_t data) { const int width = 36; const int height = 24; const int kSizeY = width * height * 2; - const int kSizeUV = width * height; uint8_t buffer[kSizeY]; memset(buffer, data, kSizeY); frame->CreateFrame( - kSizeY, buffer, kSizeUV, buffer, kSizeUV, buffer, width, height, width, + buffer, buffer, buffer, width, height, width, width / 2, width / 2); - frame->set_timestamp(data); - frame->set_ntp_time_ms(data); frame->set_render_time_ms(data); return frame; } diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_channel.cc b/media/webrtc/trunk/webrtc/video_engine/vie_channel.cc index f311fe929a..514b793db2 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_channel.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_channel.cc @@ -13,10 +13,13 @@ #include #include +#include "webrtc/base/checks.h" #include "webrtc/common.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/experiments.h" +#include "webrtc/frame_callback.h" #include "webrtc/modules/pacing/include/paced_sender.h" +#include "webrtc/modules/pacing/include/packet_router.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" #include "webrtc/modules/utility/interface/process_thread.h" @@ -27,12 +30,14 @@ #include "webrtc/system_wrappers/interface/logging.h" #include "webrtc/system_wrappers/interface/metrics.h" #include "webrtc/system_wrappers/interface/thread_wrapper.h" +#include "webrtc/video/receive_statistics_proxy.h" #include "webrtc/video_engine/call_stats.h" #include "webrtc/video_engine/include/vie_codec.h" #include "webrtc/video_engine/include/vie_errors.h" #include "webrtc/video_engine/include/vie_image_process.h" #include "webrtc/video_engine/include/vie_rtp_rtcp.h" -#include "webrtc/frame_callback.h" +#include "webrtc/video_engine/payload_router.h" +#include "webrtc/video_engine/report_block_stats.h" #include "webrtc/video_engine/vie_defines.h" #include "webrtc/voice_engine/include/voe_rtp_rtcp.h" // for webrtc::SenderInfo @@ -43,50 +48,6 @@ const int kInvalidRtpExtensionId = 0; static const int kMaxTargetDelayMs = 10000; static const float kMaxIncompleteTimeMultiplier = 3.5f; -namespace { - -RTCPReportBlock AggregateReportBlocks( - const std::vector& report_blocks, - std::map* prev_report_blocks) { - int fraction_lost_sum = 0; - int fl_seq_num_sum = 0; - int jitter_sum = 0; - int number_of_report_blocks = 0; - RTCPReportBlock aggregate; - std::vector::const_iterator report_block = - report_blocks.begin(); - for (; report_block != report_blocks.end(); ++report_block) { - aggregate.cumulativeLost += report_block->cumulativeLost; - std::map::iterator prev_report_block = - prev_report_blocks->find(report_block->sourceSSRC); - if (prev_report_block != prev_report_blocks->end()) { - // Skip the first report block since we won't be able to get a correct - // weight for it. - int seq_num_diff = report_block->extendedHighSeqNum - - prev_report_block->second.extendedHighSeqNum; - if (seq_num_diff > 0) { - fraction_lost_sum += report_block->fractionLost * seq_num_diff; - fl_seq_num_sum += seq_num_diff; - } - } - jitter_sum += report_block->jitter; - ++number_of_report_blocks; - (*prev_report_blocks)[report_block->sourceSSRC] = *report_block; - } - if (fl_seq_num_sum > 0) { - aggregate.fractionLost = - (fraction_lost_sum + fl_seq_num_sum / 2) / fl_seq_num_sum; - } - if (number_of_report_blocks > 0) { - aggregate.jitter = - (jitter_sum + number_of_report_blocks / 2) / number_of_report_blocks; - } - // Not well defined for aggregated report blocks. - aggregate.extendedHighSeqNum = 0; - return aggregate; -} -} // namespace - // Helper class receiving statistics callbacks. class ChannelStatsObserver : public CallStatsObserver { public: @@ -94,10 +55,30 @@ class ChannelStatsObserver : public CallStatsObserver { virtual ~ChannelStatsObserver() {} // Implements StatsObserver. - virtual void OnRttUpdate(uint32_t rtt) { + virtual void OnRttUpdate(int64_t rtt) { owner_->OnRttUpdate(rtt); } + private: + ViEChannel* const owner_; +}; + +class ViEChannelProtectionCallback : public VCMProtectionCallback { + public: + ViEChannelProtectionCallback(ViEChannel* owner) : owner_(owner) {} + ~ViEChannelProtectionCallback() {} + + + int ProtectionRequest( + const FecProtectionParams* delta_fec_params, + const FecProtectionParams* key_fec_params, + uint32_t* sent_video_rate_bps, + uint32_t* sent_nack_rate_bps, + uint32_t* sent_fec_rate_bps) override { + return owner_->ProtectionRequest(delta_fec_params, key_fec_params, + sent_video_rate_bps, sent_nack_rate_bps, + sent_fec_rate_bps); + } private: ViEChannel* owner_; }; @@ -112,8 +93,9 @@ ViEChannel::ViEChannel(int32_t channel_id, RemoteBitrateEstimator* remote_bitrate_estimator, RtcpRttStats* rtt_stats, PacedSender* paced_sender, - RtpRtcp* default_rtp_rtcp, - bool sender) + PacketRouter* packet_router, + bool sender, + bool disable_default_encoder) : ViEFrameProviderBase(channel_id, engine_id), channel_id_(channel_id), engine_id_(engine_id), @@ -121,74 +103,65 @@ ViEChannel::ViEChannel(int32_t channel_id, num_socket_threads_(kViESocketThreads), callback_cs_(CriticalSectionWrapper::CreateCriticalSection()), rtp_rtcp_cs_(CriticalSectionWrapper::CreateCriticalSection()), - default_rtp_rtcp_(default_rtp_rtcp), - vcm_(VideoCodingModule::Create()), + send_payload_router_(new PayloadRouter()), + vcm_protection_callback_(new ViEChannelProtectionCallback(this)), + vcm_(VideoCodingModule::Create(nullptr)), vie_receiver_(channel_id, vcm_, remote_bitrate_estimator, this), vie_sender_(channel_id), vie_sync_(vcm_, this), stats_observer_(new ChannelStatsObserver(this)), + vcm_receive_stats_callback_(NULL), module_process_thread_(module_process_thread), codec_observer_(NULL), do_key_frame_callbackRequest_(false), rtp_observer_(NULL), - rtcp_observer_(NULL), intra_frame_observer_(intra_frame_observer), rtt_stats_(rtt_stats), paced_sender_(paced_sender), - pad_with_redundant_payloads_(false), + packet_router_(packet_router), bandwidth_observer_(bandwidth_observer), send_timestamp_extension_id_(kInvalidRtpExtensionId), absolute_send_time_extension_id_(kInvalidRtpExtensionId), + video_rotation_extension_id_(kInvalidRtpExtensionId), external_transport_(NULL), decoder_reset_(true), wait_for_key_frame_(false), - decode_thread_(NULL), effect_filter_(NULL), color_enhancement_(false), mtu_(0), sender_(sender), + disable_default_encoder_(disable_default_encoder), nack_history_size_sender_(kSendSidePacketHistorySize), max_nack_reordering_threshold_(kMaxPacketAgeToNack), pre_render_callback_(NULL), - start_ms_(Clock::GetRealTimeClock()->TimeInMilliseconds()) { - RtpRtcp::Configuration configuration; - configuration.id = ViEModuleId(engine_id, channel_id); - configuration.audio = false; - configuration.default_module = default_rtp_rtcp; - configuration.outgoing_transport = &vie_sender_; - configuration.rtcp_feedback = this; - configuration.intra_frame_callback = intra_frame_observer; - configuration.bandwidth_callback = bandwidth_observer; - configuration.rtt_stats = rtt_stats; + report_block_stats_sender_(new ReportBlockStats()), + report_block_stats_receiver_(new ReportBlockStats()) { + RtpRtcp::Configuration configuration = CreateRtpRtcpConfiguration(); configuration.remote_bitrate_estimator = remote_bitrate_estimator; - configuration.paced_sender = paced_sender; configuration.receive_statistics = vie_receiver_.GetReceiveStatistics(); - configuration.send_bitrate_observer = &send_bitrate_observer_; - configuration.send_frame_count_observer = &send_frame_count_observer_; - configuration.send_side_delay_observer = &send_side_delay_observer_; - rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(configuration)); vie_receiver_.SetRtpRtcpModule(rtp_rtcp_.get()); vcm_->SetNackSettings(kMaxNackListSize, max_nack_reordering_threshold_, 0); } int32_t ViEChannel::Init() { - if (module_process_thread_.RegisterModule( - vie_receiver_.GetReceiveStatistics()) != 0) { - return -1; - } + module_process_thread_.RegisterModule(vie_receiver_.GetReceiveStatistics()); + // RTP/RTCP initialization. - if (rtp_rtcp_->SetSendingMediaStatus(false) != 0) { - return -1; - } - if (module_process_thread_.RegisterModule(rtp_rtcp_.get()) != 0) { - return -1; - } + rtp_rtcp_->SetSendingMediaStatus(false); + module_process_thread_.RegisterModule(rtp_rtcp_.get()); + rtp_rtcp_->SetKeyFrameRequestMethod(kKeyFrameReqFirRtp); rtp_rtcp_->SetRTCPStatus(kRtcpCompound); if (paced_sender_) { rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_); } + if (sender_) { + packet_router_->AddRtpModule(rtp_rtcp_.get()); + std::list send_rtp_modules(1, rtp_rtcp_.get()); + send_payload_router_->SetSendingRtpModules(send_rtp_modules); + DCHECK(!send_payload_router_->active()); + } if (vcm_->InitializeReceiver() != 0) { return -1; } @@ -203,22 +176,25 @@ int32_t ViEChannel::Init() { vcm_->RegisterReceiveStatisticsCallback(this); vcm_->RegisterDecoderTimingCallback(this); vcm_->SetRenderDelay(kViEDefaultRenderDelayMs); - if (module_process_thread_.RegisterModule(vcm_) != 0) { - return -1; - } + + module_process_thread_.RegisterModule(vcm_); + module_process_thread_.RegisterModule(&vie_sync_); + #ifdef VIDEOCODEC_VP8 - VideoCodec video_codec; - if (vcm_->Codec(kVideoCodecVP8, &video_codec) == VCM_OK) { - rtp_rtcp_->RegisterSendPayload(video_codec); - // TODO(holmer): Can we call SetReceiveCodec() here instead? - if (!vie_receiver_.RegisterPayload(video_codec)) { - return -1; + if (!disable_default_encoder_) { + VideoCodec video_codec; + if (vcm_->Codec(kVideoCodecVP8, &video_codec) == VCM_OK) { + rtp_rtcp_->RegisterSendPayload(video_codec); + // TODO(holmer): Can we call SetReceiveCodec() here instead? + if (!vie_receiver_.RegisterPayload(video_codec)) { + return -1; + } + vcm_->RegisterReceiveCodec(&video_codec, number_of_cores_); + vcm_->RegisterSendCodec(&video_codec, number_of_cores_, + rtp_rtcp_->MaxDataPayloadLength()); + } else { + assert(false); } - vcm_->RegisterReceiveCodec(&video_codec, number_of_cores_); - vcm_->RegisterSendCodec(&video_codec, number_of_cores_, - rtp_rtcp_->MaxDataPayloadLength()); - } else { - assert(false); } #endif @@ -232,9 +208,12 @@ ViEChannel::~ViEChannel() { module_process_thread_.DeRegisterModule(rtp_rtcp_.get()); module_process_thread_.DeRegisterModule(vcm_); module_process_thread_.DeRegisterModule(&vie_sync_); + send_payload_router_->SetSendingRtpModules(std::list()); + packet_router_->RemoveRtpModule(rtp_rtcp_.get()); while (simulcast_rtp_rtcp_.size() > 0) { std::list::iterator it = simulcast_rtp_rtcp_.begin(); RtpRtcp* rtp_rtcp = *it; + packet_router_->RemoveRtpModule(rtp_rtcp); module_process_thread_.DeRegisterModule(rtp_rtcp); delete rtp_rtcp; simulcast_rtp_rtcp_.erase(it); @@ -252,51 +231,114 @@ ViEChannel::~ViEChannel() { } void ViEChannel::UpdateHistograms() { - const float kMinCallLengthInMinutes = 0.5f; - float elapsed_minutes = - (Clock::GetRealTimeClock()->TimeInMilliseconds() - start_ms_) / 60000.0f; - if (elapsed_minutes < kMinCallLengthInMinutes) { - return; - } - RtcpPacketTypeCounter rtcp_sent; - RtcpPacketTypeCounter rtcp_received; - GetRtcpPacketTypeCounters(&rtcp_sent, &rtcp_received); + int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds(); if (sender_) { - if (rtcp_received.nack_requests > 0) { - RTC_HISTOGRAM_PERCENTAGE( - "WebRTC.Video.UniqueNackRequestsReceivedInPercent", - rtcp_received.UniqueNackRequestsInPercent()); - } - RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.NackPacketsReceivedPerMinute", - rtcp_received.nack_packets / elapsed_minutes); - RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.FirPacketsReceivedPerMinute", - rtcp_received.fir_packets / elapsed_minutes); - RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PliPacketsReceivedPerMinute", - rtcp_received.pli_packets / elapsed_minutes); - } else if (vie_receiver_.GetRemoteSsrc() > 0) { - // Get receive stats if we are receiving packets, i.e. there is a remote - // ssrc. - if (rtcp_sent.nack_requests > 0) { - RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.UniqueNackRequestsSentInPercent", - rtcp_sent.UniqueNackRequestsInPercent()); - } - RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.NackPacketsSentPerMinute", - rtcp_sent.nack_packets / elapsed_minutes); - RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.FirPacketsSentPerMinute", - rtcp_sent.fir_packets / elapsed_minutes); - RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PliPacketsSentPerMinute", - rtcp_sent.pli_packets / elapsed_minutes); - - webrtc::VCMFrameCount frames; - if (vcm_->ReceivedFrameCount(frames) == VCM_OK) { - uint32_t total_frames = frames.numKeyFrames + frames.numDeltaFrames; - if (total_frames > 0) { - RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.KeyFramesReceivedInPermille", - static_cast((frames.numKeyFrames * 1000.0f / total_frames) + - 0.5f)); + RtcpPacketTypeCounter rtcp_counter; + GetSendRtcpPacketTypeCounter(&rtcp_counter); + int64_t elapsed_sec = rtcp_counter.TimeSinceFirstPacketInMs(now) / 1000; + if (elapsed_sec > metrics::kMinRunTimeInSeconds) { + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.NackPacketsReceivedPerMinute", + rtcp_counter.nack_packets * 60 / elapsed_sec); + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.FirPacketsReceivedPerMinute", + rtcp_counter.fir_packets * 60 / elapsed_sec); + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PliPacketsReceivedPerMinute", + rtcp_counter.pli_packets * 60 / elapsed_sec); + if (rtcp_counter.nack_requests > 0) { + RTC_HISTOGRAM_PERCENTAGE( + "WebRTC.Video.UniqueNackRequestsReceivedInPercent", + rtcp_counter.UniqueNackRequestsInPercent()); + } + int fraction_lost = report_block_stats_sender_->FractionLostInPercent(); + if (fraction_lost != -1) { + RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.SentPacketsLostInPercent", + fraction_lost); } } + } else if (vie_receiver_.GetRemoteSsrc() > 0) { + // Get receive stats if we are receiving packets, i.e. there is a remote + // ssrc. + RtcpPacketTypeCounter rtcp_counter; + GetReceiveRtcpPacketTypeCounter(&rtcp_counter); + int64_t elapsed_sec = rtcp_counter.TimeSinceFirstPacketInMs(now) / 1000; + if (elapsed_sec > metrics::kMinRunTimeInSeconds) { + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.NackPacketsSentPerMinute", + rtcp_counter.nack_packets * 60 / elapsed_sec); + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.FirPacketsSentPerMinute", + rtcp_counter.fir_packets * 60 / elapsed_sec); + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PliPacketsSentPerMinute", + rtcp_counter.pli_packets * 60 / elapsed_sec); + if (rtcp_counter.nack_requests > 0) { + RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.UniqueNackRequestsSentInPercent", + rtcp_counter.UniqueNackRequestsInPercent()); + } + int fraction_lost = report_block_stats_receiver_->FractionLostInPercent(); + if (fraction_lost != -1) { + RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.ReceivedPacketsLostInPercent", + fraction_lost); + } + } + + StreamDataCounters rtp; + StreamDataCounters rtx; + GetReceiveStreamDataCounters(&rtp, &rtx); + StreamDataCounters rtp_rtx = rtp; + rtp_rtx.Add(rtx); + elapsed_sec = rtp_rtx.TimeSinceFirstPacketInMs(now) / 1000; + if (elapsed_sec > metrics::kMinRunTimeInSeconds) { + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.BitrateReceivedInKbps", + rtp_rtx.transmitted.TotalBytes() * 8 / elapsed_sec / 1000); + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.MediaBitrateReceivedInKbps", + rtp.MediaPayloadBytes() * 8 / elapsed_sec / 1000); + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PaddingBitrateReceivedInKbps", + rtp_rtx.transmitted.padding_bytes * 8 / elapsed_sec / 1000); + RTC_HISTOGRAM_COUNTS_10000( + "WebRTC.Video.RetransmittedBitrateReceivedInKbps", + rtp_rtx.retransmitted.TotalBytes() * 8 / elapsed_sec / 1000); + uint32_t ssrc = 0; + if (vie_receiver_.GetRtxSsrc(&ssrc)) { + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtxBitrateReceivedInKbps", + rtx.transmitted.TotalBytes() * 8 / elapsed_sec / 1000); + } + if (vie_receiver_.IsFecEnabled()) { + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.FecBitrateReceivedInKbps", + rtp_rtx.fec.TotalBytes() * 8 / elapsed_sec / 1000); + } + } + } +} + +void ViEChannel::UpdateHistogramsAtStopSend() { + StreamDataCounters rtp; + StreamDataCounters rtx; + GetSendStreamDataCounters(&rtp, &rtx); + StreamDataCounters rtp_rtx = rtp; + rtp_rtx.Add(rtx); + + int64_t elapsed_sec = rtp_rtx.TimeSinceFirstPacketInMs( + Clock::GetRealTimeClock()->TimeInMilliseconds()) / 1000; + if (elapsed_sec < metrics::kMinRunTimeInSeconds) { + return; + } + RTC_HISTOGRAM_COUNTS_100000("WebRTC.Video.BitrateSentInKbps", + rtp_rtx.transmitted.TotalBytes() * 8 / elapsed_sec / 1000); + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.MediaBitrateSentInKbps", + rtp.MediaPayloadBytes() * 8 / elapsed_sec / 1000); + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PaddingBitrateSentInKbps", + rtp_rtx.transmitted.padding_bytes * 8 / elapsed_sec / 1000); + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RetransmittedBitrateSentInKbps", + rtp_rtx.retransmitted.TotalBytes() * 8 / elapsed_sec / 1000); + if (rtp_rtcp_->RtxSendStatus() != kRtxOff) { + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtxBitrateSentInKbps", + rtx.transmitted.TotalBytes() * 8 / elapsed_sec / 1000); + } + bool fec_enabled = false; + uint8_t pltype_red; + uint8_t pltype_fec; + rtp_rtcp_->GenericFECStatus(fec_enabled, pltype_red, pltype_fec); + if (fec_enabled) { + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.FecBitrateSentInKbps", + rtp_rtx.fec.TotalBytes() * 8 / elapsed_sec / 1000); } } @@ -319,6 +361,12 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec, // Stop and Start the RTP module -> trigger new SSRC, if an SSRC hasn't been // set explicitly. bool restart_rtp = false; + bool router_was_active = send_payload_router_->active(); + send_payload_router_->set_active(false); + send_payload_router_->SetSendingRtpModules(std::list()); + packet_router_->RemoveRtpModule(rtp_rtcp_.get()); + for (RtpRtcp* module : simulcast_rtp_rtcp_) + packet_router_->RemoveRtpModule(module); if (rtp_rtcp_->Sending() && new_stream) { restart_rtp = true; rtp_rtcp_->SetSendingStatus(false); @@ -334,154 +382,183 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec, uint8_t payload_type_fec; rtp_rtcp_->GenericFECStatus(fec_enabled, payload_type_red, payload_type_fec); - CriticalSectionScoped cs(rtp_rtcp_cs_.get()); + std::vector registered_modules; + std::vector deregistered_modules; + { + CriticalSectionScoped cs(rtp_rtcp_cs_.get()); - if (video_codec.numberOfSimulcastStreams > 0) { - // Set correct bitrate to base layer. - // Create our simulcast RTP modules. - int num_modules_to_add = video_codec.numberOfSimulcastStreams - - simulcast_rtp_rtcp_.size() - 1; - if (num_modules_to_add < 0) { - num_modules_to_add = 0; - } - - // Add back removed rtp modules. Order is important (allocate from front of - // removed modules) to preserve RTP settings such as SSRCs for simulcast - // streams. - std::list new_rtp_modules; - for (; removed_rtp_rtcp_.size() > 0 && num_modules_to_add > 0; - --num_modules_to_add) { - new_rtp_modules.push_back(removed_rtp_rtcp_.front()); - removed_rtp_rtcp_.pop_front(); - } - - for (int i = 0; i < num_modules_to_add; ++i) - new_rtp_modules.push_back(CreateRtpRtcpModule()); - - // Initialize newly added modules. - for (std::list::iterator it = new_rtp_modules.begin(); - it != new_rtp_modules.end(); - ++it) { - RtpRtcp* rtp_rtcp = *it; - - rtp_rtcp->SetRTCPStatus(rtp_rtcp_->RTCP()); - - if (rtp_rtcp_->StorePackets()) { - rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_); - } else if (paced_sender_) { - rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_); + if (video_codec.numberOfSimulcastStreams > 0) { + // Set correct bitrate to base layer. + // Create our simulcast RTP modules. + int num_modules_to_add = + video_codec.numberOfSimulcastStreams - simulcast_rtp_rtcp_.size() - 1; + if (num_modules_to_add < 0) { + num_modules_to_add = 0; } - if (fec_enabled) { - rtp_rtcp->SetGenericFECStatus( - fec_enabled, payload_type_red, payload_type_fec); + // Add back removed rtp modules. Order is important (allocate from front + // of removed modules) to preserve RTP settings such as SSRCs for + // simulcast streams. + std::list new_rtp_modules; + for (; removed_rtp_rtcp_.size() > 0 && num_modules_to_add > 0; + --num_modules_to_add) { + new_rtp_modules.push_back(removed_rtp_rtcp_.front()); + removed_rtp_rtcp_.pop_front(); } - rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending()); - rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia()); - int mode; - uint32_t ssrc; - int payload_type; - rtp_rtcp_->RTXSendStatus(&mode, &ssrc, &payload_type); - rtp_rtcp->SetRTXSendStatus(mode); - simulcast_rtp_rtcp_.push_back(rtp_rtcp); + for (int i = 0; i < num_modules_to_add; ++i) + new_rtp_modules.push_back(CreateRtpRtcpModule()); - // Silently ignore error. - module_process_thread_.RegisterModule(rtp_rtcp); - } + // Initialize newly added modules. + for (std::list::iterator it = new_rtp_modules.begin(); + it != new_rtp_modules.end(); ++it) { + RtpRtcp* rtp_rtcp = *it; - // Remove last in list if we have too many. - for (int j = simulcast_rtp_rtcp_.size(); - j > (video_codec.numberOfSimulcastStreams - 1); - j--) { - RtpRtcp* rtp_rtcp = simulcast_rtp_rtcp_.back(); - module_process_thread_.DeRegisterModule(rtp_rtcp); - rtp_rtcp->SetSendingStatus(false); - rtp_rtcp->SetSendingMediaStatus(false); - rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL); - rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL); - simulcast_rtp_rtcp_.pop_back(); - removed_rtp_rtcp_.push_front(rtp_rtcp); - } - uint8_t idx = 0; - // Configure all simulcast modules. - for (std::list::iterator it = simulcast_rtp_rtcp_.begin(); - it != simulcast_rtp_rtcp_.end(); - it++) { - idx++; - RtpRtcp* rtp_rtcp = *it; - rtp_rtcp->DeRegisterSendPayload(video_codec.plType); - if (rtp_rtcp->RegisterSendPayload(video_codec) != 0) { - return -1; - } - if (mtu_ != 0) { - rtp_rtcp->SetMaxTransferUnit(mtu_); - } - if (restart_rtp) { - rtp_rtcp->SetSendingStatus(true); - rtp_rtcp->SetSendingMediaStatus(true); - } - if (send_timestamp_extension_id_ != kInvalidRtpExtensionId) { - // Deregister in case the extension was previously enabled. - rtp_rtcp->DeregisterSendRtpHeaderExtension( - kRtpExtensionTransmissionTimeOffset); - if (rtp_rtcp->RegisterSendRtpHeaderExtension( - kRtpExtensionTransmissionTimeOffset, - send_timestamp_extension_id_) != 0) { + rtp_rtcp->SetRTCPStatus(rtp_rtcp_->RTCP()); + + if (rtp_rtcp_->StorePackets()) { + rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_); + } else if (paced_sender_) { + rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_); } - } else { - rtp_rtcp->DeregisterSendRtpHeaderExtension( - kRtpExtensionTransmissionTimeOffset); - } - if (absolute_send_time_extension_id_ != kInvalidRtpExtensionId) { - // Deregister in case the extension was previously enabled. - rtp_rtcp->DeregisterSendRtpHeaderExtension( - kRtpExtensionAbsoluteSendTime); - if (rtp_rtcp->RegisterSendRtpHeaderExtension( - kRtpExtensionAbsoluteSendTime, - absolute_send_time_extension_id_) != 0) { - } - } else { - rtp_rtcp->DeregisterSendRtpHeaderExtension( - kRtpExtensionAbsoluteSendTime); - } - rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback( - rtp_rtcp_->GetSendChannelRtcpStatisticsCallback()); - rtp_rtcp->RegisterSendChannelRtpStatisticsCallback( - rtp_rtcp_->GetSendChannelRtpStatisticsCallback()); - } - // |RegisterSimulcastRtpRtcpModules| resets all old weak pointers and old - // modules can be deleted after this step. - vie_receiver_.RegisterSimulcastRtpRtcpModules(simulcast_rtp_rtcp_); - } else { - while (!simulcast_rtp_rtcp_.empty()) { - RtpRtcp* rtp_rtcp = simulcast_rtp_rtcp_.back(); - module_process_thread_.DeRegisterModule(rtp_rtcp); - rtp_rtcp->SetSendingStatus(false); - rtp_rtcp->SetSendingMediaStatus(false); - rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL); - rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL); - simulcast_rtp_rtcp_.pop_back(); - removed_rtp_rtcp_.push_front(rtp_rtcp); - } - // Clear any previous modules. - vie_receiver_.RegisterSimulcastRtpRtcpModules(simulcast_rtp_rtcp_); - } - // Don't log this error, no way to check in advance if this pl_type is - // registered or not... - rtp_rtcp_->DeRegisterSendPayload(video_codec.plType); - if (rtp_rtcp_->RegisterSendPayload(video_codec) != 0) { - return -1; - } - if (restart_rtp) { - rtp_rtcp_->SetSendingStatus(true); - for (std::list::iterator it = simulcast_rtp_rtcp_.begin(); - it != simulcast_rtp_rtcp_.end(); ++it) { - (*it)->SetSendingStatus(true); - (*it)->SetSendingMediaStatus(true); + if (fec_enabled) { + rtp_rtcp->SetGenericFECStatus(fec_enabled, payload_type_red, + payload_type_fec); + } + rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending()); + rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia()); + rtp_rtcp->SetRtxSendStatus(rtp_rtcp_->RtxSendStatus()); + simulcast_rtp_rtcp_.push_back(rtp_rtcp); + + // Silently ignore error. + registered_modules.push_back(rtp_rtcp); + } + + // Remove last in list if we have too many. + for (int j = simulcast_rtp_rtcp_.size(); + j > (video_codec.numberOfSimulcastStreams - 1); j--) { + RtpRtcp* rtp_rtcp = simulcast_rtp_rtcp_.back(); + deregistered_modules.push_back(rtp_rtcp); + rtp_rtcp->SetSendingStatus(false); + rtp_rtcp->SetSendingMediaStatus(false); + rtp_rtcp->RegisterRtcpStatisticsCallback(NULL); + rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL); + simulcast_rtp_rtcp_.pop_back(); + removed_rtp_rtcp_.push_front(rtp_rtcp); + } + uint8_t idx = 0; + // Configure all simulcast modules. + for (std::list::iterator it = simulcast_rtp_rtcp_.begin(); + it != simulcast_rtp_rtcp_.end(); it++) { + idx++; + RtpRtcp* rtp_rtcp = *it; + rtp_rtcp->DeRegisterSendPayload(video_codec.plType); + if (rtp_rtcp->RegisterSendPayload(video_codec) != 0) { + return -1; + } + if (mtu_ != 0) { + rtp_rtcp->SetMaxTransferUnit(mtu_); + } + if (restart_rtp) { + rtp_rtcp->SetSendingStatus(true); + rtp_rtcp->SetSendingMediaStatus(true); + } + if (send_timestamp_extension_id_ != kInvalidRtpExtensionId) { + // Deregister in case the extension was previously enabled. + rtp_rtcp->DeregisterSendRtpHeaderExtension( + kRtpExtensionTransmissionTimeOffset); + if (rtp_rtcp->RegisterSendRtpHeaderExtension( + kRtpExtensionTransmissionTimeOffset, + send_timestamp_extension_id_) != 0) { + LOG(LS_WARNING) << "Register Transmission Time Offset failed"; + } + } else { + rtp_rtcp->DeregisterSendRtpHeaderExtension( + kRtpExtensionTransmissionTimeOffset); + } + if (absolute_send_time_extension_id_ != kInvalidRtpExtensionId) { + // Deregister in case the extension was previously enabled. + rtp_rtcp->DeregisterSendRtpHeaderExtension( + kRtpExtensionAbsoluteSendTime); + if (rtp_rtcp->RegisterSendRtpHeaderExtension( + kRtpExtensionAbsoluteSendTime, + absolute_send_time_extension_id_) != 0) { + LOG(LS_WARNING) << "Register Absolute Send Time failed"; + } + } else { + rtp_rtcp->DeregisterSendRtpHeaderExtension( + kRtpExtensionAbsoluteSendTime); + } + if (video_rotation_extension_id_ != kInvalidRtpExtensionId) { + // Deregister in case the extension was previously enabled. + rtp_rtcp->DeregisterSendRtpHeaderExtension( + kRtpExtensionVideoRotation); + if (rtp_rtcp->RegisterSendRtpHeaderExtension( + kRtpExtensionVideoRotation, video_rotation_extension_id_) != + 0) { + LOG(LS_WARNING) << "Register VideoRotation extension failed"; + } + } else { + rtp_rtcp->DeregisterSendRtpHeaderExtension( + kRtpExtensionVideoRotation); + } + rtp_rtcp->RegisterRtcpStatisticsCallback( + rtp_rtcp_->GetRtcpStatisticsCallback()); + rtp_rtcp->RegisterSendChannelRtpStatisticsCallback( + rtp_rtcp_->GetSendChannelRtpStatisticsCallback()); + } + // |RegisterSimulcastRtpRtcpModules| resets all old weak pointers and old + // modules can be deleted after this step. + vie_receiver_.RegisterSimulcastRtpRtcpModules(simulcast_rtp_rtcp_); + } else { + while (!simulcast_rtp_rtcp_.empty()) { + RtpRtcp* rtp_rtcp = simulcast_rtp_rtcp_.back(); + deregistered_modules.push_back(rtp_rtcp); + rtp_rtcp->SetSendingStatus(false); + rtp_rtcp->SetSendingMediaStatus(false); + rtp_rtcp->RegisterRtcpStatisticsCallback(NULL); + rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL); + simulcast_rtp_rtcp_.pop_back(); + removed_rtp_rtcp_.push_front(rtp_rtcp); + } + // Clear any previous modules. + vie_receiver_.RegisterSimulcastRtpRtcpModules(simulcast_rtp_rtcp_); } + + // Don't log this error, no way to check in advance if this pl_type is + // registered or not... + rtp_rtcp_->DeRegisterSendPayload(video_codec.plType); + if (rtp_rtcp_->RegisterSendPayload(video_codec) != 0) { + return -1; + } + if (restart_rtp) { + rtp_rtcp_->SetSendingStatus(true); + for (std::list::iterator it = simulcast_rtp_rtcp_.begin(); + it != simulcast_rtp_rtcp_.end(); ++it) { + (*it)->SetSendingStatus(true); + (*it)->SetSendingMediaStatus(true); + } + } + // Update the packet and payload routers with the sending RTP RTCP modules. + packet_router_->AddRtpModule(rtp_rtcp_.get()); + for (RtpRtcp* module : simulcast_rtp_rtcp_) + packet_router_->AddRtpModule(module); + + std::list active_send_modules; + active_send_modules.push_back(rtp_rtcp_.get()); + for (std::list::const_iterator cit = simulcast_rtp_rtcp_.begin(); + cit != simulcast_rtp_rtcp_.end(); ++cit) { + active_send_modules.push_back(*cit); + } + send_payload_router_->SetSendingRtpModules(active_send_modules); + if (router_was_active) + send_payload_router_->set_active(true); } + for (RtpRtcp* rtp_rtcp : registered_modules) + module_process_thread_.RegisterModule(rtp_rtcp); + for (RtpRtcp* rtp_rtcp : deregistered_modules) + module_process_thread_.DeRegisterModule(rtp_rtcp); return 0; } @@ -551,12 +628,9 @@ int32_t ViEChannel::DeRegisterExternalDecoder(const uint8_t pl_type) { int32_t ViEChannel::ReceiveCodecStatistics(uint32_t* num_key_frames, uint32_t* num_delta_frames) { - VCMFrameCount received_frames; - if (vcm_->ReceivedFrameCount(received_frames) != VCM_OK) { - return -1; - } - *num_key_frames = received_frames.numKeyFrames; - *num_delta_frames = received_frames.numDeltaFrames; + CriticalSectionScoped cs(callback_cs_.get()); + *num_key_frames = receive_frame_counts_.key_frames; + *num_delta_frames = receive_frame_counts_.delta_frames; return 0; } @@ -594,7 +668,7 @@ int32_t ViEChannel::SetSignalPacketLossStatus(bool enable, return 0; } -int32_t ViEChannel::SetRTCPMode(const RTCPMethod rtcp_mode) { +void ViEChannel::SetRTCPMode(const RTCPMethod rtcp_mode) { CriticalSectionScoped cs(rtp_rtcp_cs_.get()); for (std::list::iterator it = simulcast_rtp_rtcp_.begin(); it != simulcast_rtp_rtcp_.end(); @@ -602,12 +676,11 @@ int32_t ViEChannel::SetRTCPMode(const RTCPMethod rtcp_mode) { RtpRtcp* rtp_rtcp = *it; rtp_rtcp->SetRTCPStatus(rtcp_mode); } - return rtp_rtcp_->SetRTCPStatus(rtcp_mode); + rtp_rtcp_->SetRTCPStatus(rtcp_mode); } -int32_t ViEChannel::GetRTCPMode(RTCPMethod* rtcp_mode) { - *rtcp_mode = rtp_rtcp_->RTCP(); - return 0; +RTCPMethod ViEChannel::GetRTCPMode() const { + return rtp_rtcp_->RTCP(); } int32_t ViEChannel::SetNACKStatus(const bool enable) { @@ -679,6 +752,23 @@ int32_t ViEChannel::SetFECStatus(const bool enable, return ProcessFECRequest(enable, payload_typeRED, payload_typeFEC); } +bool ViEChannel::IsSendingFecEnabled() { + bool fec_enabled = false; + uint8_t pltype_red = 0; + uint8_t pltype_fec = 0; + rtp_rtcp_->GenericFECStatus(fec_enabled, pltype_red, pltype_fec); + if (fec_enabled) + return true; + + CriticalSectionScoped cs(rtp_rtcp_cs_.get()); + for (auto* module : simulcast_rtp_rtcp_) { + module->GenericFECStatus(fec_enabled, pltype_red, pltype_fec); + if (fec_enabled) + return true; + } + return false; +} + int32_t ViEChannel::ProcessFECRequest( const bool enable, const unsigned char payload_typeRED, @@ -728,9 +818,7 @@ int ViEChannel::SetSenderBufferingMode(int target_delay_ms) { nack_history_size_sender_ = kSendSidePacketHistorySize; } } - if (rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_) != 0) { - return -1; - } + rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_); return 0; } @@ -773,10 +861,8 @@ int32_t ViEChannel::SetKeyFrameRequestMethod( return rtp_rtcp_->SetKeyFrameRequestMethod(method); } -bool ViEChannel::EnableRemb(bool enable) { - if (rtp_rtcp_->SetREMBStatus(enable) != 0) - return false; - return true; +void ViEChannel::EnableRemb(bool enable) { + rtp_rtcp_->SetREMBStatus(enable); } int ViEChannel::SetSendTimestampOffsetStatus(bool enable, int id) { @@ -849,6 +935,37 @@ int ViEChannel::SetReceiveAbsoluteSendTimeStatus(bool enable, int id) { return vie_receiver_.SetReceiveAbsoluteSendTimeStatus(enable, id) ? 0 : -1; } +int ViEChannel::SetSendVideoRotationStatus(bool enable, int id) { + CriticalSectionScoped cs(rtp_rtcp_cs_.get()); + int error = 0; + if (enable) { + // Enable the extension, but disable possible old id to avoid errors. + video_rotation_extension_id_ = id; + rtp_rtcp_->DeregisterSendRtpHeaderExtension(kRtpExtensionVideoRotation); + error = rtp_rtcp_->RegisterSendRtpHeaderExtension( + kRtpExtensionVideoRotation, id); + for (std::list::iterator it = simulcast_rtp_rtcp_.begin(); + it != simulcast_rtp_rtcp_.end(); it++) { + (*it)->DeregisterSendRtpHeaderExtension(kRtpExtensionVideoRotation); + error |= + (*it)->RegisterSendRtpHeaderExtension(kRtpExtensionVideoRotation, id); + } + } else { + // Disable the extension. + video_rotation_extension_id_ = kInvalidRtpExtensionId; + rtp_rtcp_->DeregisterSendRtpHeaderExtension(kRtpExtensionVideoRotation); + for (std::list::iterator it = simulcast_rtp_rtcp_.begin(); + it != simulcast_rtp_rtcp_.end(); it++) { + (*it)->DeregisterSendRtpHeaderExtension(kRtpExtensionVideoRotation); + } + } + return error; +} + +int ViEChannel::SetReceiveVideoRotationStatus(bool enable, int id) { + return vie_receiver_.SetReceiveVideoRotationStatus(enable, id) ? 0 : -1; +} + void ViEChannel::SetRtcpXrRrtrStatus(bool enable) { CriticalSectionScoped cs(rtp_rtcp_cs_.get()); rtp_rtcp_->SetRtcpXrRrtrStatus(enable); @@ -859,12 +976,11 @@ void ViEChannel::SetTransmissionSmoothingStatus(bool enable) { paced_sender_->SetStatus(enable); } -int32_t ViEChannel::EnableTMMBR(const bool enable) { - return rtp_rtcp_->SetTMMBRStatus(enable); +void ViEChannel::EnableTMMBR(bool enable) { + rtp_rtcp_->SetTMMBRStatus(enable); } int32_t ViEChannel::EnableKeyFrameRequestCallback(const bool enable) { - CriticalSectionScoped cs(callback_cs_.get()); if (enable && !codec_observer_) { LOG(LS_ERROR) << "No ViECodecObserver set."; @@ -921,22 +1037,6 @@ int32_t ViEChannel::GetRemoteCSRC(uint32_t CSRCs[kRtpCsrcSize]) { return 0; } -void ViEChannel::SetPadWithRedundantPayloads(bool enable) { - { - CriticalSectionScoped cs(callback_cs_.get()); - pad_with_redundant_payloads_ = enable; - } - int mode; - uint32_t ssrc; - int payload_type; - rtp_rtcp_->RTXSendStatus(&mode, &ssrc, &payload_type); - if (mode != kRtxOff) { - // Since RTX was already enabled we have to reset it with payload-based - // padding on. - SetRtxSendStatus(true); - } -} - int ViEChannel::SetRtxSendPayloadType(int payload_type) { rtp_rtcp_->SetRtxSendPayloadType(payload_type); for (std::list::iterator it = simulcast_rtp_rtcp_.begin(); @@ -948,18 +1048,13 @@ int ViEChannel::SetRtxSendPayloadType(int payload_type) { } void ViEChannel::SetRtxSendStatus(bool enable) { - int rtx_settings = kRtxOff; - if (enable) { - CriticalSectionScoped cs(callback_cs_.get()); - rtx_settings = kRtxRetransmitted; - if (pad_with_redundant_payloads_) - rtx_settings |= kRtxRedundantPayloads; - } - rtp_rtcp_->SetRTXSendStatus(rtx_settings); + int rtx_settings = + enable ? kRtxRetransmitted | kRtxRedundantPayloads : kRtxOff; + rtp_rtcp_->SetRtxSendStatus(rtx_settings); CriticalSectionScoped cs(rtp_rtcp_cs_.get()); for (std::list::iterator it = simulcast_rtp_rtcp_.begin(); it != simulcast_rtp_rtcp_.end(); it++) { - (*it)->SetRTXSendStatus(rtx_settings); + (*it)->SetRtxSendStatus(rtx_settings); } } @@ -971,21 +1066,42 @@ int32_t ViEChannel::SetStartSequenceNumber(uint16_t sequence_number) { if (rtp_rtcp_->Sending()) { return -1; } - return rtp_rtcp_->SetSequenceNumber(sequence_number); + rtp_rtcp_->SetSequenceNumber(sequence_number); + return 0; } void ViEChannel::SetRtpStateForSsrc(uint32_t ssrc, const RtpState& rtp_state) { assert(!rtp_rtcp_->Sending()); - default_rtp_rtcp_->SetRtpStateForSsrc(ssrc, rtp_state); + if (rtp_rtcp_->SetRtpStateForSsrc(ssrc, rtp_state)) + return; + CriticalSectionScoped cs(rtp_rtcp_cs_.get()); + for (auto* module : simulcast_rtp_rtcp_) { + if (module->SetRtpStateForSsrc(ssrc, rtp_state)) + return; + } + for (auto* module : removed_rtp_rtcp_) { + if (module->SetRtpStateForSsrc(ssrc, rtp_state)) + return; + } } RtpState ViEChannel::GetRtpStateForSsrc(uint32_t ssrc) { assert(!rtp_rtcp_->Sending()); RtpState rtp_state; - if (!default_rtp_rtcp_->GetRtpStateForSsrc(ssrc, &rtp_state)) { - LOG(LS_ERROR) << "Couldn't get RTP state for ssrc: " << ssrc; + if (rtp_rtcp_->GetRtpStateForSsrc(ssrc, &rtp_state)) + return rtp_state; + + CriticalSectionScoped cs(rtp_rtcp_cs_.get()); + for (auto* module : simulcast_rtp_rtcp_) { + if (module->GetRtpStateForSsrc(ssrc, &rtp_state)) + return rtp_state; } + for (auto* module : removed_rtp_rtcp_) { + if (module->GetRtpStateForSsrc(ssrc, &rtp_state)) + return rtp_state; + } + LOG(LS_ERROR) << "Couldn't get RTP state for ssrc: " << ssrc; return rtp_state; } @@ -1015,20 +1131,6 @@ int32_t ViEChannel::RegisterRtpObserver(ViERTPObserver* observer) { return 0; } -int32_t ViEChannel::RegisterRtcpObserver(ViERTCPObserver* observer) { - CriticalSectionScoped cs(callback_cs_.get()); - if (observer) { - if (rtcp_observer_) { - LOG_F(LS_ERROR) << "Observer already registered."; - return -1; - } - rtcp_observer_ = observer; - } else { - rtcp_observer_ = NULL; - } - return 0; -} - int32_t ViEChannel::SendApplicationDefinedRTCPPacket( const uint8_t sub_type, uint32_t name, @@ -1065,7 +1167,7 @@ int32_t ViEChannel::GetRemoteRTCPReceiverInfo(uint32_t& NTPHigh, uint32_t* jitterSamples, uint16_t* fractionLost, uint32_t* cumulativeLost, - int32_t* rttMs) { + int32_t* rttMs) { // TODO: how do we do this for simulcast ? average for all // except cumulative_lost that is the sum ? // CriticalSectionScoped cs(rtp_rtcp_cs_.get()); @@ -1117,8 +1219,8 @@ int32_t ViEChannel::GetRemoteRTCPReceiverInfo(uint32_t& NTPHigh, *cumulativeLost = statistics->cumulativeLost; *jitterSamples = statistics->jitter; - uint16_t dummy; - uint16_t rtt = 0; + int64_t dummy; + int64_t rtt = 0; if (rtp_rtcp_->RTT(remote_ssrc, &rtt, &dummy, &dummy, &dummy) != 0) { LOG_F(LS_ERROR) << "failed to get RTT"; return -1; @@ -1131,7 +1233,7 @@ int32_t ViEChannel::GetSendRtcpStatistics(uint16_t* fraction_lost, uint32_t* cumulative_lost, uint32_t* extended_max, uint32_t* jitter_samples, - int32_t* rtt_ms) { + int64_t* rtt_ms) { // Aggregate the report blocks associated with streams sent on this channel. std::vector report_blocks; rtp_rtcp_->RemoteRTCPStat(&report_blocks); @@ -1162,19 +1264,17 @@ int32_t ViEChannel::GetSendRtcpStatistics(uint16_t* fraction_lost, remote_ssrc = report_blocks[0].remoteSSRC; } - RTCPReportBlock report; - if (report_blocks.size() > 1) - report = AggregateReportBlocks(report_blocks, &prev_report_blocks_); - else - report = report_blocks[0]; - + // TODO(asapersson): Change report_block_stats to not rely on + // GetSendRtcpStatistics to be called. + RTCPReportBlock report = + report_block_stats_sender_->AggregateAndStore(report_blocks); *fraction_lost = report.fractionLost; *cumulative_lost = report.cumulativeLost; *extended_max = report.extendedHighSeqNum; *jitter_samples = report.jitter; - uint16_t dummy; - uint16_t rtt = 0; + int64_t dummy; + int64_t rtt = 0; if (rtp_rtcp_->RTT(remote_ssrc, &rtt, &dummy, &dummy, &dummy) != 0) { return -1; } @@ -1184,12 +1284,12 @@ int32_t ViEChannel::GetSendRtcpStatistics(uint16_t* fraction_lost, void ViEChannel::RegisterSendChannelRtcpStatisticsCallback( RtcpStatisticsCallback* callback) { - rtp_rtcp_->RegisterSendChannelRtcpStatisticsCallback(callback); + rtp_rtcp_->RegisterRtcpStatisticsCallback(callback); CriticalSectionScoped cs(rtp_rtcp_cs_.get()); for (std::list::const_iterator it = simulcast_rtp_rtcp_.begin(); it != simulcast_rtp_rtcp_.end(); ++it) { - (*it)->RegisterSendChannelRtcpStatisticsCallback(callback); + (*it)->RegisterRtcpStatisticsCallback(callback); } } @@ -1200,7 +1300,7 @@ int32_t ViEChannel::GetReceivedRtcpStatistics(uint16_t* fraction_lost, uint32_t* cumulative_lost, uint32_t* extended_max, uint32_t* jitter_samples, - int32_t* rtt_ms) { + int64_t* rtt_ms) { uint32_t remote_ssrc = vie_receiver_.GetRemoteSsrc(); StreamStatistician* statistician = vie_receiver_.GetReceiveStatistics()->GetStatistician(remote_ssrc); @@ -1214,8 +1314,12 @@ int32_t ViEChannel::GetReceivedRtcpStatistics(uint16_t* fraction_lost, *extended_max = receive_stats.extended_max_sequence_number; *jitter_samples = receive_stats.jitter; - uint16_t dummy = 0; - uint16_t rtt = 0; + // TODO(asapersson): Change report_block_stats to not rely on + // GetReceivedRtcpStatistics to be called. + report_block_stats_receiver_->Store(receive_stats, remote_ssrc, 0); + + int64_t dummy = 0; + int64_t rtt = 0; rtp_rtcp_->RTT(remote_ssrc, &rtt, &dummy, &dummy, &dummy); *rtt_ms = rtt; return 0; @@ -1225,11 +1329,17 @@ void ViEChannel::RegisterReceiveChannelRtcpStatisticsCallback( RtcpStatisticsCallback* callback) { vie_receiver_.GetReceiveStatistics()->RegisterRtcpStatisticsCallback( callback); + rtp_rtcp_->RegisterRtcpStatisticsCallback(callback); } -int32_t ViEChannel::GetRtpStatistics(uint32_t* bytes_sent, +void ViEChannel::RegisterRtcpPacketTypeCounterObserver( + RtcpPacketTypeCounterObserver* observer) { + rtcp_packet_type_counter_observer_.Set(observer); +} + +int32_t ViEChannel::GetRtpStatistics(size_t* bytes_sent, uint32_t* packets_sent, - uint32_t* bytes_received, + size_t* bytes_received, uint32_t* packets_received) const { StreamStatistician* statistician = vie_receiver_.GetReceiveStatistics()-> GetStatistician(vie_receiver_.GetRemoteSsrc()); @@ -1244,7 +1354,7 @@ int32_t ViEChannel::GetRtpStatistics(uint32_t* bytes_sent, for (std::list::const_iterator it = simulcast_rtp_rtcp_.begin(); it != simulcast_rtp_rtcp_.end(); it++) { - uint32_t bytes_sent_temp = 0; + size_t bytes_sent_temp = 0; uint32_t packets_sent_temp = 0; RtpRtcp* rtp_rtcp = *it; rtp_rtcp->DataCountersRTP(&bytes_sent_temp, &packets_sent_temp); @@ -1253,7 +1363,7 @@ int32_t ViEChannel::GetRtpStatistics(uint32_t* bytes_sent, } for (std::list::const_iterator it = removed_rtp_rtcp_.begin(); it != removed_rtp_rtcp_.end(); ++it) { - uint32_t bytes_sent_temp = 0; + size_t bytes_sent_temp = 0; uint32_t packets_sent_temp = 0; RtpRtcp* rtp_rtcp = *it; rtp_rtcp->DataCountersRTP(&bytes_sent_temp, &packets_sent_temp); @@ -1263,6 +1373,48 @@ int32_t ViEChannel::GetRtpStatistics(uint32_t* bytes_sent, return 0; } +void ViEChannel::GetSendStreamDataCounters( + StreamDataCounters* rtp_counters, + StreamDataCounters* rtx_counters) const { + rtp_rtcp_->GetSendStreamDataCounters(rtp_counters, rtx_counters); + CriticalSectionScoped cs(rtp_rtcp_cs_.get()); + for (std::list::const_iterator it = simulcast_rtp_rtcp_.begin(); + it != simulcast_rtp_rtcp_.end(); + it++) { + StreamDataCounters rtp_data; + StreamDataCounters rtx_data; + (*it)->GetSendStreamDataCounters(&rtp_data, &rtx_data); + rtp_counters->Add(rtp_data); + rtx_counters->Add(rtx_data); + } + for (std::list::const_iterator it = removed_rtp_rtcp_.begin(); + it != removed_rtp_rtcp_.end(); ++it) { + StreamDataCounters rtp_data; + StreamDataCounters rtx_data; + (*it)->GetSendStreamDataCounters(&rtp_data, &rtx_data); + rtp_counters->Add(rtp_data); + rtx_counters->Add(rtx_data); + } +} + +void ViEChannel::GetReceiveStreamDataCounters( + StreamDataCounters* rtp_counters, + StreamDataCounters* rtx_counters) const { + StreamStatistician* statistician = vie_receiver_.GetReceiveStatistics()-> + GetStatistician(vie_receiver_.GetRemoteSsrc()); + if (statistician) { + statistician->GetReceiveStreamDataCounters(rtp_counters); + } + uint32_t rtx_ssrc = 0; + if (vie_receiver_.GetRtxSsrc(&rtx_ssrc)) { + StreamStatistician* statistician = + vie_receiver_.GetReceiveStatistics()->GetStatistician(rtx_ssrc); + if (statistician) { + statistician->GetReceiveStreamDataCounters(rtx_counters); + } + } +} + void ViEChannel::RegisterSendChannelRtpStatisticsCallback( StreamDataCountersCallback* callback) { rtp_rtcp_->RegisterSendChannelRtpStatisticsCallback(callback); @@ -1281,28 +1433,35 @@ void ViEChannel::RegisterReceiveChannelRtpStatisticsCallback( vie_receiver_.GetReceiveStatistics()->RegisterRtpStatisticsCallback(callback); } -void ViEChannel::GetRtcpPacketTypeCounters( - RtcpPacketTypeCounter* packets_sent, - RtcpPacketTypeCounter* packets_received) const { - rtp_rtcp_->GetRtcpPacketTypeCounters(packets_sent, packets_received); +void ViEChannel::GetSendRtcpPacketTypeCounter( + RtcpPacketTypeCounter* packet_counter) const { + std::map counter_map = + rtcp_packet_type_counter_observer_.GetPacketTypeCounterMap(); + + RtcpPacketTypeCounter counter; + counter.Add(counter_map[rtp_rtcp_->SSRC()]); CriticalSectionScoped cs(rtp_rtcp_cs_.get()); for (std::list::const_iterator it = simulcast_rtp_rtcp_.begin(); it != simulcast_rtp_rtcp_.end(); ++it) { - RtcpPacketTypeCounter sent; - RtcpPacketTypeCounter received; - (*it)->GetRtcpPacketTypeCounters(&sent, &received); - packets_sent->Add(sent); - packets_received->Add(received); + counter.Add(counter_map[(*it)->SSRC()]); } for (std::list::const_iterator it = removed_rtp_rtcp_.begin(); it != removed_rtp_rtcp_.end(); ++it) { - RtcpPacketTypeCounter sent; - RtcpPacketTypeCounter received; - (*it)->GetRtcpPacketTypeCounters(&sent, &received); - packets_sent->Add(sent); - packets_received->Add(received); + counter.Add(counter_map[(*it)->SSRC()]); } + *packet_counter = counter; +} + +void ViEChannel::GetReceiveRtcpPacketTypeCounter( + RtcpPacketTypeCounter* packet_counter) const { + std::map counter_map = + rtcp_packet_type_counter_observer_.GetPacketTypeCounterMap(); + + RtcpPacketTypeCounter counter; + counter.Add(counter_map[vie_receiver_.GetRemoteSsrc()]); + + *packet_counter = counter; } int32_t ViEChannel::GetRemoteRTCPSenderInfo(SenderInfo* sender_info) const { @@ -1384,11 +1543,6 @@ void ViEChannel::RegisterSendBitrateObserver( send_bitrate_observer_.Set(observer); } -void ViEChannel::GetReceiveBandwidthEstimatorStats( - ReceiveBandwidthEstimatorStats* output) const { - vie_receiver_.GetReceiveBandwidthEstimatorStats(output); -} - int32_t ViEChannel::StartRTPDump(const char file_nameUTF8[1024], RTPDirections direction) { if (direction == kRtpIncoming) { @@ -1428,11 +1582,14 @@ int32_t ViEChannel::StartSend() { rtp_rtcp->SetSendingMediaStatus(true); rtp_rtcp->SetSendingStatus(true); } + send_payload_router_->set_active(true); vie_receiver_.StartRTCPReceive(); return 0; } int32_t ViEChannel::StopSend() { + UpdateHistogramsAtStopSend(); + send_payload_router_->set_active(false); CriticalSectionScoped cs(rtp_rtcp_cs_.get()); rtp_rtcp_->SetSendingMediaStatus(false); for (std::list::iterator it = simulcast_rtp_rtcp_.begin(); @@ -1466,7 +1623,6 @@ bool ViEChannel::Sending() { } int32_t ViEChannel::StartReceive() { - CriticalSectionScoped cs(callback_cs_.get()); if (StartDecodeThread() != 0) { vie_receiver_.StopReceive(); return -1; @@ -1514,7 +1670,7 @@ int32_t ViEChannel::DeregisterSendTransport() { } int32_t ViEChannel::ReceivedRTPPacket( - const void* rtp_packet, const int32_t rtp_packet_length, + const void* rtp_packet, const size_t rtp_packet_length, const PacketTime& packet_time) { { CriticalSectionScoped cs(callback_cs_.get()); @@ -1527,7 +1683,7 @@ int32_t ViEChannel::ReceivedRTPPacket( } int32_t ViEChannel::ReceivedRTCPPacket( - const void* rtcp_packet, const int32_t rtcp_packet_length) { + const void* rtcp_packet, const size_t rtcp_packet_length) { { CriticalSectionScoped cs(callback_cs_.get()); if (!external_transport_) { @@ -1566,6 +1722,14 @@ RtpRtcp* ViEChannel::rtp_rtcp() { return rtp_rtcp_.get(); } +scoped_refptr ViEChannel::send_payload_router() { + return send_payload_router_; +} + +VCMProtectionCallback* ViEChannel::vcm_protection_callback() { + return vcm_protection_callback_.get(); +} + CallStatsObserver* ViEChannel::GetStatsObserver() { return stats_observer_.get(); } @@ -1594,10 +1758,9 @@ int32_t ViEChannel::FrameToRender( if (pre_render_callback_ != NULL) pre_render_callback_->FrameCallback(&video_frame); if (effect_filter_) { - unsigned int length = CalcBufferSize(kI420, - video_frame.width(), - video_frame.height()); - scoped_ptr video_buffer(new uint8_t[length]); + size_t length = + CalcBufferSize(kI420, video_frame.width(), video_frame.height()); + rtc::scoped_ptr video_buffer(new uint8_t[length]); ExtractBuffer(video_frame, length, video_buffer.get()); effect_filter_->Transform(length, video_buffer.get(), @@ -1617,7 +1780,9 @@ int32_t ViEChannel::FrameToRender( arr_ofCSRC[0] = vie_receiver_.GetRemoteSsrc(); no_of_csrcs = 1; } - DeliverFrame(&video_frame, no_of_csrcs, arr_ofCSRC); + std::vector csrcs(arr_ofCSRC, arr_ofCSRC + no_of_csrcs); + DeliverFrame(&video_frame, csrcs); + return 0; } @@ -1631,13 +1796,23 @@ void ViEChannel::IncomingCodecChanged(const VideoCodec& codec) { receive_codec_ = codec; } -int32_t ViEChannel::OnReceiveStatisticsUpdate(const uint32_t bit_rate, - const uint32_t frame_rate) { +void ViEChannel::OnReceiveRatesUpdated(uint32_t bit_rate, uint32_t frame_rate) { CriticalSectionScoped cs(callback_cs_.get()); - if (codec_observer_) { + if (codec_observer_) codec_observer_->IncomingRate(channel_id_, frame_rate, bit_rate); - } - return 0; +} + +void ViEChannel::OnDiscardedPacketsUpdated(int discarded_packets) { + CriticalSectionScoped cs(callback_cs_.get()); + if (vcm_receive_stats_callback_ != NULL) + vcm_receive_stats_callback_->OnDiscardedPacketsUpdated(discarded_packets); +} + +void ViEChannel::OnFrameCountsUpdated(const FrameCounts& frame_counts) { + CriticalSectionScoped cs(callback_cs_.get()); + receive_frame_counts_ = frame_counts; + if (vcm_receive_stats_callback_ != NULL) + vcm_receive_stats_callback_->OnFrameCountsUpdated(frame_counts); } void ViEChannel::OnDecoderTiming(int decode_ms, @@ -1694,14 +1869,40 @@ bool ViEChannel::ChannelDecodeThreadFunction(void* obj) { } bool ViEChannel::ChannelDecodeProcess() { + // TODO(pbos): Make sure the decoder thread doesn't run for send-only + // channels. vcm_->Decode(kMaxDecodeWaitTimeMs); return true; } -void ViEChannel::OnRttUpdate(uint32_t rtt) { +void ViEChannel::OnRttUpdate(int64_t rtt) { vcm_->SetReceiveChannelParameters(rtt); } +int ViEChannel::ProtectionRequest(const FecProtectionParams* delta_fec_params, + const FecProtectionParams* key_fec_params, + uint32_t* video_rate_bps, + uint32_t* nack_rate_bps, + uint32_t* fec_rate_bps) { + uint32_t not_used = 0; + rtp_rtcp_->SetFecParameters(delta_fec_params, key_fec_params); + rtp_rtcp_->BitrateSent(¬_used, video_rate_bps, fec_rate_bps, + nack_rate_bps); + CriticalSectionScoped cs(rtp_rtcp_cs_.get()); + for (auto* module : simulcast_rtp_rtcp_) { + uint32_t child_video_rate = 0; + uint32_t child_fec_rate = 0; + uint32_t child_nack_rate = 0; + module->SetFecParameters(delta_fec_params, key_fec_params); + module->BitrateSent(¬_used, &child_video_rate, &child_fec_rate, + &child_nack_rate); + *video_rate_bps += child_video_rate; + *nack_rate_bps += child_nack_rate; + *fec_rate_bps += child_fec_rate; + } + return 0; +} + void ViEChannel::ReserveRtpRtcpModules(size_t num_modules) { for (size_t total_modules = 1 + simulcast_rtp_rtcp_.size() + removed_rtp_rtcp_.size(); @@ -1710,7 +1911,7 @@ void ViEChannel::ReserveRtpRtcpModules(size_t num_modules) { RtpRtcp* rtp_rtcp = CreateRtpRtcpModule(); rtp_rtcp->SetSendingStatus(false); rtp_rtcp->SetSendingMediaStatus(false); - rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL); + rtp_rtcp->RegisterRtcpStatisticsCallback(NULL); rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL); removed_rtp_rtcp_.push_back(rtp_rtcp); } @@ -1741,19 +1942,26 @@ RtpRtcp* ViEChannel::GetRtpRtcpModule(size_t index) const { return *it; } -RtpRtcp* ViEChannel::CreateRtpRtcpModule() { +RtpRtcp::Configuration ViEChannel::CreateRtpRtcpConfiguration() { RtpRtcp::Configuration configuration; configuration.id = ViEModuleId(engine_id_, channel_id_); - configuration.audio = false; // Video. - configuration.default_module = default_rtp_rtcp_; + configuration.audio = false; configuration.outgoing_transport = &vie_sender_; configuration.intra_frame_callback = intra_frame_observer_; configuration.bandwidth_callback = bandwidth_observer_.get(); configuration.rtt_stats = rtt_stats_; + configuration.rtcp_packet_type_counter_observer = + &rtcp_packet_type_counter_observer_; configuration.paced_sender = paced_sender_; + configuration.send_bitrate_observer = &send_bitrate_observer_; + configuration.send_frame_count_observer = &send_frame_count_observer_; configuration.send_side_delay_observer = &send_side_delay_observer_; - return RtpRtcp::CreateRtpRtcp(configuration); + return configuration; +} + +RtpRtcp* ViEChannel::CreateRtpRtcpModule() { + return RtpRtcp::CreateRtpRtcp(CreateRtpRtcpConfiguration()); } int32_t ViEChannel::StartDecodeThread() { @@ -1763,19 +1971,9 @@ int32_t ViEChannel::StartDecodeThread() { return 0; } decode_thread_ = ThreadWrapper::CreateThread(ChannelDecodeThreadFunction, - this, kHighestPriority, - "DecodingThread"); - if (!decode_thread_) { - return -1; - } - - unsigned int thread_id; - if (decode_thread_->Start(thread_id) == false) { - delete decode_thread_; - decode_thread_ = NULL; - LOG(LS_ERROR) << "Could not start decode thread."; - return -1; - } + this, "DecodingThread"); + decode_thread_->Start(); + decode_thread_->SetPriority(kHighestPriority); return 0; } @@ -1784,24 +1982,17 @@ int32_t ViEChannel::StopDecodeThread() { return 0; } - decode_thread_->SetNotAlive(); - if (decode_thread_->Stop()) { - delete decode_thread_; - } else { - assert(false && "could not stop decode thread"); - } - decode_thread_ = NULL; + vcm_->TriggerDecoderShutdown(); + + decode_thread_->Stop(); + decode_thread_.reset(); + frame_delivery_thread_checker_.DetachFromThread(); + return 0; } int32_t ViEChannel::SetVoiceChannel(int32_t ve_channel_id, - VoEVideoSync* ve_sync_interface) { - if (ve_sync_interface) { - // Register lip sync - module_process_thread_.RegisterModule(&vie_sync_); - } else { - module_process_thread_.DeRegisterModule(&vie_sync_); - } + VoEVideoSync* ve_sync_interface) { return vie_sync_.ConfigureSync(ve_channel_id, ve_sync_interface, rtp_rtcp_.get(), @@ -1833,24 +2024,6 @@ void ViEChannel::RegisterPreDecodeImageCallback( vcm_->RegisterPreDecodeImageCallback(pre_decode_callback); } -void ViEChannel::OnApplicationDataReceived(const int32_t id, - const uint8_t sub_type, - const uint32_t name, - const uint16_t length, - const uint8_t* data) { - if (channel_id_ != ChannelId(id)) { - return; - } - CriticalSectionScoped cs(callback_cs_.get()); - { - if (rtcp_observer_) { - rtcp_observer_->OnApplicationDataReceived( - channel_id_, sub_type, name, reinterpret_cast(data), - length); - } - } -} - int32_t ViEChannel::OnInitializeDecoder( const int32_t id, const int8_t payload_type, @@ -1858,8 +2031,8 @@ int32_t ViEChannel::OnInitializeDecoder( const int frequency, const uint8_t channels, const uint32_t rate) { - LOG(LS_INFO) << "OnInitializeDecoder " << payload_type << " " - << payload_name; + LOG(LS_INFO) << "OnInitializeDecoder " << static_cast(payload_type) + << " " << payload_name; vcm_->ResetDecoder(); CriticalSectionScoped cs(callback_cs_.get()); @@ -1903,8 +2076,15 @@ void ViEChannel::RegisterSendFrameCountObserver( send_frame_count_observer_.Set(observer); } +void ViEChannel::RegisterReceiveStatisticsProxy( + ReceiveStatisticsProxy* receive_statistics_proxy) { + CriticalSectionScoped cs(callback_cs_.get()); + vcm_receive_stats_callback_ = receive_statistics_proxy; +} + void ViEChannel::ReceivedBWEPacket(int64_t arrival_time_ms, - int payload_size, const RTPHeader& header) { + size_t payload_size, + const RTPHeader& header) { vie_receiver_.ReceivedBWEPacket(arrival_time_ms, payload_size, header); } } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_channel.h b/media/webrtc/trunk/webrtc/video_engine/vie_channel.h index caab4c4808..1197115e28 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_channel.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_channel.h @@ -13,11 +13,13 @@ #include +#include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" +#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" #include "webrtc/modules/video_coding/main/interface/video_coding_defines.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/system_wrappers/interface/scoped_refptr.h" #include "webrtc/system_wrappers/interface/tick_util.h" #include "webrtc/typedefs.h" #include "webrtc/video_engine/include/vie_network.h" @@ -37,13 +39,16 @@ class CriticalSectionWrapper; class EncodedImageCallback; class I420FrameCallback; class PacedSender; +class PacketRouter; +class PayloadRouter; class ProcessThread; +class ReceiveStatisticsProxy; +class ReportBlockStats; class RtcpRttStats; -class RtpRtcp; class ThreadWrapper; +class ViEChannelProtectionCallback; class ViEDecoderObserver; class ViEEffectFilter; -class ViERTCPObserver; class ViERTPObserver; class VideoCodingModule; class VideoDecoder; @@ -59,11 +64,11 @@ class ViEChannel public VCMDecoderTimingCallback, public VCMPacketRequestCallback, public VCMReceiveStateCallback, - public RtcpFeedback, public RtpFeedback, public ViEFrameProviderBase { public: friend class ChannelStatsObserver; + friend class ViEChannelProtectionCallback; ViEChannel(int32_t channel_id, int32_t engine_id, @@ -75,8 +80,9 @@ class ViEChannel RemoteBitrateEstimator* remote_bitrate_estimator, RtcpRttStats* rtt_stats, PacedSender* paced_sender, - RtpRtcp* default_rtp_rtcp, - bool sender); + PacketRouter* packet_router, + bool sender, + bool disable_default_encoder); ~ViEChannel(); int32_t Init(); @@ -111,8 +117,8 @@ class ViEChannel // key frames. int32_t SetSignalPacketLossStatus(bool enable, bool only_key_frames); - int32_t SetRTCPMode(const RTCPMethod rtcp_mode); - int32_t GetRTCPMode(RTCPMethod* rtcp_mode); + void SetRTCPMode(const RTCPMethod rtcp_mode); + RTCPMethod GetRTCPMode() const; int32_t SetNACKStatus(const bool enable); int32_t SetFECStatus(const bool enable, const unsigned char payload_typeRED, @@ -120,18 +126,21 @@ class ViEChannel int32_t SetHybridNACKFECStatus(const bool enable, const unsigned char payload_typeRED, const unsigned char payload_typeFEC); + bool IsSendingFecEnabled(); int SetSenderBufferingMode(int target_delay_ms); int SetReceiverBufferingMode(int target_delay_ms); int32_t SetKeyFrameRequestMethod(const KeyFrameRequestMethod method); - bool EnableRemb(bool enable); + void EnableRemb(bool enable); int SetSendTimestampOffsetStatus(bool enable, int id); int SetReceiveTimestampOffsetStatus(bool enable, int id); int SetSendAbsoluteSendTimeStatus(bool enable, int id); int SetReceiveAbsoluteSendTimeStatus(bool enable, int id); bool GetReceiveAbsoluteSendTimeStatus() const; + int SetSendVideoRotationStatus(bool enable, int id); + int SetReceiveVideoRotationStatus(bool enable, int id); void SetRtcpXrRrtrStatus(bool enable); void SetTransmissionSmoothingStatus(bool enable); - int32_t EnableTMMBR(const bool enable); + void EnableTMMBR(bool enable); int32_t EnableKeyFrameRequestCallback(const bool enable); // Sets SSRC for outgoing stream. @@ -149,8 +158,6 @@ class ViEChannel int32_t GetRemoteCSRC(uint32_t CSRCs[kRtpCsrcSize]); int SetRtxSendPayloadType(int payload_type); - // Only has an effect once RTX is enabled. - void SetPadWithRedundantPayloads(bool enable); void SetRtxReceivePayloadType(int payload_type); // Sets the starting sequence number, must be called before StartSend. @@ -165,7 +172,6 @@ class ViEChannel // Gets the CName of the incoming stream. int32_t GetRemoteRTCPCName(char rtcp_cname[]); int32_t RegisterRtpObserver(ViERTPObserver* observer); - int32_t RegisterRtcpObserver(ViERTCPObserver* observer); int32_t SendApplicationDefinedRTCPPacket( const uint8_t sub_type, uint32_t name, @@ -187,7 +193,7 @@ class ViEChannel uint32_t* cumulative_lost, uint32_t* extended_max, uint32_t* jitter_samples, - int32_t* rtt_ms); + int64_t* rtt_ms); // Called on receipt of RTCP report block from remote side. void RegisterSendChannelRtcpStatisticsCallback( @@ -198,18 +204,26 @@ class ViEChannel uint32_t* cumulative_lost, uint32_t* extended_max, uint32_t* jitter_samples, - int32_t* rtt_ms); + int64_t* rtt_ms); // Called on generation of RTCP stats void RegisterReceiveChannelRtcpStatisticsCallback( RtcpStatisticsCallback* callback); // Gets sent/received packets statistics. - int32_t GetRtpStatistics(uint32_t* bytes_sent, + int32_t GetRtpStatistics(size_t* bytes_sent, uint32_t* packets_sent, - uint32_t* bytes_received, + size_t* bytes_received, uint32_t* packets_received) const; + // Gets send statistics for the rtp and rtx stream. + void GetSendStreamDataCounters(StreamDataCounters* rtp_counters, + StreamDataCounters* rtx_counters) const; + + // Gets received stream data counters. + void GetReceiveStreamDataCounters(StreamDataCounters* rtp_counters, + StreamDataCounters* rtx_counters) const; + // Called on update of RTP statistics. void RegisterSendChannelRtpStatisticsCallback( StreamDataCountersCallback* callback); @@ -218,8 +232,11 @@ class ViEChannel void RegisterReceiveChannelRtpStatisticsCallback( StreamDataCountersCallback* callback); - void GetRtcpPacketTypeCounters(RtcpPacketTypeCounter* packets_sent, - RtcpPacketTypeCounter* packets_received) const; + void GetSendRtcpPacketTypeCounter( + RtcpPacketTypeCounter* packet_counter) const; + + void GetReceiveRtcpPacketTypeCounter( + RtcpPacketTypeCounter* packet_counter) const; int32_t GetRemoteRTCPSenderInfo(SenderInfo* sender_info) const; @@ -232,8 +249,6 @@ class ViEChannel // to avoid deadlocks. bool GetSendSideDelay(int* avg_send_delay, int* max_send_delay) const; void RegisterSendSideDelayObserver(SendSideDelayObserver* observer); - void GetReceiveBandwidthEstimatorStats( - ReceiveBandwidthEstimatorStats* output) const; // Called on any new send bitrate estimate. void RegisterSendBitrateObserver(BitrateStatisticsObserver* observer); @@ -242,13 +257,6 @@ class ViEChannel RTPDirections direction); int32_t StopRTPDump(RTPDirections direction); - // Implements RtcpFeedback. - // TODO(pwestin) Depricate this functionality. - virtual void OnApplicationDataReceived(const int32_t id, - const uint8_t sub_type, - const uint32_t name, - const uint16_t length, - const uint8_t* data); // Implements RtpFeedback. virtual int32_t OnInitializeDecoder( const int32_t id, @@ -298,12 +306,12 @@ class ViEChannel // Incoming packet from external transport. int32_t ReceivedRTPPacket(const void* rtp_packet, - const int32_t rtp_packet_length, + const size_t rtp_packet_length, const PacketTime& packet_time); // Incoming packet from external transport. int32_t ReceivedRTCPPacket(const void* rtcp_packet, - const int32_t rtcp_packet_length); + const size_t rtcp_packet_length); // Sets the maximum transfer unit size for the network link, i.e. including // IP, UDP and RTP headers. @@ -319,6 +327,9 @@ class ViEChannel // Gets the modules used by the channel. RtpRtcp* rtp_rtcp(); + scoped_refptr send_payload_router(); + VCMProtectionCallback* vcm_protection_callback(); + CallStatsObserver* GetStatsObserver(); @@ -333,8 +344,9 @@ class ViEChannel virtual void IncomingCodecChanged(const VideoCodec& codec); // Implements VCMReceiveStatisticsCallback. - virtual int32_t OnReceiveStatisticsUpdate(const uint32_t bit_rate, - const uint32_t frame_rate); + void OnReceiveRatesUpdated(uint32_t bit_rate, uint32_t frame_rate) override; + void OnDiscardedPacketsUpdated(int discarded_packets) override; + void OnFrameCountsUpdated(const FrameCounts& frame_counts) override; // Implements VCMDecoderTimingCallback. virtual void OnDecoderTiming(int decode_ms, @@ -374,21 +386,31 @@ class ViEChannel EncodedImageCallback* pre_decode_callback); void RegisterSendFrameCountObserver(FrameCountObserver* observer); - - void ReceivedBWEPacket(int64_t arrival_time_ms, int payload_size, + void RegisterRtcpPacketTypeCounterObserver( + RtcpPacketTypeCounterObserver* observer); + void RegisterReceiveStatisticsProxy( + ReceiveStatisticsProxy* receive_statistics_proxy); + void ReceivedBWEPacket(int64_t arrival_time_ms, size_t payload_size, const RTPHeader& header); protected: static bool ChannelDecodeThreadFunction(void* obj); bool ChannelDecodeProcess(); - void OnRttUpdate(uint32_t rtt); + void OnRttUpdate(int64_t rtt); + + int ProtectionRequest(const FecProtectionParams* delta_fec_params, + const FecProtectionParams* key_fec_params, + uint32_t* sent_video_rate_bps, + uint32_t* sent_nack_rate_bps, + uint32_t* sent_fec_rate_bps); private: void ReserveRtpRtcpModules(size_t total_modules) EXCLUSIVE_LOCKS_REQUIRED(rtp_rtcp_cs_); RtpRtcp* GetRtpRtcpModule(size_t simulcast_idx) const EXCLUSIVE_LOCKS_REQUIRED(rtp_rtcp_cs_); + RtpRtcp::Configuration CreateRtpRtcpConfiguration(); RtpRtcp* CreateRtpRtcpModule(); // Assumed to be protected. int32_t StartDecodeThread(); @@ -403,6 +425,7 @@ class ViEChannel void SetRtxSendStatus(bool enable); void UpdateHistograms(); + void UpdateHistogramsAtStopSend(); // ViEChannel exposes methods that allow to modify observers and callbacks // to be modified. Such an API-style is cumbersome to implement and maintain @@ -425,7 +448,7 @@ class ViEChannel // Note: this should be implemented with a RW-lock to allow simultaneous // calls into the callback. However that doesn't seem to be needed for the // current type of callbacks covered by this class. - scoped_ptr critsect_; + rtc::scoped_ptr critsect_; T* callback_ GUARDED_BY(critsect_); private: @@ -441,68 +464,96 @@ class ViEChannel if (callback_) callback_->Notify(total_stats, retransmit_stats, ssrc); } - } - send_bitrate_observer_; + } send_bitrate_observer_; class RegisterableFrameCountObserver : public RegisterableCallback { - virtual void FrameCountUpdated(FrameType frame_type, - uint32_t frame_count, - const unsigned int ssrc) { + public: + virtual void FrameCountUpdated(const FrameCounts& frame_counts, + uint32_t ssrc) { CriticalSectionScoped cs(critsect_.get()); if (callback_) - callback_->FrameCountUpdated(frame_type, frame_count, ssrc); + callback_->FrameCountUpdated(frame_counts, ssrc); } + + private: } send_frame_count_observer_; class RegisterableSendSideDelayObserver : public RegisterableCallback { - virtual void SendSideDelayUpdated(int avg_delay_ms, - int max_delay_ms, - uint32_t ssrc) OVERRIDE { + void SendSideDelayUpdated(int avg_delay_ms, + int max_delay_ms, + uint32_t ssrc) override { CriticalSectionScoped cs(critsect_.get()); if (callback_) callback_->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc); } } send_side_delay_observer_; + class RegisterableRtcpPacketTypeCounterObserver + : public RegisterableCallback { + public: + void RtcpPacketTypesCounterUpdated( + uint32_t ssrc, + const RtcpPacketTypeCounter& packet_counter) override { + CriticalSectionScoped cs(critsect_.get()); + if (callback_) + callback_->RtcpPacketTypesCounterUpdated(ssrc, packet_counter); + counter_map_[ssrc] = packet_counter; + } + + virtual std::map GetPacketTypeCounterMap() + const { + CriticalSectionScoped cs(critsect_.get()); + return counter_map_; + } + + private: + std::map counter_map_ + GUARDED_BY(critsect_); + } rtcp_packet_type_counter_observer_; + int32_t channel_id_; int32_t engine_id_; uint32_t number_of_cores_; uint8_t num_socket_threads_; // Used for all registered callbacks except rendering. - scoped_ptr callback_cs_; - scoped_ptr rtp_rtcp_cs_; - - RtpRtcp* default_rtp_rtcp_; + rtc::scoped_ptr callback_cs_; + rtc::scoped_ptr rtp_rtcp_cs_; // Owned modules/classes. - scoped_ptr rtp_rtcp_; + rtc::scoped_ptr rtp_rtcp_; std::list simulcast_rtp_rtcp_; std::list removed_rtp_rtcp_; + scoped_refptr send_payload_router_; + rtc::scoped_ptr vcm_protection_callback_; + VideoCodingModule* const vcm_; ViEReceiver vie_receiver_; ViESender vie_sender_; ViESyncModule vie_sync_; // Helper to report call statistics. - scoped_ptr stats_observer_; + rtc::scoped_ptr stats_observer_; // Not owned. + VCMReceiveStatisticsCallback* vcm_receive_stats_callback_ + GUARDED_BY(callback_cs_); + FrameCounts receive_frame_counts_ GUARDED_BY(callback_cs_); ProcessThread& module_process_thread_; ViEDecoderObserver* codec_observer_; bool do_key_frame_callbackRequest_; ViERTPObserver* rtp_observer_; - ViERTCPObserver* rtcp_observer_; RtcpIntraFrameObserver* intra_frame_observer_; RtcpRttStats* rtt_stats_; PacedSender* paced_sender_; - bool pad_with_redundant_payloads_; + PacketRouter* packet_router_; - scoped_ptr bandwidth_observer_; + rtc::scoped_ptr bandwidth_observer_; int send_timestamp_extension_id_; int absolute_send_time_extension_id_; + int video_rotation_extension_id_; Transport* external_transport_; @@ -510,7 +561,7 @@ class ViEChannel // Current receive codec used for codec change callback. VideoCodec receive_codec_; bool wait_for_key_frame_; - ThreadWrapper* decode_thread_; + rtc::scoped_ptr decode_thread_; ViEEffectFilter* effect_filter_; bool color_enhancement_; @@ -518,13 +569,15 @@ class ViEChannel // User set MTU, -1 if not set. uint16_t mtu_; const bool sender_; + // Used to skip default encoder in the new API. + const bool disable_default_encoder_; int nack_history_size_sender_; int max_nack_reordering_threshold_; I420FrameCallback* pre_render_callback_; - const int64_t start_ms_; - std::map prev_report_blocks_; + rtc::scoped_ptr report_block_stats_sender_; + rtc::scoped_ptr report_block_stats_receiver_; }; } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_channel_group.cc b/media/webrtc/trunk/webrtc/video_engine/vie_channel_group.cc index 9c2d59f014..3b752cc722 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_channel_group.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_channel_group.cc @@ -10,10 +10,12 @@ #include "webrtc/video_engine/vie_channel_group.h" +#include "webrtc/base/checks.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/common.h" #include "webrtc/experiments.h" -#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" +#include "webrtc/modules/pacing/include/paced_sender.h" +#include "webrtc/modules/pacing/include/packet_router.h" #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" #include "webrtc/modules/utility/interface/process_thread.h" @@ -21,9 +23,11 @@ #include "webrtc/system_wrappers/interface/logging.h" #include "webrtc/video_engine/call_stats.h" #include "webrtc/video_engine/encoder_state_feedback.h" +#include "webrtc/video_engine/payload_router.h" #include "webrtc/video_engine/vie_channel.h" #include "webrtc/video_engine/vie_encoder.h" #include "webrtc/video_engine/vie_remb.h" +#include "webrtc/voice_engine/include/voe_video_sync.h" namespace webrtc { namespace { @@ -32,19 +36,16 @@ static const uint32_t kTimeOffsetSwitchThreshold = 30; class WrappingBitrateEstimator : public RemoteBitrateEstimator { public: - WrappingBitrateEstimator(int engine_id, - RemoteBitrateObserver* observer, + WrappingBitrateEstimator(RemoteBitrateObserver* observer, Clock* clock, const Config& config) : observer_(observer), clock_(clock), crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), - engine_id_(engine_id), min_bitrate_bps_(config.Get().min_rate), - rate_control_type_(kAimdControl), rbe_(RemoteBitrateEstimatorFactory().Create(observer_, clock_, - rate_control_type_, + kAimdControl, min_bitrate_bps_)), using_absolute_send_time_(false), packets_since_absolute_send_time_(0) { @@ -52,56 +53,45 @@ class WrappingBitrateEstimator : public RemoteBitrateEstimator { virtual ~WrappingBitrateEstimator() {} - virtual void IncomingPacket(int64_t arrival_time_ms, - int payload_size, - const RTPHeader& header) OVERRIDE { + void IncomingPacket(int64_t arrival_time_ms, + size_t payload_size, + const RTPHeader& header) override { CriticalSectionScoped cs(crit_sect_.get()); PickEstimatorFromHeader(header); rbe_->IncomingPacket(arrival_time_ms, payload_size, header); } - virtual int32_t Process() OVERRIDE { + int32_t Process() override { CriticalSectionScoped cs(crit_sect_.get()); return rbe_->Process(); } - virtual int32_t TimeUntilNextProcess() OVERRIDE { + int64_t TimeUntilNextProcess() override { CriticalSectionScoped cs(crit_sect_.get()); return rbe_->TimeUntilNextProcess(); } - virtual void OnRttUpdate(uint32_t rtt) OVERRIDE { + void OnRttUpdate(int64_t rtt) override { CriticalSectionScoped cs(crit_sect_.get()); rbe_->OnRttUpdate(rtt); } - virtual void RemoveStream(unsigned int ssrc) OVERRIDE { + void RemoveStream(unsigned int ssrc) override { CriticalSectionScoped cs(crit_sect_.get()); rbe_->RemoveStream(ssrc); } - virtual bool LatestEstimate(std::vector* ssrcs, - unsigned int* bitrate_bps) const OVERRIDE { + bool LatestEstimate(std::vector* ssrcs, + unsigned int* bitrate_bps) const override { CriticalSectionScoped cs(crit_sect_.get()); return rbe_->LatestEstimate(ssrcs, bitrate_bps); } - virtual bool GetStats(ReceiveBandwidthEstimatorStats* output) const OVERRIDE { + bool GetStats(ReceiveBandwidthEstimatorStats* output) const override { CriticalSectionScoped cs(crit_sect_.get()); return rbe_->GetStats(output); } - void SetConfig(const webrtc::Config& config) { - CriticalSectionScoped cs(crit_sect_.get()); - RateControlType new_control_type = - config.Get().enabled ? kAimdControl : - kMimdControl; - if (new_control_type != rate_control_type_) { - rate_control_type_ = new_control_type; - PickEstimator(); - } - } - private: void PickEstimatorFromHeader(const RTPHeader& header) EXCLUSIVE_LOCKS_REQUIRED(crit_sect_.get()) { @@ -132,20 +122,18 @@ class WrappingBitrateEstimator : public RemoteBitrateEstimator { void PickEstimator() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_.get()) { if (using_absolute_send_time_) { rbe_.reset(AbsoluteSendTimeRemoteBitrateEstimatorFactory().Create( - observer_, clock_, rate_control_type_, min_bitrate_bps_)); + observer_, clock_, kAimdControl, min_bitrate_bps_)); } else { rbe_.reset(RemoteBitrateEstimatorFactory().Create( - observer_, clock_, rate_control_type_, min_bitrate_bps_)); + observer_, clock_, kAimdControl, min_bitrate_bps_)); } } RemoteBitrateObserver* observer_; Clock* clock_; - scoped_ptr crit_sect_; - const int engine_id_; + rtc::scoped_ptr crit_sect_; const uint32_t min_bitrate_bps_; - RateControlType rate_control_type_; - scoped_ptr rbe_; + rtc::scoped_ptr rbe_; bool using_absolute_send_time_; uint32_t packets_since_absolute_send_time_; @@ -153,89 +141,331 @@ class WrappingBitrateEstimator : public RemoteBitrateEstimator { }; } // namespace -ChannelGroup::ChannelGroup(int engine_id, - ProcessThread* process_thread, - const Config* config) +ChannelGroup::ChannelGroup(ProcessThread* process_thread, const Config* config) : remb_(new VieRemb()), - bitrate_controller_( - BitrateController::CreateBitrateController(Clock::GetRealTimeClock(), - true)), + bitrate_allocator_(new BitrateAllocator()), call_stats_(new CallStats()), encoder_state_feedback_(new EncoderStateFeedback()), + packet_router_(new PacketRouter()), + pacer_(new PacedSender(Clock::GetRealTimeClock(), + packet_router_.get(), + BitrateController::kDefaultStartBitrateKbps, + PacedSender::kDefaultPaceMultiplier * + BitrateController::kDefaultStartBitrateKbps, + 0)), + encoder_map_cs_(CriticalSectionWrapper::CreateCriticalSection()), config_(config), own_config_(), - process_thread_(process_thread) { + process_thread_(process_thread), + pacer_thread_(ProcessThread::Create()), + // Constructed last as this object calls the provided callback on + // construction. + bitrate_controller_( + BitrateController::CreateBitrateController(Clock::GetRealTimeClock(), + this)) { if (!config) { own_config_.reset(new Config); config_ = own_config_.get(); } - assert(config_); // Must have a valid config pointer here. + DCHECK(config_); // Must have a valid config pointer here. remote_bitrate_estimator_.reset( - new WrappingBitrateEstimator(engine_id, - remb_.get(), + new WrappingBitrateEstimator(remb_.get(), Clock::GetRealTimeClock(), *config_)); call_stats_->RegisterStatsObserver(remote_bitrate_estimator_.get()); + pacer_thread_->RegisterModule(pacer_.get()); + pacer_thread_->Start(); + process_thread->RegisterModule(remote_bitrate_estimator_.get()); process_thread->RegisterModule(call_stats_.get()); process_thread->RegisterModule(bitrate_controller_.get()); } ChannelGroup::~ChannelGroup() { + pacer_thread_->Stop(); + pacer_thread_->DeRegisterModule(pacer_.get()); process_thread_->DeRegisterModule(bitrate_controller_.get()); process_thread_->DeRegisterModule(call_stats_.get()); process_thread_->DeRegisterModule(remote_bitrate_estimator_.get()); call_stats_->DeregisterStatsObserver(remote_bitrate_estimator_.get()); - assert(channels_.empty()); - assert(!remb_->InUse()); + DCHECK(channels_.empty()); + DCHECK(channel_map_.empty()); + DCHECK(!remb_->InUse()); + DCHECK(vie_encoder_map_.empty()); + DCHECK(send_encoders_.empty()); +} + +bool ChannelGroup::CreateSendChannel(int channel_id, + int engine_id, + int number_of_cores, + bool disable_default_encoder) { + rtc::scoped_ptr vie_encoder(new ViEEncoder( + channel_id, number_of_cores, *config_, *process_thread_, pacer_.get(), + bitrate_allocator_.get(), bitrate_controller_.get(), false)); + if (!vie_encoder->Init()) { + return false; + } + ViEEncoder* encoder = vie_encoder.get(); + if (!CreateChannel(channel_id, engine_id, number_of_cores, + vie_encoder.release(), true, disable_default_encoder)) { + return false; + } + ViEChannel* channel = channel_map_[channel_id]; + // Connect the encoder with the send packet router, to enable sending. + encoder->StartThreadsAndSetSharedMembers(channel->send_payload_router(), + channel->vcm_protection_callback()); + + // Register the ViEEncoder to get key frame requests for this channel. + unsigned int ssrc = 0; + int stream_idx = 0; + channel->GetLocalSSRC(stream_idx, &ssrc); + encoder_state_feedback_->AddEncoder(ssrc, encoder); + std::list ssrcs; + ssrcs.push_back(ssrc); + encoder->SetSsrcs(ssrcs); + return true; +} + +bool ChannelGroup::CreateReceiveChannel(int channel_id, + int engine_id, + int base_channel_id, + int number_of_cores, + bool disable_default_encoder) { + ViEEncoder* encoder = GetEncoder(base_channel_id); + return CreateChannel(channel_id, engine_id, number_of_cores, encoder, false, + disable_default_encoder); +} + +bool ChannelGroup::CreateChannel(int channel_id, + int engine_id, + int number_of_cores, + ViEEncoder* vie_encoder, + bool sender, + bool disable_default_encoder) { + DCHECK(vie_encoder); + + rtc::scoped_ptr channel(new ViEChannel( + channel_id, engine_id, number_of_cores, *config_, *process_thread_, + encoder_state_feedback_->GetRtcpIntraFrameObserver(), + bitrate_controller_->CreateRtcpBandwidthObserver(), + remote_bitrate_estimator_.get(), call_stats_->rtcp_rtt_stats(), + pacer_.get(), packet_router_.get(), sender, disable_default_encoder)); + if (channel->Init() != 0) { + return false; + } + if (!disable_default_encoder) { + VideoCodec encoder; + if (vie_encoder->GetEncoder(&encoder) != 0) { + return false; + } + if (sender && channel->SetSendCodec(encoder) != 0) { + return false; + } + } + + // Register the channel to receive stats updates. + call_stats_->RegisterStatsObserver(channel->GetStatsObserver()); + + // Store the channel, add it to the channel group and save the vie_encoder. + channel_map_[channel_id] = channel.release(); + { + CriticalSectionScoped lock(encoder_map_cs_.get()); + vie_encoder_map_[channel_id] = vie_encoder; + if (sender) + send_encoders_[channel_id] = vie_encoder; + } + + return true; +} + +void ChannelGroup::DeleteChannel(int channel_id) { + ViEChannel* vie_channel = PopChannel(channel_id); + + ViEEncoder* vie_encoder = GetEncoder(channel_id); + DCHECK(vie_encoder != NULL); + + call_stats_->DeregisterStatsObserver(vie_channel->GetStatsObserver()); + SetChannelRembStatus(channel_id, false, false, vie_channel); + + // If we're owning the encoder, remove the feedback and stop all encoding + // threads and processing. This must be done before deleting the channel. + if (vie_encoder->channel_id() == channel_id) { + encoder_state_feedback_->RemoveEncoder(vie_encoder); + vie_encoder->StopThreadsAndRemoveSharedMembers(); + } + + unsigned int remote_ssrc = 0; + vie_channel->GetRemoteSSRC(&remote_ssrc); + RemoveChannel(channel_id); + remote_bitrate_estimator_->RemoveStream(remote_ssrc); + + // Check if other channels are using the same encoder. + if (OtherChannelsUsingEncoder(channel_id)) { + vie_encoder = NULL; + } else { + // Delete later when we've released the critsect. + } + + // We can't erase the item before we've checked for other channels using + // same ViEEncoder. + PopEncoder(channel_id); + + delete vie_channel; + // Leave the write critsect before deleting the objects. + // Deleting a channel can cause other objects, such as renderers, to be + // deleted, which might take time. + // If statment just to show that this object is not always deleted. + if (vie_encoder) { + LOG(LS_VERBOSE) << "ViEEncoder deleted for channel " << channel_id; + delete vie_encoder; + } + + LOG(LS_VERBOSE) << "Channel deleted " << channel_id; } void ChannelGroup::AddChannel(int channel_id) { channels_.insert(channel_id); } -void ChannelGroup::RemoveChannel(int channel_id, unsigned int ssrc) { +void ChannelGroup::RemoveChannel(int channel_id) { channels_.erase(channel_id); - remote_bitrate_estimator_->RemoveStream(ssrc); } -bool ChannelGroup::HasChannel(int channel_id) { +bool ChannelGroup::HasChannel(int channel_id) const { return channels_.find(channel_id) != channels_.end(); } -bool ChannelGroup::Empty() { +bool ChannelGroup::Empty() const { return channels_.empty(); } -BitrateController* ChannelGroup::GetBitrateController() { +ViEChannel* ChannelGroup::GetChannel(int channel_id) const { + ChannelMap::const_iterator it = channel_map_.find(channel_id); + if (it == channel_map_.end()) { + LOG(LS_ERROR) << "Channel doesn't exist " << channel_id; + return NULL; + } + return it->second; +} + +ViEEncoder* ChannelGroup::GetEncoder(int channel_id) const { + CriticalSectionScoped lock(encoder_map_cs_.get()); + EncoderMap::const_iterator it = vie_encoder_map_.find(channel_id); + if (it == vie_encoder_map_.end()) { + return NULL; + } + return it->second; +} + +ViEChannel* ChannelGroup::PopChannel(int channel_id) { + ChannelMap::iterator c_it = channel_map_.find(channel_id); + DCHECK(c_it != channel_map_.end()); + ViEChannel* channel = c_it->second; + channel_map_.erase(c_it); + + return channel; +} + +ViEEncoder* ChannelGroup::PopEncoder(int channel_id) { + CriticalSectionScoped lock(encoder_map_cs_.get()); + auto it = vie_encoder_map_.find(channel_id); + DCHECK(it != vie_encoder_map_.end()); + ViEEncoder* encoder = it->second; + vie_encoder_map_.erase(it); + + it = send_encoders_.find(channel_id); + if (it != send_encoders_.end()) + send_encoders_.erase(it); + + return encoder; +} + +std::vector ChannelGroup::GetChannelIds() const { + std::vector ids; + for (auto channel : channel_map_) + ids.push_back(channel.first); + return ids; +} + +bool ChannelGroup::OtherChannelsUsingEncoder(int channel_id) const { + CriticalSectionScoped lock(encoder_map_cs_.get()); + EncoderMap::const_iterator orig_it = vie_encoder_map_.find(channel_id); + if (orig_it == vie_encoder_map_.end()) { + // No ViEEncoder for this channel. + return false; + } + + // Loop through all other channels to see if anyone points at the same + // ViEEncoder. + for (EncoderMap::const_iterator comp_it = vie_encoder_map_.begin(); + comp_it != vie_encoder_map_.end(); ++comp_it) { + // Make sure we're not comparing the same channel with itself. + if (comp_it->first != channel_id) { + if (comp_it->second == orig_it->second) { + return true; + } + } + } + return false; +} + +void ChannelGroup::SetLoadManager(CPULoadStateCallbackInvoker* load_manager) { + for (EncoderMap::const_iterator comp_it = vie_encoder_map_.begin(); + comp_it != vie_encoder_map_.end(); ++comp_it) { + comp_it->second->SetLoadManager(load_manager); + } +} + +void ChannelGroup::SetSyncInterface(VoEVideoSync* sync_interface) { + for (auto channel : channel_map_) { + channel.second->SetVoiceChannel(-1, sync_interface); + } +} + +void ChannelGroup::GetChannelsUsingEncoder(int channel_id, + ChannelList* channels) const { + CriticalSectionScoped lock(encoder_map_cs_.get()); + EncoderMap::const_iterator orig_it = vie_encoder_map_.find(channel_id); + + for (ChannelMap::const_iterator c_it = channel_map_.begin(); + c_it != channel_map_.end(); ++c_it) { + EncoderMap::const_iterator comp_it = vie_encoder_map_.find(c_it->first); + DCHECK(comp_it != vie_encoder_map_.end()); + if (comp_it->second == orig_it->second) { + channels->push_back(c_it->second); + } + } +} + +BitrateController* ChannelGroup::GetBitrateController() const { return bitrate_controller_.get(); } -RemoteBitrateEstimator* ChannelGroup::GetRemoteBitrateEstimator() { +RemoteBitrateEstimator* ChannelGroup::GetRemoteBitrateEstimator() const { return remote_bitrate_estimator_.get(); } -CallStats* ChannelGroup::GetCallStats() { +CallStats* ChannelGroup::GetCallStats() const { return call_stats_.get(); } -EncoderStateFeedback* ChannelGroup::GetEncoderStateFeedback() { +EncoderStateFeedback* ChannelGroup::GetEncoderStateFeedback() const { return encoder_state_feedback_.get(); } -bool ChannelGroup::SetChannelRembStatus(int channel_id, bool sender, - bool receiver, ViEChannel* channel) { +int64_t ChannelGroup::GetPacerQueuingDelayMs() const { + return pacer_->QueueInMs(); +} + +void ChannelGroup::SetChannelRembStatus(int channel_id, + bool sender, + bool receiver, + ViEChannel* channel) { // Update the channel state. - if (sender || receiver) { - if (!channel->EnableRemb(true)) { - return false; - } - } else { - channel->EnableRemb(false); - } + channel->EnableRemb(sender || receiver); // Update the REMB instance with necessary RTP modules. RtpRtcp* rtp_module = channel->rtp_rtcp(); if (sender) { @@ -248,12 +478,23 @@ bool ChannelGroup::SetChannelRembStatus(int channel_id, bool sender, } else { remb_->RemoveReceiveChannel(rtp_module); } - return true; } -void ChannelGroup::SetBandwidthEstimationConfig(const webrtc::Config& config) { - WrappingBitrateEstimator* estimator = - static_cast(remote_bitrate_estimator_.get()); - estimator->SetConfig(config); +void ChannelGroup::OnNetworkChanged(uint32_t target_bitrate_bps, + uint8_t fraction_loss, + int64_t rtt) { + bitrate_allocator_->OnNetworkChanged(target_bitrate_bps, fraction_loss, rtt); + int pad_up_to_bitrate_bps = 0; + { + CriticalSectionScoped lock(encoder_map_cs_.get()); + for (const auto& encoder : send_encoders_) { + pad_up_to_bitrate_bps += + encoder.second->GetPaddingNeededBps(target_bitrate_bps); + } + } + pacer_->UpdateBitrate( + target_bitrate_bps / 1000, + PacedSender::kDefaultPaceMultiplier * target_bitrate_bps / 1000, + pad_up_to_bitrate_bps / 1000); } } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_channel_group.h b/media/webrtc/trunk/webrtc/video_engine/vie_channel_group.h index 40ce71ef19..6db1a98bc9 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_channel_group.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_channel_group.h @@ -11,59 +11,114 @@ #ifndef WEBRTC_VIDEO_ENGINE_VIE_CHANNEL_GROUP_H_ #define WEBRTC_VIDEO_ENGINE_VIE_CHANNEL_GROUP_H_ +#include +#include #include +#include -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/base/scoped_ptr.h" +#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" namespace webrtc { -class BitrateController; +class BitrateAllocator; class CallStats; class Config; class EncoderStateFeedback; +class PacedSender; +class PacketRouter; class ProcessThread; class RemoteBitrateEstimator; class ViEChannel; class ViEEncoder; class VieRemb; +class VoEVideoSync; +class CPULoadStateCallbackInvoker; + +typedef std::list ChannelList; // Channel group contains data common for several channels. All channels in the // group are assumed to send/receive data to the same end-point. -class ChannelGroup { +class ChannelGroup : public BitrateObserver { public: - ChannelGroup(int engine_id, ProcessThread* process_thread, - const Config* config); + ChannelGroup(ProcessThread* process_thread, const Config* config); ~ChannelGroup(); - + bool CreateSendChannel(int channel_id, + int engine_id, + int number_of_cores, + bool disable_default_encoder); + bool CreateReceiveChannel(int channel_id, + int engine_id, + int base_channel_id, + int number_of_cores, + bool disable_default_encoder); + void DeleteChannel(int channel_id); void AddChannel(int channel_id); - void RemoveChannel(int channel_id, unsigned int ssrc); - bool HasChannel(int channel_id); - bool Empty(); + void RemoveChannel(int channel_id); + bool HasChannel(int channel_id) const; + bool Empty() const; + ViEChannel* GetChannel(int channel_id) const; + ViEEncoder* GetEncoder(int channel_id) const; + std::vector GetChannelIds() const; + bool OtherChannelsUsingEncoder(int channel_id) const; + void SetLoadManager(CPULoadStateCallbackInvoker* load_manager); + void GetChannelsUsingEncoder(int channel_id, ChannelList* channels) const; - bool SetChannelRembStatus(int channel_id, bool sender, bool receiver, + void SetSyncInterface(VoEVideoSync* sync_interface); + + void SetChannelRembStatus(int channel_id, + bool sender, + bool receiver, ViEChannel* channel); - void SetBandwidthEstimationConfig(const webrtc::Config& config); - BitrateController* GetBitrateController(); - CallStats* GetCallStats(); - RemoteBitrateEstimator* GetRemoteBitrateEstimator(); - EncoderStateFeedback* GetEncoderStateFeedback(); + BitrateController* GetBitrateController() const; + CallStats* GetCallStats() const; + RemoteBitrateEstimator* GetRemoteBitrateEstimator() const; + EncoderStateFeedback* GetEncoderStateFeedback() const; + int64_t GetPacerQueuingDelayMs() const; + + // Implements BitrateObserver. + void OnNetworkChanged(uint32_t target_bitrate_bps, + uint8_t fraction_loss, + int64_t rtt) override; private: + typedef std::map ChannelMap; typedef std::set ChannelSet; + typedef std::map EncoderMap; - scoped_ptr remb_; - scoped_ptr bitrate_controller_; - scoped_ptr call_stats_; - scoped_ptr remote_bitrate_estimator_; - scoped_ptr encoder_state_feedback_; + bool CreateChannel(int channel_id, + int engine_id, + int number_of_cores, + ViEEncoder* vie_encoder, + bool sender, + bool disable_default_encoder); + ViEChannel* PopChannel(int channel_id); + ViEEncoder* PopEncoder(int channel_id); + + rtc::scoped_ptr remb_; + rtc::scoped_ptr bitrate_allocator_; + rtc::scoped_ptr call_stats_; + rtc::scoped_ptr remote_bitrate_estimator_; + rtc::scoped_ptr encoder_state_feedback_; + rtc::scoped_ptr packet_router_; + rtc::scoped_ptr pacer_; ChannelSet channels_; + ChannelMap channel_map_; + // Maps Channel id -> ViEEncoder. + EncoderMap vie_encoder_map_; + EncoderMap send_encoders_; + rtc::scoped_ptr encoder_map_cs_; + const Config* config_; // Placeholder for the case where this owns the config. - scoped_ptr own_config_; + rtc::scoped_ptr own_config_; // Registered at construct time and assumed to outlive this class. ProcessThread* process_thread_; + rtc::scoped_ptr pacer_thread_; + + rtc::scoped_ptr bitrate_controller_; }; } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_channel_manager.cc b/media/webrtc/trunk/webrtc/video_engine/vie_channel_manager.cc index 11d77c64ae..669f9213cd 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_channel_manager.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_channel_manager.cc @@ -10,6 +10,8 @@ #include "webrtc/video_engine/vie_channel_manager.h" +#include + #include "webrtc/common.h" #include "webrtc/engine_configurations.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" @@ -19,6 +21,7 @@ #include "webrtc/video_engine/call_stats.h" #include "webrtc/video_engine/encoder_state_feedback.h" #include "webrtc/video_engine/vie_channel.h" +#include "webrtc/video_engine/vie_channel_group.h" #include "webrtc/video_engine/vie_defines.h" #include "webrtc/video_engine/vie_encoder.h" #include "webrtc/video_engine/vie_remb.h" @@ -26,19 +29,16 @@ namespace webrtc { -ViEChannelManager::ViEChannelManager( - int engine_id, - int number_of_cores, - const Config& config) +ViEChannelManager::ViEChannelManager(int engine_id, + int number_of_cores, + const Config& config) : channel_id_critsect_(CriticalSectionWrapper::CreateCriticalSection()), engine_id_(engine_id), number_of_cores_(number_of_cores), free_channel_ids_(new bool[kViEMaxNumberOfChannels]), free_channel_ids_size_(kViEMaxNumberOfChannels), voice_sync_interface_(NULL), - voice_engine_(NULL), module_process_thread_(NULL), - engine_config_(config), load_manager_(NULL) { for (int idx = 0; idx < free_channel_ids_size_; idx++) { @@ -47,10 +47,12 @@ ViEChannelManager::ViEChannelManager( } ViEChannelManager::~ViEChannelManager() { - while (channel_map_.size() > 0) { - ChannelMap::iterator it = channel_map_.begin(); - // DeleteChannel will erase this channel from the map and invalidate |it|. - DeleteChannel(it->first); + while (!channel_groups_.empty()) { + // The channel group is deleted by DeleteChannel when all its channels have + // been deleted. + for (int channel_id : channel_groups_.front()->GetChannelIds()) { + DeleteChannel(channel_id); + } } if (voice_sync_interface_) { @@ -66,8 +68,6 @@ ViEChannelManager::~ViEChannelManager() { free_channel_ids_size_ = 0; } assert(channel_groups_.empty()); - assert(channel_map_.empty()); - assert(vie_encoder_map_.empty()); } void ViEChannelManager::SetModuleProcessThread( @@ -79,9 +79,9 @@ void ViEChannelManager::SetModuleProcessThread( void ViEChannelManager::SetLoadManager( CPULoadStateCallbackInvoker* load_manager) { load_manager_ = load_manager; - for (EncoderMap::const_iterator comp_it = vie_encoder_map_.begin(); - comp_it != vie_encoder_map_.end(); ++comp_it) { - comp_it->second->SetLoadManager(load_manager); + for (ChannelGroups::const_iterator it = channel_groups_.begin(); + it != channel_groups_.end(); ++it) { + (*it)->SetLoadManager(load_manager); } } @@ -96,56 +96,25 @@ int ViEChannelManager::CreateChannel(int* channel_id, } // Create a new channel group and add this channel. - ChannelGroup* group = new ChannelGroup(engine_id_, module_process_thread_, - channel_group_config); - BitrateController* bitrate_controller = group->GetBitrateController(); - ViEEncoder* vie_encoder = new ViEEncoder(engine_id_, new_channel_id, - number_of_cores_, - engine_config_, - *module_process_thread_, - bitrate_controller); + rtc::scoped_ptr group( + new ChannelGroup(module_process_thread_, channel_group_config)); - RtcpBandwidthObserver* bandwidth_observer = - bitrate_controller->CreateRtcpBandwidthObserver(); - RemoteBitrateEstimator* remote_bitrate_estimator = - group->GetRemoteBitrateEstimator(); - EncoderStateFeedback* encoder_state_feedback = - group->GetEncoderStateFeedback(); - RtcpRttStats* rtcp_rtt_stats = - group->GetCallStats()->rtcp_rtt_stats(); - - if (!(vie_encoder->Init() && - CreateChannelObject(new_channel_id, vie_encoder, bandwidth_observer, - remote_bitrate_estimator, rtcp_rtt_stats, - encoder_state_feedback->GetRtcpIntraFrameObserver(), - true))) { - delete vie_encoder; - vie_encoder = NULL; + if (!group->CreateSendChannel(new_channel_id, engine_id_, number_of_cores_, + false)) { ReturnChannelId(new_channel_id); - delete group; return -1; } - // Add ViEEncoder to EncoderFeedBackObserver. - unsigned int ssrc = 0; - int idx = 0; - channel_map_[new_channel_id]->GetLocalSSRC(idx, &ssrc); - encoder_state_feedback->AddEncoder(ssrc, vie_encoder); - std::list ssrcs; - ssrcs.push_back(ssrc); - vie_encoder->SetSsrcs(ssrcs); *channel_id = new_channel_id; group->AddChannel(*channel_id); - channel_groups_.push_back(group); - // Register the channel to receive stats updates. - group->GetCallStats()->RegisterStatsObserver( - channel_map_[new_channel_id]->GetStatsObserver()); + channel_groups_.push_back(group.release()); return 0; } int ViEChannelManager::CreateChannel(int* channel_id, int original_channel, - bool sender) { + bool sender, + bool disable_default_encoder) { CriticalSectionScoped cs(channel_id_critsect_); ChannelGroup* channel_group = FindGroup(original_channel); @@ -156,69 +125,27 @@ int ViEChannelManager::CreateChannel(int* channel_id, if (new_channel_id == -1) { return -1; } - BitrateController* bitrate_controller = channel_group->GetBitrateController(); - RtcpBandwidthObserver* bandwidth_observer = - bitrate_controller->CreateRtcpBandwidthObserver(); - RemoteBitrateEstimator* remote_bitrate_estimator = - channel_group->GetRemoteBitrateEstimator(); - EncoderStateFeedback* encoder_state_feedback = - channel_group->GetEncoderStateFeedback(); - RtcpRttStats* rtcp_rtt_stats = - channel_group->GetCallStats()->rtcp_rtt_stats(); - - ViEEncoder* vie_encoder = NULL; if (sender) { - // We need to create a new ViEEncoder. - vie_encoder = new ViEEncoder(engine_id_, new_channel_id, number_of_cores_, - engine_config_, - *module_process_thread_, - bitrate_controller); - if (!(vie_encoder->Init() && - CreateChannelObject( - new_channel_id, - vie_encoder, - bandwidth_observer, - remote_bitrate_estimator, - rtcp_rtt_stats, - encoder_state_feedback->GetRtcpIntraFrameObserver(), - sender))) { - delete vie_encoder; - vie_encoder = NULL; + if (!channel_group->CreateSendChannel(new_channel_id, engine_id_, + number_of_cores_, + disable_default_encoder)) { + ReturnChannelId(new_channel_id); + return -1; } - // Register the ViEEncoder to get key frame requests for this channel. - unsigned int ssrc = 0; - int stream_idx = 0; - channel_map_[new_channel_id]->GetLocalSSRC(stream_idx, &ssrc); - encoder_state_feedback->AddEncoder(ssrc, vie_encoder); } else { - vie_encoder = ViEEncoderPtr(original_channel); - assert(vie_encoder); - if (!CreateChannelObject( - new_channel_id, - vie_encoder, - bandwidth_observer, - remote_bitrate_estimator, - rtcp_rtt_stats, - encoder_state_feedback->GetRtcpIntraFrameObserver(), - sender)) { - vie_encoder = NULL; + if (!channel_group->CreateReceiveChannel(new_channel_id, engine_id_, + original_channel, number_of_cores_, + disable_default_encoder)) { + ReturnChannelId(new_channel_id); + return -1; } } - if (!vie_encoder) { - ReturnChannelId(new_channel_id); - return -1; - } *channel_id = new_channel_id; channel_group->AddChannel(*channel_id); - // Register the channel to receive stats updates. - channel_group->GetCallStats()->RegisterStatsObserver( - channel_map_[new_channel_id]->GetStatsObserver()); return 0; } int ViEChannelManager::DeleteChannel(int channel_id) { - ViEChannel* vie_channel = NULL; - ViEEncoder* vie_encoder = NULL; ChannelGroup* group = NULL; { // Write lock to make sure no one is using the channel. @@ -227,45 +154,11 @@ int ViEChannelManager::DeleteChannel(int channel_id) { // Protect the maps. CriticalSectionScoped cs(channel_id_critsect_); - ChannelMap::iterator c_it = channel_map_.find(channel_id); - if (c_it == channel_map_.end()) { - // No such channel. - return -1; - } - vie_channel = c_it->second; - channel_map_.erase(c_it); - - ReturnChannelId(channel_id); - - // Find the encoder object. - EncoderMap::iterator e_it = vie_encoder_map_.find(channel_id); - assert(e_it != vie_encoder_map_.end()); - vie_encoder = e_it->second; - group = FindGroup(channel_id); - group->GetCallStats()->DeregisterStatsObserver( - vie_channel->GetStatsObserver()); - group->SetChannelRembStatus(channel_id, false, false, vie_channel); - - // Remove the feedback if we're owning the encoder. - if (vie_encoder->channel_id() == channel_id) { - group->GetEncoderStateFeedback()->RemoveEncoder(vie_encoder); - } - - unsigned int remote_ssrc = 0; - vie_channel->GetRemoteSSRC(&remote_ssrc); - group->RemoveChannel(channel_id, remote_ssrc); - - // Check if other channels are using the same encoder. - if (ChannelUsingViEEncoder(channel_id)) { - vie_encoder = NULL; - } else { - // Delete later when we've released the critsect. - } - - // We can't erase the item before we've checked for other channels using - // same ViEEncoder. - vie_encoder_map_.erase(e_it); + if (group == NULL) + return -1; + ReturnChannelId(channel_id); + group->DeleteChannel(channel_id); if (group->Empty()) { channel_groups_.remove(group); @@ -273,15 +166,6 @@ int ViEChannelManager::DeleteChannel(int channel_id) { group = NULL; // Prevent group from being deleted. } } - delete vie_channel; - // Leave the write critsect before deleting the objects. - // Deleting a channel can cause other objects, such as renderers, to be - // deleted, which might take time. - // If statment just to show that this object is not always deleted. - if (vie_encoder) { - LOG(LS_VERBOSE) << "ViEEncoder deleted for channel " << channel_id; - delete vie_encoder; - } // If statment just to show that this object is not always deleted. if (group) { // Delete the group if empty last since the encoder holds a pointer to the @@ -289,7 +173,6 @@ int ViEChannelManager::DeleteChannel(int channel_id) { LOG(LS_VERBOSE) << "Channel group deleted for channel " << channel_id; delete group; } - LOG(LS_VERBOSE) << "Channel deleted " << channel_id; return 0; } @@ -308,14 +191,12 @@ int ViEChannelManager::SetVoiceEngine(VoiceEngine* voice_engine) { } } - for (ChannelMap::iterator it = channel_map_.begin(); it != channel_map_.end(); - ++it) { - it->second->SetVoiceChannel(-1, sync_interface); + for (ChannelGroup* group : channel_groups_) { + group->SetSyncInterface(sync_interface); } if (voice_sync_interface_) { voice_sync_interface_->Release(); } - voice_engine_ = voice_engine; voice_sync_interface_ = sync_interface; return 0; } @@ -344,11 +225,6 @@ int ViEChannelManager::DisconnectVoiceChannel(int channel_id) { return -1; } -VoiceEngine* ViEChannelManager::GetVoiceEngine() { - CriticalSectionScoped cs(channel_id_critsect_); - return voice_engine_; -} - bool ViEChannelManager::SetRembStatus(int channel_id, bool sender, bool receiver) { CriticalSectionScoped cs(channel_id_critsect_); @@ -359,7 +235,8 @@ bool ViEChannelManager::SetRembStatus(int channel_id, bool sender, ViEChannel* channel = ViEChannelPtr(channel_id); assert(channel); - return group->SetChannelRembStatus(channel_id, sender, receiver, channel); + group->SetChannelRembStatus(channel_id, sender, receiver, channel); + return true; } bool ViEChannelManager::SetReservedTransmitBitrate( @@ -396,17 +273,6 @@ void ViEChannelManager::UpdateSsrcs(int channel_id, } } -bool ViEChannelManager::SetBandwidthEstimationConfig( - int channel_id, const webrtc::Config& config) { - CriticalSectionScoped cs(channel_id_critsect_); - ChannelGroup* group = FindGroup(channel_id); - if (!group) { - return false; - } - group->SetBandwidthEstimationConfig(config); - return true; -} - bool ViEChannelManager::GetEstimatedSendBandwidth( int channel_id, uint32_t* estimated_bandwidth) const { CriticalSectionScoped cs(channel_id_critsect_); @@ -433,66 +299,46 @@ bool ViEChannelManager::GetEstimatedReceiveBandwidth( return true; } -bool ViEChannelManager::CreateChannelObject( - int channel_id, - ViEEncoder* vie_encoder, - RtcpBandwidthObserver* bandwidth_observer, - RemoteBitrateEstimator* remote_bitrate_estimator, - RtcpRttStats* rtcp_rtt_stats, - RtcpIntraFrameObserver* intra_frame_observer, - bool sender) { - PacedSender* paced_sender = vie_encoder->GetPacedSender(); +bool ViEChannelManager::GetPacerQueuingDelayMs(int channel_id, + int64_t* delay_ms) const { + CriticalSectionScoped cs(channel_id_critsect_); + ChannelGroup* group = FindGroup(channel_id); + if (!group) + return false; + *delay_ms = group->GetPacerQueuingDelayMs(); + return true; +} - // Register the channel at the encoder. - RtpRtcp* send_rtp_rtcp_module = vie_encoder->SendRtpRtcpModule(); - - ViEChannel* vie_channel = new ViEChannel(channel_id, engine_id_, - number_of_cores_, - engine_config_, - *module_process_thread_, - intra_frame_observer, - bandwidth_observer, - remote_bitrate_estimator, - rtcp_rtt_stats, - paced_sender, - send_rtp_rtcp_module, - sender); - if (vie_channel->Init() != 0) { - delete vie_channel; +bool ViEChannelManager::SetBitrateConfig(int channel_id, + int min_bitrate_bps, + int start_bitrate_bps, + int max_bitrate_bps) { + CriticalSectionScoped cs(channel_id_critsect_); + ChannelGroup* group = FindGroup(channel_id); + if (!group) return false; - } - VideoCodec encoder; - if (vie_encoder->GetEncoder(&encoder) != 0) { - delete vie_channel; - return false; - } - if (sender && vie_channel->SetSendCodec(encoder) != 0) { - delete vie_channel; - return false; - } - // Store the channel, add it to the channel group and save the vie_encoder. - channel_map_[channel_id] = vie_channel; - vie_encoder_map_[channel_id] = vie_encoder; + BitrateController* bitrate_controller = group->GetBitrateController(); + if (start_bitrate_bps > 0) + bitrate_controller->SetStartBitrate(start_bitrate_bps); + bitrate_controller->SetMinMaxBitrate(min_bitrate_bps, max_bitrate_bps); return true; } ViEChannel* ViEChannelManager::ViEChannelPtr(int channel_id) const { CriticalSectionScoped cs(channel_id_critsect_); - ChannelMap::const_iterator it = channel_map_.find(channel_id); - if (it == channel_map_.end()) { - LOG(LS_ERROR) << "Channel doesn't exist " << channel_id; + ChannelGroup* group = FindGroup(channel_id); + if (group == NULL) return NULL; - } - return it->second; + return group->GetChannel(channel_id); } ViEEncoder* ViEChannelManager::ViEEncoderPtr(int video_channel_id) const { CriticalSectionScoped cs(channel_id_critsect_); - EncoderMap::const_iterator it = vie_encoder_map_.find(video_channel_id); - if (it == vie_encoder_map_.end()) { + ChannelGroup* group = FindGroup(video_channel_id); + if (group == NULL) { return NULL; } - return it->second; + return group->GetEncoder(video_channel_id); } int ViEChannelManager::FreeChannelId() { @@ -528,39 +374,20 @@ ChannelGroup* ViEChannelManager::FindGroup(int channel_id) const { bool ViEChannelManager::ChannelUsingViEEncoder(int channel_id) const { CriticalSectionScoped cs(channel_id_critsect_); - EncoderMap::const_iterator orig_it = vie_encoder_map_.find(channel_id); - if (orig_it == vie_encoder_map_.end()) { - // No ViEEncoder for this channel. + ChannelGroup* group = FindGroup(channel_id); + if (group == NULL) { return false; } - - // Loop through all other channels to see if anyone points at the same - // ViEEncoder. - for (EncoderMap::const_iterator comp_it = vie_encoder_map_.begin(); - comp_it != vie_encoder_map_.end(); ++comp_it) { - // Make sure we're not comparing the same channel with itself. - if (comp_it->first != channel_id) { - if (comp_it->second == orig_it->second) { - return true; - } - } - } - return false; + return group->OtherChannelsUsingEncoder(channel_id); } void ViEChannelManager::ChannelsUsingViEEncoder(int channel_id, ChannelList* channels) const { CriticalSectionScoped cs(channel_id_critsect_); - EncoderMap::const_iterator orig_it = vie_encoder_map_.find(channel_id); - - for (ChannelMap::const_iterator c_it = channel_map_.begin(); - c_it != channel_map_.end(); ++c_it) { - EncoderMap::const_iterator comp_it = vie_encoder_map_.find(c_it->first); - assert(comp_it != vie_encoder_map_.end()); - if (comp_it->second == orig_it->second) { - channels->push_back(c_it->second); - } - } + ChannelGroup* group = FindGroup(channel_id); + if (group == NULL) + return; + group->GetChannelsUsingEncoder(channel_id, channels); } ViEChannelManagerScoped::ViEChannelManagerScoped( diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_channel_manager.h b/media/webrtc/trunk/webrtc/video_engine/vie_channel_manager.h index f2a64bd340..f6eb9dab4c 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_channel_manager.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_channel_manager.h @@ -15,16 +15,15 @@ #include #include "webrtc/engine_configurations.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/typedefs.h" #include "webrtc/video_engine/include/vie_rtp_rtcp.h" -#include "webrtc/video_engine/vie_channel_group.h" #include "webrtc/video_engine/vie_defines.h" #include "webrtc/video_engine/vie_manager_base.h" #include "webrtc/video_engine/vie_remb.h" namespace webrtc { +class ChannelGroup; class Config; class CriticalSectionWrapper; class ProcessThread; @@ -36,8 +35,6 @@ class VoiceEngine; typedef std::list ChannelGroups; typedef std::list ChannelList; -typedef std::map ChannelMap; -typedef std::map EncoderMap; class ViEChannelManager: private ViEManagerBase { friend class ViEChannelManagerScoped; @@ -58,7 +55,11 @@ class ViEChannelManager: private ViEManagerBase { // Creates a new channel grouped with |original_channel|. The new channel // will get its own |ViEEncoder| if |sender| is set to true. It will be a // receive only channel, without an own |ViEEncoder| if |sender| is false. - int CreateChannel(int* channel_id, int original_channel, bool sender); + // Doesn't internally allocate an encoder if |disable_default_encoder|. + int CreateChannel(int* channel_id, + int original_channel, + bool sender, + bool disable_default_encoder); // Deletes a channel. int DeleteChannel(int channel_id); @@ -72,8 +73,6 @@ class ViEChannelManager: private ViEManagerBase { // Disables lip sync of the channel. int DisconnectVoiceChannel(int channel_id); - VoiceEngine* GetVoiceEngine(); - // Adds a channel to include when sending REMB. bool SetRembStatus(int channel_id, bool sender, bool receiver); @@ -84,26 +83,21 @@ class ViEChannelManager: private ViEManagerBase { // it will simply be ignored and no error is returned. void UpdateSsrcs(int channel_id, const std::list& ssrcs); - // Sets bandwidth estimation related configurations. - bool SetBandwidthEstimationConfig(int channel_id, - const webrtc::Config& config); - bool GetEstimatedSendBandwidth(int channel_id, uint32_t* estimated_bandwidth) const; bool GetEstimatedReceiveBandwidth(int channel_id, uint32_t* estimated_bandwidth) const; - private: - // Creates a channel object connected to |vie_encoder|. Assumed to be called - // protected. - bool CreateChannelObject(int channel_id, - ViEEncoder* vie_encoder, - RtcpBandwidthObserver* bandwidth_observer, - RemoteBitrateEstimator* remote_bitrate_estimator, - RtcpRttStats* rtcp_rtt_stats, - RtcpIntraFrameObserver* intra_frame_observer, - bool sender); + bool GetPacerQueuingDelayMs(int channel_id, int64_t* delay_ms) const; + bool SetBitrateConfig(int channel_id, + int min_bitrate_bps, + int start_bitrate_bps, + int max_bitrate_bps); + + bool ReAllocateBitrates(int channel_id); + + private: // Used by ViEChannelScoped, forcing a manager user to use scoped. // Returns a pointer to the channel with id 'channel_id'. ViEChannel* ViEChannelPtr(int channel_id) const; @@ -131,8 +125,6 @@ class ViEChannelManager: private ViEManagerBase { int engine_id_; int number_of_cores_; - // TODO(mflodman) Make part of channel group. - ChannelMap channel_map_; bool* free_channel_ids_; int free_channel_ids_size_; @@ -140,13 +132,9 @@ class ViEChannelManager: private ViEManagerBase { std::list channel_groups_; // TODO(mflodman) Make part of channel group. - // Maps Channel id -> ViEEncoder. - EncoderMap vie_encoder_map_; VoEVideoSync* voice_sync_interface_; - VoiceEngine* voice_engine_; ProcessThread* module_process_thread_; - const Config& engine_config_; CPULoadStateCallbackInvoker* load_manager_; }; diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_codec_impl.cc b/media/webrtc/trunk/webrtc/video_engine/vie_codec_impl.cc index 3b1bce5019..b4c1b8c9d4 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_codec_impl.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_codec_impl.cc @@ -189,22 +189,21 @@ int ViECodecImpl::SetSendCodec(const int video_channel, LOG(LS_INFO) << "New max bitrate set " << video_codec_internal.maxBitrate; } - if (video_codec_internal.startBitrate < video_codec_internal.minBitrate) { - video_codec_internal.startBitrate = video_codec_internal.minBitrate; + if (video_codec_internal.startBitrate > 0) { + if (video_codec_internal.startBitrate < video_codec_internal.minBitrate) { + video_codec_internal.startBitrate = video_codec_internal.minBitrate; + } + if (video_codec_internal.startBitrate > video_codec_internal.maxBitrate) { + video_codec_internal.startBitrate = video_codec_internal.maxBitrate; + } } - if (video_codec_internal.startBitrate > video_codec_internal.maxBitrate) { - video_codec_internal.startBitrate = video_codec_internal.maxBitrate; - } - - VideoCodec encoder; - vie_encoder->GetEncoder(&encoder); // Make sure to generate a new SSRC if the codec type and/or resolution has // changed. This won't have any effect if the user has set an SSRC. - bool new_rtp_stream = false; - if (encoder.codecType != video_codec_internal.codecType) { - new_rtp_stream = true; - } + bool new_rtp_stream = true; + VideoCodec encoder; + if (vie_encoder->GetEncoder(&encoder) == 0) + new_rtp_stream = encoder.codecType != video_codec_internal.codecType; ViEInputManagerScoped is(*(shared_data_->input_manager())); @@ -254,7 +253,8 @@ int ViECodecImpl::SetSendCodec(const int video_channel, shared_data_->channel_manager()->UpdateSsrcs(video_channel, ssrcs); // Update the protection mode, we might be switching NACK/FEC. - vie_encoder->UpdateProtectionMethod(vie_encoder->nack_enabled()); + vie_encoder->UpdateProtectionMethod(vie_encoder->nack_enabled(), + vie_channel->IsSendingFecEnabled()); // Get new best format for frame provider. ViEFrameProviderBase* frame_provider = is.FrameProvider(vie_encoder); @@ -285,7 +285,7 @@ int ViECodecImpl::SetReceiveCodec(const int video_channel, const VideoCodec& video_codec) { LOG(LS_INFO) << "SetReceiveCodec for channel " << video_channel; LOG(LS_INFO) << "Codec type " << video_codec.codecType - << ", payload type " << video_codec.plType; + << ", payload type " << static_cast(video_codec.plType); if (CodecValid(video_codec) == false) { shared_data_->SetLastError(kViECodecInvalidCodec); @@ -412,6 +412,12 @@ int ViECodecImpl::GetReceiveSideDelay(const int video_channel, return 0; } +uint32_t ViECodecImpl::GetLastObservedBitrateBps(int video_channel) const { + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEEncoder* vie_encoder = cs.Encoder(video_channel); + assert(vie_encoder != nullptr); + return vie_encoder->LastObservedBitrateBps(); +} int ViECodecImpl::GetCodecTargetBitrate(const int video_channel, unsigned int* bitrate) const { @@ -661,7 +667,8 @@ bool ViECodecImpl::CodecValid(const VideoCodec& video_codec) { } if (video_codec.plType == 0 || video_codec.plType > 127) { - LOG(LS_ERROR) << "Invalif payload type: " << video_codec.plType; + LOG(LS_ERROR) << "Invalid payload type: " + << static_cast(video_codec.plType); return false; } @@ -672,7 +679,8 @@ bool ViECodecImpl::CodecValid(const VideoCodec& video_codec) { return false; } - if (video_codec.startBitrate < kViEMinCodecBitrate) { + if (video_codec.startBitrate > 0 && + video_codec.startBitrate < kViEMinCodecBitrate) { LOG(LS_ERROR) << "Invalid start bitrate."; return false; } diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_codec_impl.h b/media/webrtc/trunk/webrtc/video_engine/vie_codec_impl.h index 93b9a29a17..51537b4685 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_codec_impl.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_codec_impl.h @@ -51,6 +51,7 @@ class ViECodecImpl unsigned int& delta_frames) const; virtual int GetReceiveSideDelay(const int video_channel, int* delay_ms) const; + uint32_t GetLastObservedBitrateBps(int video_channel) const override; virtual int GetCodecTargetBitrate(const int video_channel, unsigned int* bitrate) const; virtual int GetNumDiscardedPackets(int video_channel) const; diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_encoder.cc b/media/webrtc/trunk/webrtc/video_engine/vie_encoder.cc index ba089e6b61..84b68fc160 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_encoder.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_encoder.cc @@ -14,10 +14,11 @@ #include +#include "webrtc/base/checks.h" #include "webrtc/common_video/interface/video_image.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" +#include "webrtc/frame_callback.h" #include "webrtc/modules/pacing/include/paced_sender.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" #include "webrtc/modules/utility/interface/process_thread.h" #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" #include "webrtc/modules/video_coding/main/interface/video_coding.h" @@ -29,9 +30,10 @@ #include "webrtc/system_wrappers/interface/metrics.h" #include "webrtc/system_wrappers/interface/tick_util.h" #include "webrtc/system_wrappers/interface/trace_event.h" +#include "webrtc/video/send_statistics_proxy.h" #include "webrtc/video_engine/include/vie_codec.h" #include "webrtc/video_engine/include/vie_image_process.h" -#include "webrtc/frame_callback.h" +#include "webrtc/video_engine/payload_router.h" #include "webrtc/video_engine/vie_defines.h" namespace webrtc { @@ -43,12 +45,6 @@ static const float kEncoderPausePacerMargin = 2.0f; // Don't stop the encoder unless the delay is above this configured value. static const int kMinPacingDelayMs = 200; -// Allow packets to be transmitted in up to 2 times max video bitrate if the -// bandwidth estimate allows it. -// TODO(holmer): Expose transmission start, min and max bitrates in the -// VideoEngine API and remove the kTransmissionMaxBitrateMultiplier. -static const int kTransmissionMaxBitrateMultiplier = 2; - static const float kStopPaddingThresholdMs = 2000; std::vector AllocateStreamBitrates( @@ -95,35 +91,15 @@ class ViEBitrateObserver : public BitrateObserver { } virtual ~ViEBitrateObserver() {} // Implements BitrateObserver. - virtual void OnNetworkChanged(const uint32_t bitrate_bps, - const uint8_t fraction_lost, - const uint32_t rtt) { + virtual void OnNetworkChanged(uint32_t bitrate_bps, + uint8_t fraction_lost, + int64_t rtt) { owner_->OnNetworkChanged(bitrate_bps, fraction_lost, rtt); } private: ViEEncoder* owner_; }; -class ViEPacedSenderCallback : public PacedSender::Callback { - public: - explicit ViEPacedSenderCallback(ViEEncoder* owner) - : owner_(owner) { - } - virtual ~ViEPacedSenderCallback() {} - virtual bool TimeToSendPacket(uint32_t ssrc, - uint16_t sequence_number, - int64_t capture_time_ms, - bool retransmission) { - return owner_->TimeToSendPacket(ssrc, sequence_number, capture_time_ms, - retransmission); - } - virtual int TimeToSendPadding(int bytes) { - return owner_->TimeToSendPadding(bytes); - } - private: - ViEEncoder* owner_; -}; - class ViECPULoadStateObserver : public CPULoadStateObserver { public: explicit ViECPULoadStateObserver(ViEEncoder* owner) @@ -139,56 +115,51 @@ class ViECPULoadStateObserver : public CPULoadStateObserver { ViEEncoder* owner_; }; -ViEEncoder::ViEEncoder(int32_t engine_id, - int32_t channel_id, +ViEEncoder::ViEEncoder(int32_t channel_id, uint32_t number_of_cores, const Config& config, ProcessThread& module_process_thread, - BitrateController* bitrate_controller) - : engine_id_(engine_id), - channel_id_(channel_id), - number_of_cores_(number_of_cores), - vcm_(*webrtc::VideoCodingModule::Create()), - vpm_(*webrtc::VideoProcessingModule::Create(ViEModuleId(engine_id, - channel_id))), - callback_cs_(CriticalSectionWrapper::CreateCriticalSection()), - data_cs_(CriticalSectionWrapper::CreateCriticalSection()), - bitrate_controller_(bitrate_controller), - time_of_last_incoming_frame_ms_(0), - load_manager_(NULL), - send_padding_(false), - min_transmit_bitrate_kbps_(0), - target_delay_ms_(0), - network_is_transmitting_(true), - encoder_paused_(false), - encoder_paused_and_dropped_frame_(false), - fec_enabled_(false), - nack_enabled_(false), - codec_observer_(NULL), - effect_filter_(NULL), - module_process_thread_(module_process_thread), - has_received_sli_(false), - picture_id_sli_(0), - has_received_rpsi_(false), - picture_id_rpsi_(0), - qm_callback_(NULL), - video_suspended_(false), - pre_encode_callback_(NULL), - start_ms_(Clock::GetRealTimeClock()->TimeInMilliseconds()) { - RtpRtcp::Configuration configuration; - configuration.id = ViEModuleId(engine_id_, channel_id_); - configuration.audio = false; // Video. - - default_rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(configuration)); + PacedSender* pacer, + BitrateAllocator* bitrate_allocator, + BitrateController* bitrate_controller, + bool disable_default_encoder) + : channel_id_(channel_id), + number_of_cores_(number_of_cores), + disable_default_encoder_(disable_default_encoder), + vcm_(*webrtc::VideoCodingModule::Create(this)), + vpm_(*webrtc::VideoProcessingModule::Create(ViEModuleId(-1, channel_id))), + send_payload_router_(NULL), + vcm_protection_callback_(NULL), + callback_cs_(CriticalSectionWrapper::CreateCriticalSection()), + data_cs_(CriticalSectionWrapper::CreateCriticalSection()), + pacer_(pacer), + bitrate_allocator_(bitrate_allocator), + bitrate_controller_(bitrate_controller), + time_of_last_incoming_frame_ms_(0), + load_manager_(NULL), + send_padding_(false), + min_transmit_bitrate_kbps_(0), + last_observed_bitrate_bps_(0), + target_delay_ms_(0), + network_is_transmitting_(true), + encoder_paused_(false), + encoder_paused_and_dropped_frame_(false), + fec_enabled_(false), + nack_enabled_(false), + codec_observer_(NULL), + effect_filter_(NULL), + module_process_thread_(module_process_thread), + has_received_sli_(false), + picture_id_sli_(0), + has_received_rpsi_(false), + picture_id_rpsi_(0), + qm_callback_(NULL), + video_suspended_(false), + pre_encode_callback_(NULL), + start_ms_(Clock::GetRealTimeClock()->TimeInMilliseconds()), + send_statistics_proxy_(NULL) { bitrate_observer_.reset(new ViEBitrateObserver(this)); - pacing_callback_.reset(new ViEPacedSenderCallback(this)); loadstate_observer_.reset(new ViECPULoadStateObserver(this)); - paced_sender_.reset(new PacedSender( - Clock::GetRealTimeClock(), - pacing_callback_.get(), - kDefaultStartBitrateKbps, - PacedSender::kDefaultPaceMultiplier * kDefaultStartBitrateKbps, - 0)); } bool ViEEncoder::Init() { @@ -200,36 +171,29 @@ bool ViEEncoder::Init() { // Enable content analysis if load management enabled vpm_.EnableContentAnalysis(load_manager_ != NULL); - if (module_process_thread_.RegisterModule(&vcm_) != 0 || - module_process_thread_.RegisterModule(default_rtp_rtcp_.get()) != 0 || - module_process_thread_.RegisterModule(paced_sender_.get()) != 0) { - return false; - } if (qm_callback_) { delete qm_callback_; } qm_callback_ = new QMVideoSettingsCallback(&vpm_); + if (!disable_default_encoder_) { #ifdef VIDEOCODEC_VP8 - VideoCodecType codec_type = webrtc::kVideoCodecVP8; + VideoCodecType codec_type = webrtc::kVideoCodecVP8; #else - VideoCodecType codec_type = webrtc::kVideoCodecI420; + VideoCodecType codec_type = webrtc::kVideoCodecI420; #endif - - VideoCodec video_codec; - if (vcm_.Codec(codec_type, &video_codec) != VCM_OK) { - return false; - } - { - CriticalSectionScoped cs(data_cs_.get()); - send_padding_ = video_codec.numberOfSimulcastStreams > 1; - } - if (vcm_.RegisterSendCodec(&video_codec, number_of_cores_, - default_rtp_rtcp_->MaxDataPayloadLength()) != 0) { - return false; - } - if (default_rtp_rtcp_->RegisterSendPayload(video_codec) != 0) { - return false; + VideoCodec video_codec; + if (vcm_.Codec(codec_type, &video_codec) != VCM_OK) { + return false; + } + { + CriticalSectionScoped cs(data_cs_.get()); + send_padding_ = video_codec.numberOfSimulcastStreams > 1; + } + if (vcm_.RegisterSendCodec(&video_codec, number_of_cores_, + PayloadRouter::DefaultMaxPayloadLength()) != 0) { + return false; + } } if (vcm_.RegisterTransportCallback(this) != 0) { return false; @@ -243,6 +207,25 @@ bool ViEEncoder::Init() { return true; } +void ViEEncoder::StartThreadsAndSetSharedMembers( + scoped_refptr send_payload_router, + VCMProtectionCallback* vcm_protection_callback) { + DCHECK(send_payload_router_ == NULL); + DCHECK(vcm_protection_callback_ == NULL); + + send_payload_router_ = send_payload_router; + vcm_protection_callback_ = vcm_protection_callback; + + module_process_thread_.RegisterModule(&vcm_); +} + +void ViEEncoder::StopThreadsAndRemoveSharedMembers() { + vcm_.RegisterProtectionCallback(NULL); + vcm_protection_callback_ = NULL; + module_process_thread_.DeRegisterModule(&vcm_); + module_process_thread_.DeRegisterModule(&vpm_); +} + void ViEEncoder::SetLoadManager(CPULoadStateCallbackInvoker* load_manager) { load_manager_ = load_manager; if (load_manager_) { @@ -253,26 +236,20 @@ void ViEEncoder::SetLoadManager(CPULoadStateCallbackInvoker* load_manager) { ViEEncoder::~ViEEncoder() { UpdateHistograms(); - if (bitrate_controller_) { - bitrate_controller_->RemoveBitrateObserver(bitrate_observer_.get()); - } + if (bitrate_allocator_) + bitrate_allocator_->RemoveBitrateObserver(bitrate_observer_.get()); if (load_manager_) { load_manager_->RemoveObserver(loadstate_observer_.get()); } - module_process_thread_.DeRegisterModule(&vcm_); - module_process_thread_.DeRegisterModule(&vpm_); - module_process_thread_.DeRegisterModule(default_rtp_rtcp_.get()); - module_process_thread_.DeRegisterModule(paced_sender_.get()); VideoCodingModule::Destroy(&vcm_); VideoProcessingModule::Destroy(&vpm_); delete qm_callback_; } void ViEEncoder::UpdateHistograms() { - const float kMinCallLengthInMinutes = 0.5f; - float elapsed_minutes = - (Clock::GetRealTimeClock()->TimeInMilliseconds() - start_ms_) / 60000.0f; - if (elapsed_minutes < kMinCallLengthInMinutes) { + int64_t elapsed_sec = + (Clock::GetRealTimeClock()->TimeInMilliseconds() - start_ms_) / 1000; + if (elapsed_sec < metrics::kMinRunTimeInSeconds) { return; } webrtc::VCMFrameCount frames; @@ -297,9 +274,9 @@ void ViEEncoder::SetNetworkTransmissionState(bool is_transmitting) { network_is_transmitting_ = is_transmitting; } if (is_transmitting) { - paced_sender_->Resume(); + pacer_->Resume(); } else { - paced_sender_->Pause(); + pacer_->Pause(); } } @@ -338,6 +315,7 @@ int32_t ViEEncoder::RegisterExternalEncoder(webrtc::VideoEncoder* encoder, } int32_t ViEEncoder::DeRegisterExternalEncoder(uint8_t pl_type) { + DCHECK(send_payload_router_ != NULL); webrtc::VideoCodec current_send_codec; if (vcm_.SendCodec(¤t_send_codec) == VCM_OK) { uint32_t current_bitrate_bps = 0; @@ -351,11 +329,12 @@ int32_t ViEEncoder::DeRegisterExternalEncoder(uint8_t pl_type) { return -1; } + if (disable_default_encoder_) + return 0; + // If the external encoder is the current send codec, use vcm internal // encoder. if (current_send_codec.plType == pl_type) { - uint16_t max_data_payload_length = - default_rtp_rtcp_->MaxDataPayloadLength(); { CriticalSectionScoped cs(data_cs_.get()); send_padding_ = current_send_codec.numberOfSimulcastStreams > 1; @@ -365,6 +344,7 @@ int32_t ViEEncoder::DeRegisterExternalEncoder(uint8_t pl_type) { // a hack to prevent the following code from crashing. This should be fixed // for realz. https://code.google.com/p/chromium/issues/detail?id=348222 current_send_codec.extra_options = NULL; + size_t max_data_payload_length = send_payload_router_->MaxPayloadLength(); if (vcm_.RegisterSendCodec(¤t_send_codec, number_of_cores_, max_data_payload_length) != VCM_OK) { LOG(LS_INFO) << "De-registered the currently used external encoder (" @@ -377,63 +357,58 @@ int32_t ViEEncoder::DeRegisterExternalEncoder(uint8_t pl_type) { } int32_t ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec) { + DCHECK(send_payload_router_ != NULL); // Setting target width and height for VPM. if (vpm_.SetTargetResolution(video_codec.width, video_codec.height, video_codec.maxFramerate) != VPM_OK) { return -1; } - if (default_rtp_rtcp_->RegisterSendPayload(video_codec) != 0) { - return -1; - } - // Convert from kbps to bps. - std::vector stream_bitrates = AllocateStreamBitrates( - video_codec.startBitrate * 1000, - video_codec.simulcastStream, - video_codec.numberOfSimulcastStreams); - default_rtp_rtcp_->SetTargetSendBitrate(stream_bitrates); - - uint16_t max_data_payload_length = - default_rtp_rtcp_->MaxDataPayloadLength(); - { CriticalSectionScoped cs(data_cs_.get()); send_padding_ = video_codec.numberOfSimulcastStreams > 1; } - if (vcm_.RegisterSendCodec(&video_codec, number_of_cores_, + + // Add a bitrate observer to the allocator and update the start, max and + // min bitrates of the bitrate controller as needed. + int allocated_bitrate_bps; + int new_bwe_candidate_bps = bitrate_allocator_->AddBitrateObserver( + bitrate_observer_.get(), video_codec.startBitrate * 1000, + video_codec.minBitrate * 1000, video_codec.maxBitrate * 1000, + &allocated_bitrate_bps); + + // Only set the start/min/max bitrate of the bitrate controller if the start + // bitrate is greater than zero. The new API sets these via the channel group + // and passes a zero start bitrate to SetSendCodec. + // TODO(holmer): Remove this when the new API has been launched. + if (video_codec.startBitrate > 0) { + if (new_bwe_candidate_bps > 0) { + uint32_t current_bwe_bps = 0; + bitrate_controller_->AvailableBandwidth(¤t_bwe_bps); + bitrate_controller_->SetStartBitrate(std::max( + static_cast(new_bwe_candidate_bps), current_bwe_bps)); + } + + int new_bwe_min_bps = 0; + int new_bwe_max_bps = 0; + bitrate_allocator_->GetMinMaxBitrateSumBps(&new_bwe_min_bps, + &new_bwe_max_bps); + bitrate_controller_->SetMinMaxBitrate(new_bwe_min_bps, new_bwe_max_bps); + } + + webrtc::VideoCodec modified_video_codec = video_codec; + modified_video_codec.startBitrate = allocated_bitrate_bps / 1000; + + size_t max_data_payload_length = send_payload_router_->MaxPayloadLength(); + if (vcm_.RegisterSendCodec(&modified_video_codec, number_of_cores_, max_data_payload_length) != VCM_OK) { return -1; } - - // Set this module as sending right away, let the slave module in the channel - // start and stop sending. - if (default_rtp_rtcp_->SetSendingStatus(true) != 0) { - return -1; - } - - bitrate_controller_->SetBitrateObserver(bitrate_observer_.get(), - video_codec.startBitrate * 1000, - video_codec.minBitrate * 1000, - kTransmissionMaxBitrateMultiplier * - video_codec.maxBitrate * 1000); - - CriticalSectionScoped crit(data_cs_.get()); - int pad_up_to_bitrate_kbps = video_codec.startBitrate; - if (pad_up_to_bitrate_kbps < min_transmit_bitrate_kbps_) - pad_up_to_bitrate_kbps = min_transmit_bitrate_kbps_; - - paced_sender_->UpdateBitrate( - video_codec.startBitrate, - PacedSender::kDefaultPaceMultiplier * video_codec.startBitrate, - pad_up_to_bitrate_kbps); - return 0; } int32_t ViEEncoder::GetEncoder(VideoCodec* video_codec) { - if (vcm_.SendCodec(video_codec) != 0) { - return -1; - } + *video_codec = vcm_.GetSendCodec(); return 0; } @@ -463,25 +438,64 @@ int32_t ViEEncoder::ScaleInputImage(bool enable) { return 0; } -bool ViEEncoder::TimeToSendPacket(uint32_t ssrc, - uint16_t sequence_number, - int64_t capture_time_ms, - bool retransmission) { - return default_rtp_rtcp_->TimeToSendPacket(ssrc, sequence_number, - capture_time_ms, retransmission); -} - -int ViEEncoder::TimeToSendPadding(int bytes) { - bool send_padding; +int ViEEncoder::GetPaddingNeededBps(int bitrate_bps) const { + int64_t time_of_last_incoming_frame_ms; + int min_transmit_bitrate_bps; { CriticalSectionScoped cs(data_cs_.get()); - send_padding = + bool send_padding = send_padding_ || video_suspended_ || min_transmit_bitrate_kbps_ > 0; + if (!send_padding) + return 0; + time_of_last_incoming_frame_ms = time_of_last_incoming_frame_ms_; + min_transmit_bitrate_bps = 1000 * min_transmit_bitrate_kbps_; } - if (send_padding) { - return default_rtp_rtcp_->TimeToSendPadding(bytes); + + VideoCodec send_codec; + if (vcm_.SendCodec(&send_codec) != 0) + return 0; + SimulcastStream* stream_configs = send_codec.simulcastStream; + // Allocate the bandwidth between the streams. + std::vector stream_bitrates = AllocateStreamBitrates( + bitrate_bps, stream_configs, send_codec.numberOfSimulcastStreams); + + bool video_is_suspended = vcm_.VideoSuspended(); + + // Find the max amount of padding we can allow ourselves to send at this + // point, based on which streams are currently active and what our current + // available bandwidth is. + int pad_up_to_bitrate_bps = 0; + if (send_codec.numberOfSimulcastStreams == 0) { + pad_up_to_bitrate_bps = send_codec.minBitrate * 1000; + } else { + pad_up_to_bitrate_bps = + stream_configs[send_codec.numberOfSimulcastStreams - 1].minBitrate * + 1000; + for (int i = 0; i < send_codec.numberOfSimulcastStreams - 1; ++i) { + pad_up_to_bitrate_bps += stream_configs[i].targetBitrate * 1000; + } } - return 0; + + // Disable padding if only sending one stream and video isn't suspended and + // min-transmit bitrate isn't used (applied later). + if (!video_is_suspended && send_codec.numberOfSimulcastStreams <= 1) + pad_up_to_bitrate_bps = 0; + + // The amount of padding should decay to zero if no frames are being + // captured unless a min-transmit bitrate is used. + int64_t now_ms = TickTime::MillisecondTimestamp(); + if (now_ms - time_of_last_incoming_frame_ms > kStopPaddingThresholdMs) + pad_up_to_bitrate_bps = 0; + + // Pad up to min bitrate. + if (pad_up_to_bitrate_bps < min_transmit_bitrate_bps) + pad_up_to_bitrate_bps = min_transmit_bitrate_bps; + + // Padding may never exceed bitrate estimate. + if (pad_up_to_bitrate_bps > bitrate_bps) + pad_up_to_bitrate_bps = bitrate_bps; + + return pad_up_to_bitrate_bps; } bool ViEEncoder::EncoderPaused() const { @@ -494,12 +508,12 @@ bool ViEEncoder::EncoderPaused() const { // Buffered mode. // TODO(pwestin): Workaround until nack is configured as a time and not // number of packets. - return paced_sender_->QueueInMs() >= - std::max(static_cast(target_delay_ms_ * kEncoderPausePacerMargin), - kMinPacingDelayMs); + return pacer_->QueueInMs() >= + std::max( + static_cast(target_delay_ms_ * kEncoderPausePacerMargin), + kMinPacingDelayMs); } - if (paced_sender_->ExpectedQueueTimeMs() > - PacedSender::kDefaultMaxQueueLengthMs) { + if (pacer_->ExpectedQueueTimeMs() > PacedSender::kDefaultMaxQueueLengthMs) { // Too much data in pacer queue, drop frame. return true; } @@ -523,16 +537,14 @@ void ViEEncoder::TraceFrameDropEnd() { encoder_paused_and_dropped_frame_ = false; } -RtpRtcp* ViEEncoder::SendRtpRtcpModule() { - return default_rtp_rtcp_.get(); -} - void ViEEncoder::DeliverFrame(int id, I420VideoFrame* video_frame, - int num_csrcs, - const uint32_t CSRC[kRtpCsrcSize]) { - if (default_rtp_rtcp_->SendingMedia() == false) { - // We've paused or we have no channels attached, don't encode. + const std::vector& csrcs) { + DCHECK(send_payload_router_ != NULL); + DCHECK(csrcs.empty()); + if (!send_payload_router_->active()) { + // We've paused or we have no channels attached, don't waste resources on + // encoding. return; } { @@ -545,38 +557,17 @@ void ViEEncoder::DeliverFrame(int id, TraceFrameDropEnd(); } - // Convert render time, in ms, to RTP timestamp. - const int kMsToRtpTimestamp = 90; - const uint32_t time_stamp = - kMsToRtpTimestamp * - static_cast(video_frame->render_time_ms()); - TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame->render_time_ms(), "Encode"); - video_frame->set_timestamp(time_stamp); - - // Make sure the CSRC list is correct. - if (num_csrcs > 0) { - uint32_t tempCSRC[kRtpCsrcSize]; - for (int i = 0; i < num_csrcs; i++) { - if (CSRC[i] == 1) { - tempCSRC[i] = default_rtp_rtcp_->SSRC(); - } else { - tempCSRC[i] = CSRC[i]; - } - } - default_rtp_rtcp_->SetCSRCs(tempCSRC, (uint8_t) num_csrcs); - } - I420VideoFrame* decimated_frame = NULL; // TODO(wuchengli): support texture frames. if (video_frame->native_handle() == NULL) { { CriticalSectionScoped cs(callback_cs_.get()); if (effect_filter_) { - unsigned int length = + size_t length = CalcBufferSize(kI420, video_frame->width(), video_frame->height()); - scoped_ptr video_buffer(new uint8_t[length]); + rtc::scoped_ptr video_buffer(new uint8_t[length]); ExtractBuffer(*video_frame, length, video_buffer.get()); effect_filter_->Transform(length, video_buffer.get(), @@ -654,7 +645,6 @@ void ViEEncoder::DeliverFrame(int id, } void ViEEncoder::DelayChanged(int id, int frame_delay) { - default_rtp_rtcp_->SetCameraDelay(frame_delay); } int ViEEncoder::GetPreferedFrameSettings(int* width, @@ -687,8 +677,9 @@ int32_t ViEEncoder::SendCodecStatistics( return 0; } -int32_t ViEEncoder::PacerQueuingDelayMs() const { - return paced_sender_->QueueInMs(); +uint32_t ViEEncoder::LastObservedBitrateBps() const { + CriticalSectionScoped cs(data_cs_.get()); + return last_observed_bitrate_bps_; } int ViEEncoder::CodecTargetBitrate(uint32_t* bitrate) const { @@ -697,28 +688,19 @@ int ViEEncoder::CodecTargetBitrate(uint32_t* bitrate) const { return 0; } -int32_t ViEEncoder::UpdateProtectionMethod(bool enable_nack) { - bool fec_enabled = false; - uint8_t dummy_ptype_red = 0; - uint8_t dummy_ptypeFEC = 0; +int32_t ViEEncoder::UpdateProtectionMethod(bool nack, bool fec) { + DCHECK(send_payload_router_ != NULL); + DCHECK(vcm_protection_callback_ != NULL); - // Updated protection method to VCM to get correct packetization sizes. - // FEC has larger overhead than NACK -> set FEC if used. - int32_t error = default_rtp_rtcp_->GenericFECStatus(fec_enabled, - dummy_ptype_red, - dummy_ptypeFEC); - if (error) { - return -1; - } - if (fec_enabled_ == fec_enabled && nack_enabled_ == enable_nack) { + if (fec_enabled_ == fec && nack_enabled_ == nack) { // No change needed, we're already in correct state. return 0; } - fec_enabled_ = fec_enabled; - nack_enabled_ = enable_nack; + fec_enabled_ = fec; + nack_enabled_ = nack; // Set Video Protection for VCM. - if (fec_enabled && nack_enabled_) { + if (fec_enabled_ && nack_enabled_) { vcm_.SetVideoProtection(webrtc::kProtectionNackFEC, true); } else { vcm_.SetVideoProtection(webrtc::kProtectionFEC, fec_enabled_); @@ -727,11 +709,10 @@ int32_t ViEEncoder::UpdateProtectionMethod(bool enable_nack) { } if (fec_enabled_ || nack_enabled_) { - vcm_.RegisterProtectionCallback(this); + vcm_.RegisterProtectionCallback(vcm_protection_callback_); // The send codec must be registered to set correct MTU. webrtc::VideoCodec codec; if (vcm_.SendCodec(&codec) == 0) { - uint16_t max_pay_load = default_rtp_rtcp_->MaxDataPayloadLength(); uint32_t current_bitrate_bps = 0; if (vcm_.Bitrate(¤t_bitrate_bps) != 0) { LOG_F(LS_WARNING) << @@ -739,7 +720,9 @@ int32_t ViEEncoder::UpdateProtectionMethod(bool enable_nack) { } // Convert to start bitrate in kbps. codec.startBitrate = (current_bitrate_bps + 500) / 1000; - if (vcm_.RegisterSendCodec(&codec, number_of_cores_, max_pay_load) != 0) { + size_t max_payload_length = send_payload_router_->MaxPayloadLength(); + if (vcm_.RegisterSendCodec(&codec, number_of_cores_, + max_payload_length) != 0) { return -1; } } @@ -767,36 +750,30 @@ void ViEEncoder::SetSenderBufferingMode(int target_delay_ms) { } } -int32_t ViEEncoder::SendData( - const FrameType frame_type, - const uint8_t payload_type, - const uint32_t time_stamp, - int64_t capture_time_ms, - const uint8_t* payload_data, - const uint32_t payload_size, - const webrtc::RTPFragmentationHeader& fragmentation_header, - const RTPVideoHeader* rtp_video_hdr) { - // New encoded data, hand over to the rtp module. - return default_rtp_rtcp_->SendOutgoingData(frame_type, - payload_type, - time_stamp, - capture_time_ms, - payload_data, - payload_size, - &fragmentation_header, - rtp_video_hdr); +void ViEEncoder::OnSetRates(uint32_t bitrate_bps, int framerate) { + CriticalSectionScoped cs(callback_cs_.get()); + if (send_statistics_proxy_ != nullptr) + send_statistics_proxy_->OnSetRates(bitrate_bps, framerate); } -int32_t ViEEncoder::ProtectionRequest( - const FecProtectionParams* delta_fec_params, - const FecProtectionParams* key_fec_params, - uint32_t* sent_video_rate_bps, - uint32_t* sent_nack_rate_bps, - uint32_t* sent_fec_rate_bps) { - default_rtp_rtcp_->SetFecParameters(delta_fec_params, key_fec_params); - default_rtp_rtcp_->BitrateSent(NULL, sent_video_rate_bps, sent_fec_rate_bps, - sent_nack_rate_bps); - return 0; +int32_t ViEEncoder::SendData( + const uint8_t payload_type, + const EncodedImage& encoded_image, + const webrtc::RTPFragmentationHeader& fragmentation_header, + const RTPVideoHeader* rtp_video_hdr) { + DCHECK(send_payload_router_ != NULL); + + { + CriticalSectionScoped cs(callback_cs_.get()); + if (send_statistics_proxy_ != NULL) + send_statistics_proxy_->OnSendEncodedImage(encoded_image, rtp_video_hdr); + } + + return send_payload_router_->RoutePayload( + VCMEncodedFrame::ConvertFrameType(encoded_image._frameType), payload_type, + encoded_image._timeStamp, encoded_image.capture_time_ms_, + encoded_image._buffer, encoded_image._length, &fragmentation_header, + rtp_video_hdr) ? 0 : -1; } int32_t ViEEncoder::SendStatistics(const uint32_t bit_rate, @@ -911,15 +888,16 @@ void ViEEncoder::SetMinTransmitBitrate(int min_transmit_bitrate_kbps) { } // Called from ViEBitrateObserver. -void ViEEncoder::OnNetworkChanged(const uint32_t bitrate_bps, - const uint8_t fraction_lost, - const uint32_t round_trip_time_ms) { +void ViEEncoder::OnNetworkChanged(uint32_t bitrate_bps, + uint8_t fraction_lost, + int64_t round_trip_time_ms) { LOG(LS_VERBOSE) << "OnNetworkChanged, bitrate" << bitrate_bps << " packet loss " << fraction_lost << " rtt " << round_trip_time_ms; + DCHECK(send_payload_router_ != NULL); vcm_.SetChannelParameters(bitrate_bps, fraction_lost, round_trip_time_ms); bool video_is_suspended = vcm_.VideoSuspended(); - int bitrate_kbps = bitrate_bps / 1000; + VideoCodec send_codec; if (vcm_.SendCodec(&send_codec) != 0) { return; @@ -927,54 +905,16 @@ void ViEEncoder::OnNetworkChanged(const uint32_t bitrate_bps, SimulcastStream* stream_configs = send_codec.simulcastStream; // Allocate the bandwidth between the streams. std::vector stream_bitrates = AllocateStreamBitrates( - bitrate_bps, - stream_configs, - send_codec.numberOfSimulcastStreams); - // Find the max amount of padding we can allow ourselves to send at this - // point, based on which streams are currently active and what our current - // available bandwidth is. - int pad_up_to_bitrate_kbps = 0; - if (send_codec.numberOfSimulcastStreams == 0) { - pad_up_to_bitrate_kbps = send_codec.minBitrate; - } else { - pad_up_to_bitrate_kbps = - stream_configs[send_codec.numberOfSimulcastStreams - 1].minBitrate; - for (int i = 0; i < send_codec.numberOfSimulcastStreams - 1; ++i) { - pad_up_to_bitrate_kbps += stream_configs[i].targetBitrate; - } - } - - // Disable padding if only sending one stream and video isn't suspended and - // min-transmit bitrate isn't used (applied later). - if (!video_is_suspended && send_codec.numberOfSimulcastStreams <= 1) - pad_up_to_bitrate_kbps = 0; + bitrate_bps, stream_configs, send_codec.numberOfSimulcastStreams); + send_payload_router_->SetTargetSendBitrates(stream_bitrates); { CriticalSectionScoped cs(data_cs_.get()); - // The amount of padding should decay to zero if no frames are being - // captured unless a min-transmit bitrate is used. - int64_t now_ms = TickTime::MillisecondTimestamp(); - if (now_ms - time_of_last_incoming_frame_ms_ > kStopPaddingThresholdMs) - pad_up_to_bitrate_kbps = 0; - - // Pad up to min bitrate. - if (pad_up_to_bitrate_kbps < min_transmit_bitrate_kbps_) - pad_up_to_bitrate_kbps = min_transmit_bitrate_kbps_; - - // Padding may never exceed bitrate estimate. - if (pad_up_to_bitrate_kbps > bitrate_kbps) - pad_up_to_bitrate_kbps = bitrate_kbps; - - paced_sender_->UpdateBitrate( - bitrate_kbps, - PacedSender::kDefaultPaceMultiplier * bitrate_kbps, - pad_up_to_bitrate_kbps); - default_rtp_rtcp_->SetTargetSendBitrate(stream_bitrates); + last_observed_bitrate_bps_ = bitrate_bps; if (video_suspended_ == video_is_suspended) return; video_suspended_ = video_is_suspended; } - // Video suspend-state changed, inform codec observer. CriticalSectionScoped crit(callback_cs_.get()); if (codec_observer_) { @@ -989,10 +929,6 @@ void ViEEncoder::onLoadStateChanged(CPULoadState load_state) { vcm_.SetCPULoadState(load_state); } -PacedSender* ViEEncoder::GetPacedSender() { - return paced_sender_.get(); -} - int32_t ViEEncoder::RegisterEffectFilter(ViEEffectFilter* effect_filter) { CriticalSectionScoped cs(callback_cs_.get()); if (effect_filter != NULL && effect_filter_ != NULL) { @@ -1013,7 +949,7 @@ int ViEEncoder::StopDebugRecording() { void ViEEncoder::SuspendBelowMinBitrate() { vcm_.SuspendBelowMinBitrate(); - bitrate_controller_->EnforceMinBitrate(false); + bitrate_allocator_->EnforceMinBitrate(false); } void ViEEncoder::RegisterPreEncodeCallback( @@ -1036,6 +972,12 @@ void ViEEncoder::DeRegisterPostEncodeImageCallback() { vcm_.RegisterPostEncodeImageCallback(NULL); } +void ViEEncoder::RegisterSendStatisticsProxy( + SendStatisticsProxy* send_statistics_proxy) { + CriticalSectionScoped cs(callback_cs_.get()); + send_statistics_proxy_ = send_statistics_proxy; +} + QMVideoSettingsCallback::QMVideoSettingsCallback(VideoProcessingModule* vpm) : vpm_(vpm) { } diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_encoder.h b/media/webrtc/trunk/webrtc/video_engine/vie_encoder.h index 5f6c7f3f30..44bfa4968f 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_encoder.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_encoder.h @@ -13,16 +13,19 @@ #include #include +#include +#include "webrtc/base/scoped_ptr.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/common_types.h" +#include "webrtc/modules/bitrate_controller/include/bitrate_allocator.h" #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" #include "webrtc/modules/video_coding/main/interface/video_coding_defines.h" #include "webrtc/modules/video_processing/main/interface/video_processing.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/typedefs.h" #include "webrtc/frame_callback.h" +#include "webrtc/system_wrappers/interface/scoped_refptr.h" #include "webrtc/video_engine/vie_defines.h" #include "webrtc/video_engine/vie_frame_provider_base.h" @@ -32,37 +35,50 @@ class Config; class CriticalSectionWrapper; class EncodedImageCallback; class PacedSender; +class PayloadRouter; class ProcessThread; class QMVideoSettingsCallback; -class RtpRtcp; +class SendStatisticsProxy; class ViEBitrateObserver; class ViEEffectFilter; class ViEEncoderObserver; class VideoCodingModule; -class ViEPacedSenderCallback; class ViECPULoadStateObserver; class ViEEncoder : public RtcpIntraFrameObserver, + public VideoEncoderRateObserver, public VCMPacketizationCallback, - public VCMProtectionCallback, public VCMSendStatisticsCallback, public ViEFrameCallback { public: friend class ViEBitrateObserver; - friend class ViEPacedSenderCallback; friend class ViECPULoadStateObserver; - ViEEncoder(int32_t engine_id, - int32_t channel_id, + ViEEncoder(int32_t channel_id, uint32_t number_of_cores, const Config& config, ProcessThread& module_process_thread, - BitrateController* bitrate_controller); + PacedSender* pacer, + BitrateAllocator* bitrate_allocator, + BitrateController* bitrate_controller, + bool disable_default_encoder); ~ViEEncoder(); bool Init(); + // This function is assumed to be called before any frames are delivered and + // only once. + // Ideally this would be done in Init, but the dependencies between ViEEncoder + // and ViEChannel makes it really hard to do in a good way. + void StartThreadsAndSetSharedMembers( + scoped_refptr send_payload_router, + VCMProtectionCallback* vcm_protection_callback); + + // This function must be called before the corresponding ViEChannel is + // deleted. + void StopThreadsAndRemoveSharedMembers(); + void SetNetworkTransmissionState(bool is_transmitting); // Returns the id of the owning channel. @@ -86,73 +102,53 @@ class ViEEncoder unsigned char config_parameters[kConfigParameterSize], unsigned char& config_parameters_size); - PacedSender* GetPacedSender(); - // Scale or crop/pad image. int32_t ScaleInputImage(bool enable); - // RTP settings. - RtpRtcp* SendRtpRtcpModule(); - // Implementing ViEFrameCallback. - virtual void DeliverFrame(int id, - I420VideoFrame* video_frame, - int num_csrcs = 0, - const uint32_t CSRC[kRtpCsrcSize] = NULL) OVERRIDE; - virtual void DelayChanged(int id, int frame_delay) OVERRIDE; - virtual int GetPreferedFrameSettings(int* width, - int* height, - int* frame_rate) OVERRIDE; + void DeliverFrame(int id, + I420VideoFrame* video_frame, + const std::vector& csrcs) override; + void DelayChanged(int id, int frame_delay) override; + int GetPreferedFrameSettings(int* width, + int* height, + int* frame_rate) override; - virtual void ProviderDestroyed(int id) OVERRIDE { - return; - } + void ProviderDestroyed(int id) override { return; } int32_t SendKeyFrame(); int32_t SendCodecStatistics(uint32_t* num_key_frames, uint32_t* num_delta_frames); - int PacerQueuingDelayMs() const; - + uint32_t LastObservedBitrateBps() const; int CodecTargetBitrate(uint32_t* bitrate) const; // Loss protection. - int32_t UpdateProtectionMethod(bool enable_nack); + int32_t UpdateProtectionMethod(bool nack, bool fec); bool nack_enabled() const { return nack_enabled_; } // Buffering mode. void SetSenderBufferingMode(int target_delay_ms); - // Implements VCMPacketizationCallback. - virtual int32_t SendData( - FrameType frame_type, - uint8_t payload_type, - uint32_t time_stamp, - int64_t capture_time_ms, - const uint8_t* payload_data, - uint32_t payload_size, - const RTPFragmentationHeader& fragmentation_header, - const RTPVideoHeader* rtp_video_hdr) OVERRIDE; + // Implements VideoEncoderRateObserver. + void OnSetRates(uint32_t bitrate_bps, int framerate) override; - // Implements VideoProtectionCallback. - virtual int ProtectionRequest( - const FecProtectionParams* delta_fec_params, - const FecProtectionParams* key_fec_params, - uint32_t* sent_video_rate_bps, - uint32_t* sent_nack_rate_bps, - uint32_t* sent_fec_rate_bps) OVERRIDE; + // Implements VCMPacketizationCallback. + int32_t SendData(uint8_t payload_type, + const EncodedImage& encoded_image, + const RTPFragmentationHeader& fragmentation_header, + const RTPVideoHeader* rtp_video_hdr) override; // Implements VideoSendStatisticsCallback. - virtual int32_t SendStatistics(const uint32_t bit_rate, - const uint32_t frame_rate) OVERRIDE; + int32_t SendStatistics(const uint32_t bit_rate, + const uint32_t frame_rate) override; int32_t RegisterCodecObserver(ViEEncoderObserver* observer); // Implements RtcpIntraFrameObserver. - virtual void OnReceivedIntraFrameRequest(uint32_t ssrc) OVERRIDE; - virtual void OnReceivedSLI(uint32_t ssrc, uint8_t picture_id) OVERRIDE; - virtual void OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id) OVERRIDE; - virtual void OnLocalSsrcChanged(uint32_t old_ssrc, - uint32_t new_ssrc) OVERRIDE; + void OnReceivedIntraFrameRequest(uint32_t ssrc) override; + void OnReceivedSLI(uint32_t ssrc, uint8_t picture_id) override; + void OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id) override; + void OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) override; // Sets SSRCs for all streams. bool SetSsrcs(const std::list& ssrcs); @@ -183,21 +179,21 @@ class ViEEncoder EncodedImageCallback* post_encode_callback); void DeRegisterPostEncodeImageCallback(); + void RegisterSendStatisticsProxy(SendStatisticsProxy* send_statistics_proxy); + int channel_id() const { return channel_id_; } + int GetPaddingNeededBps(int bitrate_bps) const; + protected: // Called by BitrateObserver. - void OnNetworkChanged(const uint32_t bitrate_bps, - const uint8_t fraction_lost, - const uint32_t round_trip_time_ms); + void OnNetworkChanged(uint32_t bitrate_bps, + uint8_t fraction_lost, + int64_t round_trip_time_ms); // Called by CPULoadStateObserver void onLoadStateChanged(CPULoadState load_state); - // Called by PacedSender. - bool TimeToSendPacket(uint32_t ssrc, uint16_t sequence_number, - int64_t capture_time_ms, bool retransmission); - int TimeToSendPadding(int bytes); private: bool EncoderPaused() const EXCLUSIVE_LOCKS_REQUIRED(data_cs_); void TraceFrameDropStart() EXCLUSIVE_LOCKS_REQUIRED(data_cs_); @@ -205,27 +201,30 @@ class ViEEncoder void UpdateHistograms(); - int32_t engine_id_; const int channel_id_; const uint32_t number_of_cores_; + const bool disable_default_encoder_; VideoCodingModule& vcm_; VideoProcessingModule& vpm_; - scoped_ptr default_rtp_rtcp_; - scoped_ptr callback_cs_; - scoped_ptr data_cs_; - scoped_ptr bitrate_observer_; - scoped_ptr paced_sender_; - scoped_ptr loadstate_observer_; - scoped_ptr pacing_callback_; + scoped_refptr send_payload_router_; + VCMProtectionCallback* vcm_protection_callback_; - BitrateController* bitrate_controller_; + rtc::scoped_ptr callback_cs_; + rtc::scoped_ptr data_cs_; + rtc::scoped_ptr bitrate_observer_; + rtc::scoped_ptr loadstate_observer_; + + PacedSender* const pacer_; + BitrateAllocator* const bitrate_allocator_; + BitrateController* const bitrate_controller_; // Owned by PeerConnection, not ViEEncoder CPULoadStateCallbackInvoker* load_manager_; int64_t time_of_last_incoming_frame_ms_ GUARDED_BY(data_cs_); bool send_padding_ GUARDED_BY(data_cs_); int min_transmit_bitrate_kbps_ GUARDED_BY(data_cs_); + uint32_t last_observed_bitrate_bps_ GUARDED_BY(data_cs_); int target_delay_ms_ GUARDED_BY(data_cs_); bool network_is_transmitting_ GUARDED_BY(data_cs_); bool encoder_paused_ GUARDED_BY(data_cs_); @@ -251,6 +250,8 @@ class ViEEncoder bool video_suspended_ GUARDED_BY(data_cs_); I420FrameCallback* pre_encode_callback_ GUARDED_BY(callback_cs_); const int64_t start_ms_; + + SendStatisticsProxy* send_statistics_proxy_ GUARDED_BY(callback_cs_); }; } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_external_codec_impl.cc b/media/webrtc/trunk/webrtc/video_engine/vie_external_codec_impl.cc index 7eb015c4b6..1be2d31618 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_external_codec_impl.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_external_codec_impl.cc @@ -99,12 +99,12 @@ int ViEExternalCodecImpl::DeRegisterExternalSendCodec( int ViEExternalCodecImpl::RegisterExternalReceiveCodec( const int video_channel, - const unsigned int pl_type, + const unsigned char pl_type, VideoDecoder* decoder, bool decoder_render, int render_delay) { - LOG(LS_INFO) << "Register exrernal decoder for channel " << video_channel - << ", pl_type " << pl_type + LOG(LS_INFO) << "Register external decoder for channel " << video_channel + << ", pl_type " << static_cast(pl_type) << ", decoder_render " << decoder_render << ", render_delay " << render_delay; assert(decoder != NULL); @@ -127,7 +127,7 @@ int ViEExternalCodecImpl::RegisterExternalReceiveCodec( int ViEExternalCodecImpl::DeRegisterExternalReceiveCodec( const int video_channel, const unsigned char pl_type) { LOG(LS_INFO) << "DeRegisterExternalReceiveCodec for channel " << video_channel - << ", pl_type " << pl_type; + << ", pl_type " << static_cast(pl_type); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_external_codec_impl.h b/media/webrtc/trunk/webrtc/video_engine/vie_external_codec_impl.h index 7c8f4a20fd..da5a445ddf 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_external_codec_impl.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_external_codec_impl.h @@ -31,7 +31,7 @@ class ViEExternalCodecImpl virtual int DeRegisterExternalSendCodec(const int video_channel, const unsigned char pl_type); virtual int RegisterExternalReceiveCodec(const int video_channel, - const unsigned int pl_type, + const unsigned char pl_type, VideoDecoder* decoder, bool decoder_render = false, int render_delay = 0); diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_file_image.cc b/media/webrtc/trunk/webrtc/video_engine/vie_file_image.cc index 919da9fa1b..cb6e206190 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_file_image.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_file_image.cc @@ -74,9 +74,8 @@ int ViEFileImage::ConvertPictureToI420VideoFrame(int engine_id, int half_width = (picture.width + 1) / 2; video_frame->CreateEmptyFrame(picture.width, picture.height, picture.width, half_width, half_width); - return ConvertToI420(kI420, picture.data, 0, 0, - picture.width, picture.height, - 0, kRotateNone, video_frame); + return ConvertToI420(kI420, picture.data, 0, 0, picture.width, picture.height, + 0, kVideoRotation_0, video_frame); } } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_frame_provider_base.cc b/media/webrtc/trunk/webrtc/video_engine/vie_frame_provider_base.cc index a5cd838e2b..d7b453d155 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_frame_provider_base.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_frame_provider_base.cc @@ -12,6 +12,7 @@ #include +#include "webrtc/base/checks.h" #include "webrtc/common_video/interface/i420_video_frame.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/logging.h" @@ -25,52 +26,50 @@ ViEFrameProviderBase::ViEFrameProviderBase(int Id, int engine_id) engine_id_(engine_id), provider_cs_(CriticalSectionWrapper::CreateCriticalSection()), frame_delay_(0) { + frame_delivery_thread_checker_.DetachFromThread(); } ViEFrameProviderBase::~ViEFrameProviderBase() { - if (frame_callbacks_.size() > 0) { - LOG_F(LS_WARNING) << "FrameCallbacks still exist when Provider deleted: " - << frame_callbacks_.size(); - } + DCHECK(thread_checker_.CalledOnValidThread()); + // XXX!!! FIX THIS - remove our callback + // DCHECK(frame_callbacks_.empty()); - for (FrameCallbacks::iterator it = frame_callbacks_.begin(); - it != frame_callbacks_.end(); ++it) { - (*it)->ProviderDestroyed(id_); + // TODO(tommi): Remove this when we're confident we've fixed the places where + // cleanup wasn't being done. + for (ViEFrameCallback* callback : frame_callbacks_) { + LOG_F(LS_WARNING) << "FrameCallback still registered."; + callback->ProviderDestroyed(id_); } - frame_callbacks_.clear(); } -int ViEFrameProviderBase::Id() { +int ViEFrameProviderBase::Id() const { return id_; } -void ViEFrameProviderBase::DeliverFrame( - I420VideoFrame* video_frame, - int num_csrcs, - const uint32_t CSRC[kRtpCsrcSize]) { +void ViEFrameProviderBase::DeliverFrame(I420VideoFrame* video_frame, + const std::vector& csrcs) { + DCHECK(frame_delivery_thread_checker_.CalledOnValidThread()); #ifdef DEBUG_ const TickTime start_process_time = TickTime::Now(); #endif CriticalSectionScoped cs(provider_cs_.get()); // Deliver the frame to all registered callbacks. - if (frame_callbacks_.size() > 0) { - if (frame_callbacks_.size() == 1) { - // We don't have to copy the frame. - frame_callbacks_.front()->DeliverFrame(id_, video_frame, num_csrcs, CSRC); - } else { - for (FrameCallbacks::iterator it = frame_callbacks_.begin(); - it != frame_callbacks_.end(); ++it) { - if (video_frame->native_handle() != NULL) { - (*it)->DeliverFrame(id_, video_frame, num_csrcs, CSRC); - } else { - // Make a copy of the frame for all callbacks. - if (!extra_frame_.get()) { - extra_frame_.reset(new I420VideoFrame()); - } - extra_frame_->CopyFrame(*video_frame); - (*it)->DeliverFrame(id_, extra_frame_.get(), num_csrcs, CSRC); + if (frame_callbacks_.size() == 1) { + // We don't have to copy the frame. + frame_callbacks_.front()->DeliverFrame(id_, video_frame, csrcs); + } else { + for (ViEFrameCallback* callback : frame_callbacks_) { + if (video_frame->native_handle() != NULL) { + callback->DeliverFrame(id_, video_frame, csrcs); + } else { + // Make a copy of the frame for all callbacks. + if (!extra_frame_.get()) { + extra_frame_.reset(new I420VideoFrame()); } + // TODO(mflodman): We can get rid of this frame copy. + extra_frame_->CopyFrame(*video_frame); + callback->DeliverFrame(id_, extra_frame_.get(), csrcs); } } } @@ -85,34 +84,50 @@ void ViEFrameProviderBase::DeliverFrame( } void ViEFrameProviderBase::SetFrameDelay(int frame_delay) { + // Called on the capture thread (see OnIncomingCapturedFrame). + // To test, run ViEStandardIntegrationTest.RunsBaseTestWithoutErrors + // in vie_auto_tests. + // In the same test, it appears that it's also called on a thread that's + // neither the ctor thread nor the capture thread. CriticalSectionScoped cs(provider_cs_.get()); frame_delay_ = frame_delay; - for (FrameCallbacks::iterator it = frame_callbacks_.begin(); - it != frame_callbacks_.end(); ++it) { - (*it)->DelayChanged(id_, frame_delay); + for (ViEFrameCallback* callback : frame_callbacks_) { + callback->DelayChanged(id_, frame_delay); } } int ViEFrameProviderBase::FrameDelay() { + // Called on the default thread in WebRtcVideoMediaChannelTest.SetSend + // (libjingle_media_unittest). + + // Called on neither the ctor thread nor the capture thread in + // BitrateEstimatorTest.ImmediatelySwitchToAST (video_engine_tests). + + // Most of the time Called on the capture thread (see OnCaptureDelayChanged). + // To test, run ViEStandardIntegrationTest.RunsBaseTestWithoutErrors + // in vie_auto_tests. return frame_delay_; } int ViEFrameProviderBase::GetBestFormat(int* best_width, int* best_height, int* best_frame_rate) { + DCHECK(thread_checker_.CalledOnValidThread()); int largest_width = 0; int largest_height = 0; int highest_frame_rate = 0; - CriticalSectionScoped cs(provider_cs_.get()); - for (FrameCallbacks::iterator it = frame_callbacks_.begin(); - it != frame_callbacks_.end(); ++it) { + // Here we don't need to grab the provider_cs_ lock to run through the list + // of callbacks. The reason is that we know that we're currently on the same + // thread that is the only thread that will modify the callback list and + // we can be sure that the thread won't race with itself. + for (ViEFrameCallback* callback : frame_callbacks_) { int prefered_width = 0; int prefered_height = 0; int prefered_frame_rate = 0; - if ((*it)->GetPreferedFrameSettings(&prefered_width, &prefered_height, - &prefered_frame_rate) == 0) { + if (callback->GetPreferedFrameSettings(&prefered_width, &prefered_height, + &prefered_frame_rate) == 0) { if (prefered_width > largest_width) { largest_width = prefered_width; } @@ -132,12 +147,13 @@ int ViEFrameProviderBase::GetBestFormat(int* best_width, int ViEFrameProviderBase::RegisterFrameCallback( int observer_id, ViEFrameCallback* callback_object) { - assert(callback_object); + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(callback_object); { CriticalSectionScoped cs(provider_cs_.get()); if (std::find(frame_callbacks_.begin(), frame_callbacks_.end(), callback_object) != frame_callbacks_.end()) { - assert(false && "frameObserver already registered"); + DCHECK(false && "frameObserver already registered"); return -1; } frame_callbacks_.push_back(callback_object); @@ -152,33 +168,35 @@ int ViEFrameProviderBase::RegisterFrameCallback( int ViEFrameProviderBase::DeregisterFrameCallback( const ViEFrameCallback* callback_object) { - assert(callback_object); - CriticalSectionScoped cs(provider_cs_.get()); - - FrameCallbacks::iterator it = std::find(frame_callbacks_.begin(), - frame_callbacks_.end(), - callback_object); - if (it == frame_callbacks_.end()) { - return -1; + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(callback_object); + { + CriticalSectionScoped cs(provider_cs_.get()); + FrameCallbacks::iterator it = std::find(frame_callbacks_.begin(), + frame_callbacks_.end(), + callback_object); + if (it == frame_callbacks_.end()) { + return -1; + } + frame_callbacks_.erase(it); } - frame_callbacks_.erase(it); // Notify implementer of this class that the callback list have changed. FrameCallbackChanged(); + return 0; } bool ViEFrameProviderBase::IsFrameCallbackRegistered( const ViEFrameCallback* callback_object) { - assert(callback_object); + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(callback_object); - CriticalSectionScoped cs(provider_cs_.get()); + // Here we don't need to grab the lock to do this lookup. + // The reason is that we know that we're currently on the same thread that + // is the only thread that will modify the callback list and subsequently the + // thread doesn't race with itself. return std::find(frame_callbacks_.begin(), frame_callbacks_.end(), callback_object) != frame_callbacks_.end(); } - -int ViEFrameProviderBase::NumberOfRegisteredFrameCallbacks() { - CriticalSectionScoped cs(provider_cs_.get()); - return frame_callbacks_.size(); -} } // namespac webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_frame_provider_base.h b/media/webrtc/trunk/webrtc/video_engine/vie_frame_provider_base.h index e5a137b8bd..b3ace3bdfc 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_frame_provider_base.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_frame_provider_base.h @@ -13,8 +13,9 @@ #include +#include "webrtc/base/scoped_ptr.h" +#include "webrtc/base/thread_checker.h" #include "webrtc/common_types.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -29,8 +30,7 @@ class ViEFrameCallback { public: virtual void DeliverFrame(int id, I420VideoFrame* video_frame, - int num_csrcs = 0, - const uint32_t CSRC[kRtpCsrcSize] = NULL) = 0; + const std::vector& csrcs) = 0; // The capture delay has changed from the provider. |frame_delay| is given in // ms. @@ -56,18 +56,20 @@ class ViEFrameProviderBase { virtual ~ViEFrameProviderBase(); // Returns the frame provider id. - int Id(); + int Id() const; // Register frame callbacks, i.e. a receiver of the captured frame. - virtual int RegisterFrameCallback(int observer_id, - ViEFrameCallback* callback_object); + // Must be called on the same thread as the provider was constructed on. + int RegisterFrameCallback(int observer_id, ViEFrameCallback* callback); - virtual int DeregisterFrameCallback(const ViEFrameCallback* callback_object); + // Unregisters a previously registered callback. Returns -1 if the callback + // object hasn't been registered. + // Must be called on the same thread as the provider was constructed on. + int DeregisterFrameCallback(const ViEFrameCallback* callback); - virtual bool IsFrameCallbackRegistered( - const ViEFrameCallback* callback_object); - - int NumberOfRegisteredFrameCallbacks(); + // Determines if a callback is currently registered. + // Must be called on the same thread as the provider was constructed on. + bool IsFrameCallbackRegistered(const ViEFrameCallback* callback); // FrameCallbackChanged // Inherited classes should check for new frame_settings and reconfigure @@ -76,24 +78,26 @@ class ViEFrameProviderBase { protected: void DeliverFrame(I420VideoFrame* video_frame, - int num_csrcs = 0, - const uint32_t CSRC[kRtpCsrcSize] = NULL); + const std::vector& csrcs); void SetFrameDelay(int frame_delay); int FrameDelay(); int GetBestFormat(int* best_width, int* best_height, int* best_frame_rate); - int id_; - int engine_id_; + rtc::ThreadChecker thread_checker_; + rtc::ThreadChecker frame_delivery_thread_checker_; + + const int id_; + const int engine_id_; // Frame callbacks. typedef std::vector FrameCallbacks; FrameCallbacks frame_callbacks_; - scoped_ptr provider_cs_; + const rtc::scoped_ptr provider_cs_; private: - scoped_ptr extra_frame_; + rtc::scoped_ptr extra_frame_; int frame_delay_; }; diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_image_process_impl.h b/media/webrtc/trunk/webrtc/video_engine/vie_image_process_impl.h index 38a6a08cf8..64775b1e19 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_image_process_impl.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_image_process_impl.h @@ -37,25 +37,25 @@ class ViEImageProcessImpl virtual int EnableDeflickering(const int capture_id, const bool enable); virtual int EnableColorEnhancement(const int video_channel, const bool enable); - virtual void RegisterPreEncodeCallback( + void RegisterPreEncodeCallback( int video_channel, - I420FrameCallback* pre_encode_callback) OVERRIDE; - virtual void DeRegisterPreEncodeCallback(int video_channel) OVERRIDE; + I420FrameCallback* pre_encode_callback) override; + void DeRegisterPreEncodeCallback(int video_channel) override; - virtual void RegisterPostEncodeImageCallback( + void RegisterPostEncodeImageCallback( int video_channel, - EncodedImageCallback* post_encode_callback) OVERRIDE; - virtual void DeRegisterPostEncodeCallback(int video_channel) OVERRIDE; + EncodedImageCallback* post_encode_callback) override; + void DeRegisterPostEncodeCallback(int video_channel) override; - virtual void RegisterPreDecodeImageCallback( - int video_channel, - EncodedImageCallback* post_encode_callback) OVERRIDE; - virtual void DeRegisterPreDecodeCallback(int video_channel) OVERRIDE; - - virtual void RegisterPreRenderCallback( + void RegisterPreDecodeImageCallback( int video_channel, - I420FrameCallback* pre_render_callback) OVERRIDE; - virtual void DeRegisterPreRenderCallback(int video_channel) OVERRIDE; + EncodedImageCallback* post_encode_callback) override; + void DeRegisterPreDecodeCallback(int video_channel) override; + + void RegisterPreRenderCallback( + int video_channel, + I420FrameCallback* pre_render_callback) override; + void DeRegisterPreRenderCallback(int video_channel) override; protected: explicit ViEImageProcessImpl(ViESharedData* shared_data); diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_impl.h b/media/webrtc/trunk/webrtc/video_engine/vie_impl.h index 086282d187..34fd7f7f3b 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_impl.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_impl.h @@ -11,9 +11,9 @@ #ifndef WEBRTC_VIDEO_ENGINE_VIE_IMPL_H_ #define WEBRTC_VIDEO_ENGINE_VIE_IMPL_H_ +#include "webrtc/base/scoped_ptr.h" #include "webrtc/common.h" #include "webrtc/engine_configurations.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/video_engine/vie_defines.h" #include "webrtc/video_engine/vie_base_impl.h" @@ -100,7 +100,7 @@ class VideoEngineImpl private: // Placeholder for the case where this owns the config. - scoped_ptr own_config_; + rtc::scoped_ptr own_config_; }; } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_input_manager.cc b/media/webrtc/trunk/webrtc/video_engine/vie_input_manager.cc index 7874aa8d7d..e3067e0191 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_input_manager.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_input_manager.cc @@ -113,29 +113,12 @@ int ViEInputManager::GetCaptureCapability( } int ViEInputManager::GetOrientation(const char* device_unique_idUTF8, - RotateCapturedFrame& orientation) { + VideoRotation& orientation) { CriticalSectionScoped cs(device_info_cs_.get()); GetDeviceInfo(); assert(capture_device_info_); - VideoCaptureRotation module_orientation; - int result = capture_device_info_->GetOrientation(device_unique_idUTF8, - module_orientation); - // Copy from module type to public type. - switch (module_orientation) { - case kCameraRotate0: - orientation = RotateCapturedFrame_0; - break; - case kCameraRotate90: - orientation = RotateCapturedFrame_90; - break; - case kCameraRotate180: - orientation = RotateCapturedFrame_180; - break; - case kCameraRotate270: - orientation = RotateCapturedFrame_270; - break; - } - return result; + return capture_device_info_->GetOrientation(device_unique_idUTF8, + orientation); } int ViEInputManager::DisplayCaptureSettingsDialogBox( @@ -260,12 +243,6 @@ int ViEInputManager::DestroyCaptureDevice(const int capture_id) { LOG(LS_ERROR) << "No such capture device id: " << capture_id; return -1; } - uint32_t num_callbacks = - vie_capture->NumberOfRegisteredFrameCallbacks(); - if (num_callbacks > 0) { - LOG(LS_WARNING) << num_callbacks << " still registered to capture id " - << capture_id << " when destroying capture device."; - } vie_frame_provider_map_.erase(capture_id); ReturnCaptureId(capture_id); // Leave cs before deleting the capture object. This is because deleting the diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_input_manager.h b/media/webrtc/trunk/webrtc/video_engine/vie_input_manager.h index 26252069f0..8a2b441639 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_input_manager.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_input_manager.h @@ -13,9 +13,10 @@ #include +#include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/video_capture/include/video_capture.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/typedefs.h" +#include "webrtc/common_video/rotation.h" #include "webrtc/video_engine/include/vie_capture.h" #include "webrtc/video_engine/vie_defines.h" #include "webrtc/video_engine/vie_frame_provider_base.h" @@ -64,7 +65,7 @@ class ViEInputManager : private ViEManagerBase { uint32_t positionX, uint32_t positionY); int GetOrientation(const char* device_unique_idUTF8, - RotateCapturedFrame& orientation); + VideoRotation& orientation); // Creates a capture module for the specified capture device and assigns // a capture device id for the device. @@ -98,8 +99,8 @@ class ViEInputManager : private ViEManagerBase { const Config& config_; int engine_id_; - scoped_ptr map_cs_; - scoped_ptr device_info_cs_; + rtc::scoped_ptr map_cs_; + rtc::scoped_ptr device_info_cs_; typedef std::map FrameProviderMap; FrameProviderMap vie_frame_provider_map_; diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_network_impl.cc b/media/webrtc/trunk/webrtc/video_engine/vie_network_impl.cc index 4a9d866585..5d45187a61 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_network_impl.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_network_impl.cc @@ -15,6 +15,7 @@ #include #endif +#include "webrtc/base/checks.h" #include "webrtc/engine_configurations.h" #include "webrtc/system_wrappers/interface/logging.h" #include "webrtc/video_engine/include/vie_errors.h" @@ -51,6 +52,26 @@ int ViENetworkImpl::Release() { return ref_count; } +ViENetworkImpl::ViENetworkImpl(ViESharedData* shared_data) + : shared_data_(shared_data) { +} + +ViENetworkImpl::~ViENetworkImpl() { +} + +void ViENetworkImpl::SetBitrateConfig(int video_channel, + int min_bitrate_bps, + int start_bitrate_bps, + int max_bitrate_bps) { + LOG_F(LS_INFO) << "channel: " << video_channel + << " new bitrate config: min=" << min_bitrate_bps + << ", start=" << start_bitrate_bps + << ", max=" << max_bitrate_bps; + bool success = shared_data_->channel_manager()->SetBitrateConfig( + video_channel, min_bitrate_bps, start_bitrate_bps, max_bitrate_bps); + DCHECK(success); +} + void ViENetworkImpl::SetNetworkTransmissionState(const int video_channel, const bool is_transmitting) { LOG_F(LS_INFO) << "channel: " << video_channel @@ -64,11 +85,6 @@ void ViENetworkImpl::SetNetworkTransmissionState(const int video_channel, vie_encoder->SetNetworkTransmissionState(is_transmitting); } -ViENetworkImpl::ViENetworkImpl(ViESharedData* shared_data) - : shared_data_(shared_data) {} - -ViENetworkImpl::~ViENetworkImpl() {} - int ViENetworkImpl::RegisterSendTransport(const int video_channel, Transport& transport) { LOG_F(LS_INFO) << "channel: " << video_channel; @@ -111,7 +127,7 @@ int ViENetworkImpl::DeregisterSendTransport(const int video_channel) { } int ViENetworkImpl::ReceivedRTPPacket(const int video_channel, const void* data, - const int length, + const size_t length, const PacketTime& packet_time) { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); @@ -123,7 +139,7 @@ int ViENetworkImpl::ReceivedRTPPacket(const int video_channel, const void* data, } int ViENetworkImpl::ReceivedRTCPPacket(const int video_channel, - const void* data, const int length) { + const void* data, const size_t length) { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { @@ -149,7 +165,9 @@ int ViENetworkImpl::SetMTU(int video_channel, unsigned int mtu) { } int ViENetworkImpl::ReceivedBWEPacket(const int video_channel, - int64_t arrival_time_ms, int payload_size, const RTPHeader& header) { + int64_t arrival_time_ms, + size_t payload_size, + const RTPHeader& header) { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { @@ -160,11 +178,4 @@ int ViENetworkImpl::ReceivedBWEPacket(const int video_channel, vie_channel->ReceivedBWEPacket(arrival_time_ms, payload_size, header); return 0; } - -bool ViENetworkImpl::SetBandwidthEstimationConfig( - int video_channel, const webrtc::Config& config) { - LOG_F(LS_INFO) << "channel: " << video_channel; - return shared_data_->channel_manager()->SetBandwidthEstimationConfig( - video_channel, config); -} } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_network_impl.h b/media/webrtc/trunk/webrtc/video_engine/vie_network_impl.h index e9ca75469d..1354f8cf4a 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_network_impl.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_network_impl.h @@ -24,29 +24,29 @@ class ViENetworkImpl public ViERefCount { public: // Implements ViENetwork. - virtual int Release() OVERRIDE; - virtual void SetNetworkTransmissionState(const int video_channel, - const bool is_transmitting) OVERRIDE; - virtual int RegisterSendTransport(const int video_channel, - Transport& transport) OVERRIDE; - virtual int DeregisterSendTransport(const int video_channel) OVERRIDE; - virtual int ReceivedRTPPacket(const int video_channel, - const void* data, - const int length, - const PacketTime& packet_time) OVERRIDE; - virtual int ReceivedRTCPPacket(const int video_channel, - const void* data, - const int length) OVERRIDE; - virtual int SetMTU(int video_channel, unsigned int mtu) OVERRIDE; + int Release() override; + void SetBitrateConfig(int video_channel, + int min_bitrate_bps, + int start_bitrate_bps, + int max_bitrate_bps) override; + void SetNetworkTransmissionState(const int video_channel, + const bool is_transmitting) override; + int RegisterSendTransport(const int video_channel, + Transport& transport) override; + int DeregisterSendTransport(const int video_channel) override; + int ReceivedRTPPacket(const int video_channel, + const void* data, + const size_t length, + const PacketTime& packet_time) override; + int ReceivedRTCPPacket(const int video_channel, + const void* data, + const size_t length) override; + int SetMTU(int video_channel, unsigned int mtu) override; - virtual int ReceivedBWEPacket(const int video_channel, - int64_t arrival_time_ms, - int payload_size, - const RTPHeader& header) OVERRIDE; - - virtual bool SetBandwidthEstimationConfig( - int video_channel, - const webrtc::Config& config) OVERRIDE; + int ReceivedBWEPacket(const int video_channel, + int64_t arrival_time_ms, + size_t payload_size, + const RTPHeader& header) override; protected: explicit ViENetworkImpl(ViESharedData* shared_data); diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_receiver.cc b/media/webrtc/trunk/webrtc/video_engine/vie_receiver.cc index 284109d925..daac6b93c4 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_receiver.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_receiver.cc @@ -16,6 +16,7 @@ #include "webrtc/modules/rtp_rtcp/interface/fec_receiver.h" #include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h" #include "webrtc/modules/rtp_rtcp/interface/remote_ntp_time_estimator.h" +#include "webrtc/modules/rtp_rtcp/interface/rtp_cvo.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h" @@ -24,6 +25,7 @@ #include "webrtc/modules/video_coding/main/interface/video_coding.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/logging.h" +#include "webrtc/system_wrappers/interface/metrics.h" #include "webrtc/system_wrappers/interface/tick_util.h" #include "webrtc/system_wrappers/interface/timestamp_extrapolator.h" #include "webrtc/system_wrappers/interface/trace.h" @@ -58,11 +60,13 @@ ViEReceiver::ViEReceiver(const int32_t channel_id, receiving_rtcp_(false), restored_packet_in_use_(false), receiving_ast_enabled_(false), + receiving_cvo_enabled_(false), last_packet_log_ms_(-1) { assert(remote_bitrate_estimator); } ViEReceiver::~ViEReceiver() { + UpdateHistograms(); if (rtp_dump_) { rtp_dump_->Stop(); RtpDump::DestroyRtpDump(rtp_dump_); @@ -70,6 +74,19 @@ ViEReceiver::~ViEReceiver() { } } +void ViEReceiver::UpdateHistograms() { + FecPacketCounter counter = fec_receiver_->GetPacketCounter(); + if (counter.num_packets > 0) { + RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.ReceivedFecPacketsInPercent", + counter.num_fec_packets * 100 / counter.num_packets); + } + if (counter.num_fec_packets > 0) { + RTC_HISTOGRAM_PERCENTAGE( + "WebRTC.Video.RecoveredMediaPacketsInPercentOfFec", + counter.num_recovered_packets * 100 / counter.num_fec_packets); + } +} + bool ViEReceiver::SetReceiveCodec(const VideoCodec& video_codec) { int8_t old_pltype = -1; if (rtp_payload_registry_->ReceivePayloadType(video_codec.plName, @@ -111,6 +128,14 @@ void ViEReceiver::SetRtxSsrc(uint32_t ssrc) { rtp_payload_registry_->SetRtxSsrc(ssrc); } +bool ViEReceiver::GetRtxSsrc(uint32_t* ssrc) const { + return rtp_payload_registry_->GetRtxSsrc(ssrc); +} + +bool ViEReceiver::IsFecEnabled() const { + return rtp_payload_registry_->ulpfec_payload_type() > -1; +} + uint32_t ViEReceiver::GetRemoteSsrc() const { return rtp_receiver_->SSRC(); } @@ -165,22 +190,38 @@ bool ViEReceiver::SetReceiveAbsoluteSendTimeStatus(bool enable, int id) { } } +bool ViEReceiver::SetReceiveVideoRotationStatus(bool enable, int id) { + if (enable) { + if (rtp_header_parser_->RegisterRtpHeaderExtension( + kRtpExtensionVideoRotation, id)) { + receiving_cvo_enabled_ = true; + return true; + } else { + return false; + } + } else { + receiving_cvo_enabled_ = false; + return rtp_header_parser_->DeregisterRtpHeaderExtension( + kRtpExtensionVideoRotation); + } +} + int ViEReceiver::ReceivedRTPPacket(const void* rtp_packet, - int rtp_packet_length, + size_t rtp_packet_length, const PacketTime& packet_time) { return InsertRTPPacket(static_cast(rtp_packet), rtp_packet_length, packet_time); } int ViEReceiver::ReceivedRTCPPacket(const void* rtcp_packet, - int rtcp_packet_length) { + size_t rtcp_packet_length) { return InsertRTCPPacket(static_cast(rtcp_packet), rtcp_packet_length); } -int32_t ViEReceiver::OnReceivedPayloadData( - const uint8_t* payload_data, const uint16_t payload_size, - const WebRtcRTPHeader* rtp_header) { +int32_t ViEReceiver::OnReceivedPayloadData(const uint8_t* payload_data, + const size_t payload_size, + const WebRtcRTPHeader* rtp_header) { WebRtcRTPHeader rtp_header_with_ntp = *rtp_header; rtp_header_with_ntp.ntp_time_ms = ntp_estimator_->Estimate(rtp_header->header.timestamp); @@ -194,7 +235,7 @@ int32_t ViEReceiver::OnReceivedPayloadData( } bool ViEReceiver::OnRecoveredPacket(const uint8_t* rtp_packet, - int rtp_packet_length) { + size_t rtp_packet_length) { RTPHeader header; if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) { return false; @@ -205,7 +246,7 @@ bool ViEReceiver::OnRecoveredPacket(const uint8_t* rtp_packet, } void ViEReceiver::ReceivedBWEPacket( - int64_t arrival_time_ms, int payload_size, const RTPHeader& header) { + int64_t arrival_time_ms, size_t payload_size, const RTPHeader& header) { // Only forward if the incoming packet *and* the channel are both configured // to receive absolute sender time. RTP time stamps may have different rates // for audio and video and shouldn't be mixed. @@ -216,7 +257,7 @@ void ViEReceiver::ReceivedBWEPacket( } int ViEReceiver::InsertRTPPacket(const uint8_t* rtp_packet, - int rtp_packet_length, + size_t rtp_packet_length, const PacketTime& packet_time) { { CriticalSectionScoped cs(receive_cs_.get()); @@ -224,8 +265,7 @@ int ViEReceiver::InsertRTPPacket(const uint8_t* rtp_packet, return -1; } if (rtp_dump_) { - rtp_dump_->DumpPacket(rtp_packet, - static_cast(rtp_packet_length)); + rtp_dump_->DumpPacket(rtp_packet, rtp_packet_length); } } @@ -234,7 +274,7 @@ int ViEReceiver::InsertRTPPacket(const uint8_t* rtp_packet, &header)) { return -1; } - int payload_length = rtp_packet_length - header.headerLength; + size_t payload_length = rtp_packet_length - header.headerLength; int64_t arrival_time_ms; int64_t now_ms = clock_->TimeInMilliseconds(); if (packet_time.timestamp != -1) @@ -278,15 +318,15 @@ int ViEReceiver::InsertRTPPacket(const uint8_t* rtp_packet, } bool ViEReceiver::ReceivePacket(const uint8_t* packet, - int packet_length, + size_t packet_length, const RTPHeader& header, bool in_order) { if (rtp_payload_registry_->IsEncapsulated(header)) { return ParseAndHandleEncapsulatingHeader(packet, packet_length, header); } const uint8_t* payload = packet + header.headerLength; - int payload_length = packet_length - header.headerLength; - assert(payload_length >= 0); + assert(packet_length >= header.headerLength); + size_t payload_length = packet_length - header.headerLength; PayloadUnion payload_specific; if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType, &payload_specific)) { @@ -297,12 +337,15 @@ bool ViEReceiver::ReceivePacket(const uint8_t* packet, } bool ViEReceiver::ParseAndHandleEncapsulatingHeader(const uint8_t* packet, - int packet_length, + size_t packet_length, const RTPHeader& header) { if (rtp_payload_registry_->IsRed(header)) { int8_t ulpfec_pt = rtp_payload_registry_->ulpfec_payload_type(); - if (packet[header.headerLength] == ulpfec_pt) - rtp_receive_statistics_->FecPacketReceived(header.ssrc); + if (packet[header.headerLength] == ulpfec_pt) { + rtp_receive_statistics_->FecPacketReceived(header, packet_length); + // Notify vcm about received FEC packets to avoid NACKing these packets. + NotifyReceiverOfFecPacket(header); + } if (fec_receiver_->AddReceivedRedPacket( header, packet, packet_length, ulpfec_pt) != 0) { return false; @@ -317,7 +360,7 @@ bool ViEReceiver::ParseAndHandleEncapsulatingHeader(const uint8_t* packet, // Remove the RTX header and parse the original RTP header. if (packet_length < header.headerLength) return false; - if (packet_length > static_cast(sizeof(restored_packet_))) + if (packet_length > sizeof(restored_packet_)) return false; CriticalSectionScoped cs(receive_cs_.get()); if (restored_packet_in_use_) { @@ -339,8 +382,35 @@ bool ViEReceiver::ParseAndHandleEncapsulatingHeader(const uint8_t* packet, return false; } +void ViEReceiver::NotifyReceiverOfFecPacket(const RTPHeader& header) { + int8_t last_media_payload_type = + rtp_payload_registry_->last_received_media_payload_type(); + if (last_media_payload_type < 0) { + LOG(LS_WARNING) << "Failed to get last media payload type."; + return; + } + // Fake an empty media packet. + WebRtcRTPHeader rtp_header = {}; + rtp_header.header = header; + rtp_header.header.payloadType = last_media_payload_type; + rtp_header.header.paddingLength = 0; + PayloadUnion payload_specific; + if (!rtp_payload_registry_->GetPayloadSpecifics(last_media_payload_type, + &payload_specific)) { + LOG(LS_WARNING) << "Failed to get payload specifics."; + return; + } + rtp_header.type.Video.codec = payload_specific.Video.videoCodecType; + rtp_header.type.Video.rotation = kVideoRotation_0; + if (header.extension.hasVideoRotation) { + rtp_header.type.Video.rotation = + ConvertCVOByteToVideoRotation(header.extension.videoRotation); + } + OnReceivedPayloadData(NULL, 0, &rtp_header); +} + int ViEReceiver::InsertRTCPPacket(const uint8_t* rtcp_packet, - int rtcp_packet_length) { + size_t rtcp_packet_length) { { CriticalSectionScoped cs(receive_cs_.get()); if (!receiving_rtcp_) { @@ -348,8 +418,7 @@ int ViEReceiver::InsertRTCPPacket(const uint8_t* rtcp_packet, } if (rtp_dump_) { - rtp_dump_->DumpPacket( - rtcp_packet, static_cast(rtcp_packet_length)); + rtp_dump_->DumpPacket(rtcp_packet, rtcp_packet_length); } std::list::iterator it = rtp_rtcp_simulcast_.begin(); @@ -364,7 +433,7 @@ int ViEReceiver::InsertRTCPPacket(const uint8_t* rtcp_packet, return ret; } - uint16_t rtt = 0; + int64_t rtt = 0; rtp_rtcp_->RTT(rtp_receiver_->SSRC(), &rtt, NULL, NULL, NULL); if (rtt == 0) { // Waiting for valid rtt. @@ -436,11 +505,6 @@ int ViEReceiver::StopRTPDump() { return 0; } -void ViEReceiver::GetReceiveBandwidthEstimatorStats( - ReceiveBandwidthEstimatorStats* output) const { - remote_bitrate_estimator_->GetStats(output); -} - ReceiveStatistics* ViEReceiver::GetReceiveStatistics() const { return rtp_receive_statistics_.get(); } @@ -463,7 +527,7 @@ bool ViEReceiver::IsPacketRetransmitted(const RTPHeader& header, if (!statistician) return false; // Check if this is a retransmission. - uint16_t min_rtt = 0; + int64_t min_rtt = 0; rtp_rtcp_->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL); return !in_order && statistician->IsRetransmitOfOldPacket(header, min_rtt); diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_receiver.h b/media/webrtc/trunk/webrtc/video_engine/vie_receiver.h index 5bbc9becbc..1002f64165 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_receiver.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_receiver.h @@ -13,10 +13,10 @@ #include +#include "webrtc/base/scoped_ptr.h" #include "webrtc/engine_configurations.h" #include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/typedefs.h" #include "webrtc/video_engine/include/vie_network.h" #include "webrtc/video_engine/vie_defines.h" @@ -49,6 +49,9 @@ class ViEReceiver : public RtpData { void SetNackStatus(bool enable, int max_nack_reordering_threshold); void SetRtxPayloadType(int payload_type); void SetRtxSsrc(uint32_t ssrc); + bool GetRtxSsrc(uint32_t* ssrc) const; + + bool IsFecEnabled() const; uint32_t GetRemoteSsrc() const; int GetCsrcs(uint32_t* csrcs) const; @@ -61,6 +64,7 @@ class ViEReceiver : public RtpData { bool SetReceiveTimestampOffsetStatus(bool enable, int id); bool SetReceiveAbsoluteSendTimeStatus(bool enable, int id); + bool SetReceiveVideoRotationStatus(bool enable, int id); void StartReceive(); void StopReceive(); @@ -72,54 +76,51 @@ class ViEReceiver : public RtpData { int StopRTPDump(); // Receives packets from external transport. - int ReceivedRTPPacket(const void* rtp_packet, int rtp_packet_length, + int ReceivedRTPPacket(const void* rtp_packet, size_t rtp_packet_length, const PacketTime& packet_time); - int ReceivedRTCPPacket(const void* rtcp_packet, int rtcp_packet_length); + int ReceivedRTCPPacket(const void* rtcp_packet, size_t rtcp_packet_length); // Implements RtpData. - virtual int32_t OnReceivedPayloadData( - const uint8_t* payload_data, - const uint16_t payload_size, - const WebRtcRTPHeader* rtp_header) OVERRIDE; - virtual bool OnRecoveredPacket(const uint8_t* packet, - int packet_length) OVERRIDE; - - void GetReceiveBandwidthEstimatorStats( - ReceiveBandwidthEstimatorStats* output) const; + int32_t OnReceivedPayloadData(const uint8_t* payload_data, + const size_t payload_size, + const WebRtcRTPHeader* rtp_header) override; + bool OnRecoveredPacket(const uint8_t* packet, size_t packet_length) override; ReceiveStatistics* GetReceiveStatistics() const; - void ReceivedBWEPacket(int64_t arrival_time_ms, int payload_size, + void ReceivedBWEPacket(int64_t arrival_time_ms, size_t payload_size, const RTPHeader& header); private: - int InsertRTPPacket(const uint8_t* rtp_packet, int rtp_packet_length, + int InsertRTPPacket(const uint8_t* rtp_packet, size_t rtp_packet_length, const PacketTime& packet_time); bool ReceivePacket(const uint8_t* packet, - int packet_length, + size_t packet_length, const RTPHeader& header, bool in_order); // Parses and handles for instance RTX and RED headers. // This function assumes that it's being called from only one thread. bool ParseAndHandleEncapsulatingHeader(const uint8_t* packet, - int packet_length, + size_t packet_length, const RTPHeader& header); - int InsertRTCPPacket(const uint8_t* rtcp_packet, int rtcp_packet_length); + void NotifyReceiverOfFecPacket(const RTPHeader& header); + int InsertRTCPPacket(const uint8_t* rtcp_packet, size_t rtcp_packet_length); bool IsPacketInOrder(const RTPHeader& header) const; bool IsPacketRetransmitted(const RTPHeader& header, bool in_order) const; + void UpdateHistograms(); - scoped_ptr receive_cs_; + rtc::scoped_ptr receive_cs_; Clock* clock_; - scoped_ptr rtp_header_parser_; - scoped_ptr rtp_payload_registry_; - scoped_ptr rtp_receiver_; - scoped_ptr rtp_receive_statistics_; - scoped_ptr fec_receiver_; + rtc::scoped_ptr rtp_header_parser_; + rtc::scoped_ptr rtp_payload_registry_; + rtc::scoped_ptr rtp_receiver_; + rtc::scoped_ptr rtp_receive_statistics_; + rtc::scoped_ptr fec_receiver_; RtpRtcp* rtp_rtcp_; std::list rtp_rtcp_simulcast_; VideoCodingModule* vcm_; RemoteBitrateEstimator* remote_bitrate_estimator_; - scoped_ptr ntp_estimator_; + rtc::scoped_ptr ntp_estimator_; RtpDump* rtp_dump_; bool receiving_; @@ -127,6 +128,7 @@ class ViEReceiver : public RtpData { uint8_t restored_packet_[kViEMaxMtu]; bool restored_packet_in_use_; bool receiving_ast_enabled_; + bool receiving_cvo_enabled_; int64_t last_packet_log_ms_; }; diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_ref_count.h b/media/webrtc/trunk/webrtc/video_engine/vie_ref_count.h index 95451c4dde..61533e10e2 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_ref_count.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_ref_count.h @@ -13,7 +13,7 @@ #ifndef WEBRTC_VIDEO_ENGINE_VIE_REF_COUNT_H_ #define WEBRTC_VIDEO_ENGINE_VIE_REF_COUNT_H_ -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/base/scoped_ptr.h" namespace webrtc { @@ -32,7 +32,7 @@ class ViERefCount { private: volatile int count_; - scoped_ptr crit_; + rtc::scoped_ptr crit_; }; } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_remb.cc b/media/webrtc/trunk/webrtc/video_engine/vie_remb.cc index d04f0a30ad..2cf794c5d4 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_remb.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_remb.cc @@ -136,8 +136,7 @@ void VieRemb::OnReceiveBitrateChanged(const std::vector& ssrcs, list_crit_->Leave(); if (sender) { - // TODO(holmer): Change RTP module API to take a const vector reference. - sender->SetREMBData(bitrate_, ssrcs.size(), &ssrcs[0]); + sender->SetREMBData(bitrate_, ssrcs); } } diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_remb.h b/media/webrtc/trunk/webrtc/video_engine/vie_remb.h index 66e1c8e689..9f38259ca8 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_remb.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_remb.h @@ -15,10 +15,10 @@ #include #include +#include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/interface/module.h" #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" namespace webrtc { @@ -57,7 +57,7 @@ class VieRemb : public RemoteBitrateObserver { private: typedef std::list RtpModules; - scoped_ptr list_crit_; + rtc::scoped_ptr list_crit_; // The last time a REMB was sent. int64_t last_remb_time_; diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_remb_unittest.cc b/media/webrtc/trunk/webrtc/video_engine/vie_remb_unittest.cc index 1f0b70c516..3949d4482c 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_remb_unittest.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_remb_unittest.cc @@ -16,10 +16,10 @@ #include +#include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" #include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h" #include "webrtc/modules/utility/interface/mock/mock_process_thread.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/tick_util.h" #include "webrtc/video_engine/vie_remb.h" @@ -37,8 +37,8 @@ class ViERembTest : public ::testing::Test { process_thread_.reset(new NiceMock); vie_remb_.reset(new VieRemb()); } - scoped_ptr process_thread_; - scoped_ptr vie_remb_; + rtc::scoped_ptr process_thread_; + rtc::scoped_ptr vie_remb_; }; TEST_F(ViERembTest, OneModuleTestForSendingRemb) { @@ -53,12 +53,12 @@ TEST_F(ViERembTest, OneModuleTestForSendingRemb) { vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); TickTime::AdvanceFakeClock(1000); - EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _)) + EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, ssrcs)) .Times(1); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Lower bitrate to send another REMB packet. - EXPECT_CALL(rtp, SetREMBData(bitrate_estimate - 100, 1, _)) + EXPECT_CALL(rtp, SetREMBData(bitrate_estimate - 100, ssrcs)) .Times(1); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate - 100); @@ -78,14 +78,14 @@ TEST_F(ViERembTest, LowerEstimateToSendRemb) { vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Call OnReceiveBitrateChanged twice to get a first estimate. TickTime::AdvanceFakeClock(1000); - EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _)) + EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, ssrcs)) .Times(1); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Lower the estimate with more than 3% to trigger a call to SetREMBData right // away. bitrate_estimate = bitrate_estimate - 100; - EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _)) + EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, ssrcs)) .Times(1); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); } @@ -104,7 +104,7 @@ TEST_F(ViERembTest, VerifyIncreasingAndDecreasing) { vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate[0]); // Call OnReceiveBitrateChanged twice to get a first estimate. - EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate[0], 2, _)) + EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate[0], ssrcs)) .Times(1); TickTime::AdvanceFakeClock(1000); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate[0]); @@ -112,7 +112,7 @@ TEST_F(ViERembTest, VerifyIncreasingAndDecreasing) { vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate[1] + 100); // Lower the estimate to trigger a callback. - EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate[1], 2, _)) + EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate[1], ssrcs)) .Times(1); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate[1]); @@ -135,17 +135,17 @@ TEST_F(ViERembTest, NoRembForIncreasedBitrate) { vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Call OnReceiveBitrateChanged twice to get a first estimate. TickTime::AdvanceFakeClock(1000); - EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _)) + EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, ssrcs)) .Times(1); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Increased estimate shouldn't trigger a callback right away. - EXPECT_CALL(rtp_0, SetREMBData(_, _, _)) + EXPECT_CALL(rtp_0, SetREMBData(_, _)) .Times(0); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate + 1); // Decreasing the estimate less than 3% shouldn't trigger a new callback. - EXPECT_CALL(rtp_0, SetREMBData(_, _, _)) + EXPECT_CALL(rtp_0, SetREMBData(_, _)) .Times(0); int lower_estimate = bitrate_estimate * 98 / 100; vie_remb_->OnReceiveBitrateChanged(ssrcs, lower_estimate); @@ -169,13 +169,13 @@ TEST_F(ViERembTest, ChangeSendRtpModule) { vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Call OnReceiveBitrateChanged twice to get a first estimate. TickTime::AdvanceFakeClock(1000); - EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _)) + EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, ssrcs)) .Times(1); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Decrease estimate to trigger a REMB. bitrate_estimate = bitrate_estimate - 100; - EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _)) + EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, ssrcs)) .Times(1); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); @@ -186,7 +186,7 @@ TEST_F(ViERembTest, ChangeSendRtpModule) { vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); bitrate_estimate = bitrate_estimate - 100; - EXPECT_CALL(rtp_1, SetREMBData(bitrate_estimate, 2, _)) + EXPECT_CALL(rtp_1, SetREMBData(bitrate_estimate, ssrcs)) .Times(1); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); @@ -205,18 +205,18 @@ TEST_F(ViERembTest, OnlyOneRembForDoubleProcess) { vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Call OnReceiveBitrateChanged twice to get a first estimate. TickTime::AdvanceFakeClock(1000); - EXPECT_CALL(rtp, SetREMBData(_, _, _)) + EXPECT_CALL(rtp, SetREMBData(_, _)) .Times(1); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Lower the estimate, should trigger a call to SetREMBData right away. bitrate_estimate = bitrate_estimate - 100; - EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _)) + EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, ssrcs)) .Times(1); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Call OnReceiveBitrateChanged again, this should not trigger a new callback. - EXPECT_CALL(rtp, SetREMBData(_, _, _)) + EXPECT_CALL(rtp, SetREMBData(_, _)) .Times(0); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); vie_remb_->RemoveReceiveChannel(&rtp); @@ -237,13 +237,13 @@ TEST_F(ViERembTest, NoSendingRtpModule) { // Call OnReceiveBitrateChanged twice to get a first estimate. TickTime::AdvanceFakeClock(1000); - EXPECT_CALL(rtp, SetREMBData(_, _, _)) + EXPECT_CALL(rtp, SetREMBData(_, _)) .Times(1); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); // Lower the estimate to trigger a new packet REMB packet. bitrate_estimate = bitrate_estimate - 100; - EXPECT_CALL(rtp, SetREMBData(_, _, _)) + EXPECT_CALL(rtp, SetREMBData(_, _)) .Times(1); vie_remb_->OnReceiveBitrateChanged(ssrcs, bitrate_estimate); } diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_render_impl.cc b/media/webrtc/trunk/webrtc/video_engine/vie_render_impl.cc index 00c0186a26..27920602b6 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_render_impl.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_render_impl.cc @@ -236,23 +236,6 @@ int ViERenderImpl::ConfigureRender(int render_id, const unsigned int z_order, return 0; } -int ViERenderImpl::MirrorRenderStream(const int render_id, const bool enable, - const bool mirror_xaxis, - const bool mirror_yaxis) { - ViERenderManagerScoped rs(*(shared_data_->render_manager())); - ViERenderer* renderer = rs.Renderer(render_id); - if (!renderer) { - shared_data_->SetLastError(kViERenderInvalidRenderId); - return -1; - } - if (renderer->EnableMirroring(render_id, enable, mirror_xaxis, mirror_yaxis) - != 0) { - shared_data_->SetLastError(kViERenderUnknownError); - return -1; - } - return 0; -} - int ViERenderImpl::AddRenderer(const int render_id, RawVideoType video_input_format, ExternalRenderer* external_renderer) { @@ -323,29 +306,4 @@ int ViERenderImpl::AddRenderer(const int render_id, } } -int ViERenderImpl::AddRenderCallback(int render_id, - VideoRenderCallback* callback) { - if (render_id < kViEChannelIdBase || render_id > kViEChannelIdMax) - return -1; - // This is a channel. - ViEChannelManagerScoped cm(*(shared_data_->channel_manager())); - ViEFrameProviderBase* frame_provider = cm.Channel(render_id); - if (!frame_provider) { - shared_data_->SetLastError(kViERenderInvalidRenderId); - return -1; - } - ViERenderer* renderer = shared_data_->render_manager()->AddRenderStream( - render_id, NULL, 0, 0.0f, 0.0f, 1.0f, 1.0f); - if (!renderer) { - shared_data_->SetLastError(kViERenderUnknownError); - return -1; - } - if (renderer->SetVideoRenderCallback(render_id, callback) != 0) { - shared_data_->SetLastError(kViERenderUnknownError); - return -1; - } - - return frame_provider->RegisterFrameCallback(render_id, renderer); -} - } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_render_impl.h b/media/webrtc/trunk/webrtc/video_engine/vie_render_impl.h index 370a7a345c..5b36d1686f 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_render_impl.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_render_impl.h @@ -40,13 +40,8 @@ class ViERenderImpl virtual int ConfigureRender(int render_id, const unsigned int z_order, const float left, const float top, const float right, const float bottom); - virtual int MirrorRenderStream(const int render_id, const bool enable, - const bool mirror_xaxis, - const bool mirror_yaxis); virtual int AddRenderer(const int render_id, RawVideoType video_input_format, ExternalRenderer* renderer); - virtual int AddRenderCallback(int render_id, - VideoRenderCallback* callback) OVERRIDE; protected: explicit ViERenderImpl(ViESharedData* shared_data); diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_render_manager.h b/media/webrtc/trunk/webrtc/video_engine/vie_render_manager.h index c1314cdedc..db1626a1e0 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_render_manager.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_render_manager.h @@ -14,7 +14,7 @@ #include #include -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/typedefs.h" #include "webrtc/video_engine/vie_manager_base.h" @@ -54,7 +54,7 @@ class ViERenderManager : private ViEManagerBase { // Methods used by ViERenderScoped. ViERenderer* ViERenderPtr(int32_t render_id) const; - scoped_ptr list_cs_; + rtc::scoped_ptr list_cs_; int32_t engine_id_; // Protected by ViEManagerBase. typedef std::map RendererMap; diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_renderer.cc b/media/webrtc/trunk/webrtc/video_engine/vie_renderer.cc index b4ec73828d..bfeeba216a 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_renderer.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_renderer.cc @@ -39,8 +39,7 @@ ViERenderer::~ViERenderer(void) { if (render_callback_) render_module_.DeleteIncomingRenderStream(render_id_); - if (incoming_external_callback_) - delete incoming_external_callback_; + delete incoming_external_callback_; } int32_t ViERenderer::StartRender() { @@ -50,11 +49,6 @@ int32_t ViERenderer::StopRender() { return render_module_.StopRender(render_id_); } -int32_t ViERenderer::GetLastRenderedFrame(const int32_t renderID, - I420VideoFrame& video_frame) { - return render_module_.GetLastRenderedFrame(renderID, video_frame); -} - int ViERenderer::SetExpectedRenderDelay(int render_delay) { return render_module_.SetExpectedRenderDelay(render_id_, render_delay); } @@ -72,14 +66,6 @@ VideoRender& ViERenderer::RenderModule() { return render_module_; } -int32_t ViERenderer::EnableMirroring(const int32_t render_id, - const bool enable, - const bool mirror_xaxis, - const bool mirror_yaxis) { - return render_module_.MirrorRenderStream(render_id, enable, mirror_xaxis, - mirror_yaxis); -} - int32_t ViERenderer::SetTimeoutImage(const I420VideoFrame& timeout_image, const int32_t timeout_value) { return render_module_.SetTimeoutImage(render_id_, timeout_image, @@ -137,8 +123,7 @@ int32_t ViERenderer::Init(const uint32_t z_order, void ViERenderer::DeliverFrame(int id, I420VideoFrame* video_frame, - int num_csrcs, - const uint32_t CSRC[kRtpCsrcSize]) { + const std::vector& csrcs) { render_callback_->RenderFrame(render_id_, *video_frame); } @@ -159,8 +144,7 @@ ViEExternalRendererImpl::ViEExternalRendererImpl() : external_renderer_(NULL), external_renderer_format_(kVideoUnknown), external_renderer_width_(0), - external_renderer_height_(0), - converted_frame_(new VideoFrame()) { + external_renderer_height_(0) { } int ViEExternalRendererImpl::SetViEExternalRenderer( @@ -173,7 +157,24 @@ int ViEExternalRendererImpl::SetViEExternalRenderer( int32_t ViEExternalRendererImpl::RenderFrame( const uint32_t stream_id, - I420VideoFrame& video_frame) { + const I420VideoFrame& video_frame) { + if (external_renderer_format_ != kVideoI420) + return ConvertAndRenderFrame(stream_id, video_frame); + + // Fast path for I420 without frame copy. + NotifyFrameSizeChange(stream_id, video_frame); + if (video_frame.native_handle() == NULL || + external_renderer_->IsTextureSupported()) { + external_renderer_->DeliverI420Frame(video_frame); + } else { + // TODO(wuchengli): readback the pixels and deliver the frame. + } + return 0; +} + +int32_t ViEExternalRendererImpl::ConvertAndRenderFrame( + uint32_t stream_id, + const I420VideoFrame& video_frame) { if (video_frame.native_handle() != NULL) { NotifyFrameSizeChange(stream_id, video_frame); @@ -190,31 +191,20 @@ int32_t ViEExternalRendererImpl::RenderFrame( return 0; } - VideoFrame* out_frame = converted_frame_.get(); - // Convert to requested format. VideoType type = RawVideoTypeToCommonVideoVideoType(external_renderer_format_); - int buffer_size = CalcBufferSize(type, video_frame.width(), - video_frame.height()); - if (buffer_size <= 0) { + size_t buffer_size = CalcBufferSize(type, video_frame.width(), + video_frame.height()); + if (buffer_size == 0) { // Unsupported video format. assert(false); return -1; } - converted_frame_->VerifyAndAllocate(buffer_size); + converted_frame_.resize(buffer_size); + uint8_t* out_frame = &converted_frame_[0]; switch (external_renderer_format_) { - case kVideoI420: { - // TODO(mikhal): need to copy the buffer as is. - // can the output here be a I420 frame? - int length = ExtractBuffer(video_frame, out_frame->Size(), - out_frame->Buffer()); - if (length < 0) - return -1; - out_frame->SetLength(length); - break; - } case kVideoYV12: case kVideoYUY2: case kVideoUYVY: @@ -222,13 +212,9 @@ int32_t ViEExternalRendererImpl::RenderFrame( case kVideoRGB24: case kVideoRGB565: case kVideoARGB4444: - case kVideoARGB1555 : - { - if (ConvertFromI420(video_frame, type, 0, - converted_frame_->Buffer()) < 0) - return -1; - converted_frame_->SetLength(buffer_size); - } + case kVideoARGB1555: + if (ConvertFromI420(video_frame, type, 0, out_frame) < 0) + return -1; break; case kVideoIYUV: // no conversion available @@ -242,8 +228,8 @@ int32_t ViEExternalRendererImpl::RenderFrame( NotifyFrameSizeChange(stream_id, video_frame); if (out_frame) { - external_renderer_->DeliverFrame(out_frame->Buffer(), - out_frame->Length(), + external_renderer_->DeliverFrame(out_frame, + converted_frame_.size(), video_frame.timestamp(), video_frame.ntp_time_ms(), video_frame.render_time_ms(), @@ -254,7 +240,7 @@ int32_t ViEExternalRendererImpl::RenderFrame( void ViEExternalRendererImpl::NotifyFrameSizeChange( const uint32_t stream_id, - I420VideoFrame& video_frame) { + const I420VideoFrame& video_frame) { if (external_renderer_width_ != video_frame.width() || external_renderer_height_ != video_frame.height()) { external_renderer_width_ = video_frame.width(); diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_renderer.h b/media/webrtc/trunk/webrtc/video_engine/vie_renderer.h index 907735cad7..5a7fdc19f1 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_renderer.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_renderer.h @@ -11,8 +11,9 @@ #ifndef WEBRTC_VIDEO_ENGINE_VIE_RENDERER_H_ #define WEBRTC_VIDEO_ENGINE_VIE_RENDERER_H_ +#include + #include "webrtc/modules/video_render/include/video_render_defines.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/video_engine/include/vie_render.h" #include "webrtc/video_engine/vie_frame_provider_base.h" @@ -32,17 +33,19 @@ class ViEExternalRendererImpl : public VideoRenderCallback { // Implements VideoRenderCallback. virtual int32_t RenderFrame(const uint32_t stream_id, - I420VideoFrame& video_frame); + const I420VideoFrame& video_frame); private: void NotifyFrameSizeChange(const uint32_t stream_id, - I420VideoFrame& video_frame); + const I420VideoFrame& video_frame); + int32_t ConvertAndRenderFrame(uint32_t stream_id, + const I420VideoFrame& video_frame); ExternalRenderer* external_renderer_; RawVideoType external_renderer_format_; int external_renderer_width_; int external_renderer_height_; // Converted_frame_ in color format specified by render_format_. - scoped_ptr converted_frame_; + std::vector converted_frame_; }; class ViERenderer: public ViEFrameCallback { @@ -61,9 +64,6 @@ class ViERenderer: public ViEFrameCallback { int32_t StartRender(); int32_t StopRender(); - int32_t GetLastRenderedFrame(const int32_t renderID, - I420VideoFrame& video_frame); - int SetExpectedRenderDelay(int render_delay); int32_t ConfigureRenderer(const unsigned int z_order, @@ -74,11 +74,6 @@ class ViERenderer: public ViEFrameCallback { VideoRender& RenderModule(); - int32_t EnableMirroring(const int32_t render_id, - const bool enable, - const bool mirror_xaxis, - const bool mirror_yaxis); - int32_t SetTimeoutImage(const I420VideoFrame& timeout_image, const int32_t timeout_value); int32_t SetRenderStartImage(const I420VideoFrame& start_image); @@ -103,8 +98,7 @@ class ViERenderer: public ViEFrameCallback { // Implement ViEFrameCallback virtual void DeliverFrame(int id, I420VideoFrame* video_frame, - int num_csrcs = 0, - const uint32_t CSRC[kRtpCsrcSize] = NULL); + const std::vector& csrcs); virtual void DelayChanged(int id, int frame_delay); virtual int GetPreferedFrameSettings(int* width, int* height, diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.cc b/media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.cc index 0a6eb4dc51..b8f8bd33a2 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.cc @@ -207,25 +207,10 @@ int ViERTP_RTCPImpl::SetRtxSendPayloadType(const int video_channel, return 0; } -int ViERTP_RTCPImpl::SetPadWithRedundantPayloads(int video_channel, - bool enable) { - LOG_F(LS_INFO) << "channel: " << video_channel - << " pad with redundant payloads: " << (enable ? "enable" : - "disable"); - ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); - ViEChannel* vie_channel = cs.Channel(video_channel); - if (!vie_channel) { - shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); - return -1; - } - vie_channel->SetPadWithRedundantPayloads(enable); - return 0; -} - int ViERTP_RTCPImpl::SetRtxReceivePayloadType(const int video_channel, const uint8_t payload_type) { LOG_F(LS_INFO) << "channel: " << video_channel - << " payload_type: " << static_cast(payload_type); + << " payload_type: " << static_cast(payload_type); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { @@ -292,10 +277,7 @@ int ViERTP_RTCPImpl::SetRTCPStatus(const int video_channel, } RTCPMethod module_mode = ViERTCPModeToRTCPMethod(rtcp_mode); - if (vie_channel->SetRTCPMode(module_mode) != 0) { - shared_data_->SetLastError(kViERtpRtcpUnknownError); - return -1; - } + vie_channel->SetRTCPMode(module_mode); return 0; } @@ -307,11 +289,7 @@ int ViERTP_RTCPImpl::GetRTCPStatus(const int video_channel, shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } - RTCPMethod module_mode = kRtcpOff; - if (vie_channel->GetRTCPMode(&module_mode) != 0) { - shared_data_->SetLastError(kViERtpRtcpUnknownError); - return -1; - } + RTCPMethod module_mode = vie_channel->GetRTCPMode(); rtcp_mode = RTCPMethodToViERTCPMode(module_mode); return 0; } @@ -401,8 +379,8 @@ int ViERTP_RTCPImpl::SendApplicationDefinedRTCPPacket( shared_data_->SetLastError(kViERtpRtcpNotSending); return -1; } - RTCPMethod method; - if (vie_channel->GetRTCPMode(&method) != 0 || method == kRtcpOff) { + RTCPMethod method = vie_channel->GetRTCPMode(); + if (method == kRtcpOff) { shared_data_->SetLastError(kViERtpRtcpRtcpDisabled); return -1; } @@ -435,7 +413,8 @@ int ViERTP_RTCPImpl::SetNACKStatus(const int video_channel, const bool enable) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } - vie_encoder->UpdateProtectionMethod(enable); + vie_encoder->UpdateProtectionMethod(enable, + vie_channel->IsSendingFecEnabled()); return 0; } @@ -463,7 +442,7 @@ int ViERTP_RTCPImpl::SetFECStatus(const int video_channel, const bool enable, shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } - vie_encoder->UpdateProtectionMethod(false); + vie_encoder->UpdateProtectionMethod(false, true); return 0; } @@ -496,7 +475,7 @@ int ViERTP_RTCPImpl::SetHybridNACKFECStatus( shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } - vie_encoder->UpdateProtectionMethod(enable); + vie_encoder->UpdateProtectionMethod(enable, enable); return 0; } @@ -576,10 +555,7 @@ int ViERTP_RTCPImpl::SetTMMBRStatus(const int video_channel, shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } - if (vie_channel->EnableTMMBR(enable) != 0) { - shared_data_->SetLastError(kViERtpRtcpUnknownError); - return -1; - } + vie_channel->EnableTMMBR(enable); return 0; } @@ -619,7 +595,7 @@ int ViERTP_RTCPImpl::SetReceiveTimestampOffsetStatus(int video_channel, bool enable, int id) { LOG_F(LS_INFO) << "channel: " << video_channel - << "enable: " << (enable ? "on" : "off") << " id: " << id; + << " enable: " << (enable ? "on" : "off") << " id: " << id; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { @@ -637,7 +613,7 @@ int ViERTP_RTCPImpl::SetSendAbsoluteSendTimeStatus(int video_channel, bool enable, int id) { LOG_F(LS_INFO) << "channel: " << video_channel - << "enable: " << (enable ? "on" : "off") << " id: " << id; + << " enable: " << (enable ? "on" : "off") << " id: " << id; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); @@ -656,7 +632,7 @@ int ViERTP_RTCPImpl::SetReceiveAbsoluteSendTimeStatus(int video_channel, bool enable, int id) { LOG_F(LS_INFO) << "channel: " << video_channel - << "enable: " << (enable ? "on" : "off") << " id: " << id; + << " enable: " << (enable ? "on" : "off") << " id: " << id; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { @@ -670,6 +646,43 @@ int ViERTP_RTCPImpl::SetReceiveAbsoluteSendTimeStatus(int video_channel, return 0; } +int ViERTP_RTCPImpl::SetSendVideoRotationStatus(int video_channel, + bool enable, + int id) { + LOG_F(LS_INFO) << "channel: " << video_channel + << " enable: " << (enable ? "on" : "off") << " id: " << id; + + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); + return -1; + } + if (vie_channel->SetSendVideoRotationStatus(enable, id) != 0) { + shared_data_->SetLastError(kViERtpRtcpUnknownError); + return -1; + } + return 0; +} + +int ViERTP_RTCPImpl::SetReceiveVideoRotationStatus(int video_channel, + bool enable, + int id) { + LOG_F(LS_INFO) << "channel: " << video_channel + << " enable: " << (enable ? "on" : "off") << " id: " << id; + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); + return -1; + } + if (vie_channel->SetReceiveVideoRotationStatus(enable, id) != 0) { + shared_data_->SetLastError(kViERtpRtcpUnknownError); + return -1; + } + return 0; +} + int ViERTP_RTCPImpl::SetRtcpXrRrtrStatus(int video_channel, bool enable) { LOG_F(LS_INFO) << "channel: " << video_channel << " enable: " << (enable ? "on" : "off"); @@ -725,7 +738,7 @@ int ViERTP_RTCPImpl::SetReservedTransmitBitrate( int ViERTP_RTCPImpl::GetReceiveChannelRtcpStatistics( const int video_channel, RtcpStatistics& basic_stats, - int& rtt_ms) const { + int64_t& rtt_ms) const { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { @@ -750,7 +763,7 @@ int ViERTP_RTCPImpl::GetReceiveChannelRtcpStatistics( int ViERTP_RTCPImpl::GetSendChannelRtcpStatistics(const int video_channel, RtcpStatistics& basic_stats, - int& rtt_ms) const { + int64_t& rtt_ms) const { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { @@ -782,27 +795,39 @@ int ViERTP_RTCPImpl::GetRtpStatistics(const int video_channel, shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } - if (vie_channel->GetRtpStatistics(&sent.bytes, - &sent.packets, - &received.bytes, - &received.packets) != 0) { + if (vie_channel->GetRtpStatistics(&sent.transmitted.payload_bytes, + &sent.transmitted.packets, + &received.transmitted.payload_bytes, + &received.transmitted.packets) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } -int ViERTP_RTCPImpl::GetRtcpPacketTypeCounters( +int ViERTP_RTCPImpl::GetSendRtcpPacketTypeCounter( int video_channel, - RtcpPacketTypeCounter* packets_sent, - RtcpPacketTypeCounter* packets_received) const { + RtcpPacketTypeCounter* packet_counter) const { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } - vie_channel->GetRtcpPacketTypeCounters(packets_sent, packets_received); + vie_channel->GetSendRtcpPacketTypeCounter(packet_counter); + return 0; +} + +int ViERTP_RTCPImpl::GetReceiveRtcpPacketTypeCounter( + int video_channel, + RtcpPacketTypeCounter* packet_counter) const { + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); + return -1; + } + vie_channel->GetReceiveRtcpPacketTypeCounter(packet_counter); return 0; } @@ -861,28 +886,12 @@ int ViERTP_RTCPImpl::GetEstimatedReceiveBandwidth( return 0; } -int ViERTP_RTCPImpl::GetReceiveBandwidthEstimatorStats( - const int video_channel, - ReceiveBandwidthEstimatorStats* output) const { - ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); - ViEChannel* vie_channel = cs.Channel(video_channel); - if (!vie_channel) { - shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); - return -1; - } - vie_channel->GetReceiveBandwidthEstimatorStats(output); - return 0; -} - int ViERTP_RTCPImpl::GetPacerQueuingDelayMs( - const int video_channel, int* delay_ms) const { - ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); - ViEEncoder* vie_encoder = cs.Encoder(video_channel); - if (!vie_encoder) { - shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); + const int video_channel, int64_t* delay_ms) const { + if (!shared_data_->channel_manager()->GetPacerQueuingDelayMs(video_channel, + delay_ms)) { return -1; } - *delay_ms = vie_encoder->PacerQueuingDelayMs(); return 0; } @@ -954,37 +963,6 @@ int ViERTP_RTCPImpl::DeregisterRTPObserver(const int video_channel) { return 0; } -int ViERTP_RTCPImpl::RegisterRTCPObserver(const int video_channel, - ViERTCPObserver& observer) { - LOG_F(LS_INFO) << "channel " << video_channel; - ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); - ViEChannel* vie_channel = cs.Channel(video_channel); - if (!vie_channel) { - shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); - return -1; - } - if (vie_channel->RegisterRtcpObserver(&observer) != 0) { - shared_data_->SetLastError(kViERtpRtcpObserverAlreadyRegistered); - return -1; - } - return 0; -} - -int ViERTP_RTCPImpl::DeregisterRTCPObserver(const int video_channel) { - LOG_F(LS_INFO) << "channel " << video_channel; - ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); - ViEChannel* vie_channel = cs.Channel(video_channel); - if (!vie_channel) { - shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); - return -1; - } - if (vie_channel->RegisterRtcpObserver(NULL) != 0) { - shared_data_->SetLastError(kViERtpRtcpObserverNotRegistered); - return -1; - } - return 0; -} - int ViERTP_RTCPImpl::RegisterSendChannelRtcpStatisticsCallback( int video_channel, RtcpStatisticsCallback* callback) { LOG_F(LS_INFO) << "channel " << video_channel; @@ -1123,4 +1101,18 @@ int ViERTP_RTCPImpl::DeregisterSendFrameCountObserver( vie_channel->RegisterSendFrameCountObserver(NULL); return 0; } + +int ViERTP_RTCPImpl::RegisterRtcpPacketTypeCounterObserver( + int video_channel, + RtcpPacketTypeCounterObserver* observer) { + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); + return -1; + } + vie_channel->RegisterRtcpPacketTypeCounterObserver(observer); + return 0; +} + } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.h b/media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.h index 5953da2f5e..8f92a72525 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.h @@ -41,16 +41,14 @@ class ViERTP_RTCPImpl unsigned int CSRCs[kRtpCsrcSize]) const; virtual int SetRtxSendPayloadType(const int video_channel, const uint8_t payload_type); - virtual int SetPadWithRedundantPayloads(int video_channel, bool enable); virtual int SetRtxReceivePayloadType(const int video_channel, const uint8_t payload_type); virtual int SetStartSequenceNumber(const int video_channel, uint16_t sequence_number); - virtual void SetRtpStateForSsrc(int video_channel, - uint32_t ssrc, - const RtpState& rtp_state) OVERRIDE; - virtual RtpState GetRtpStateForSsrc(int video_channel, - uint32_t ssrc) OVERRIDE; + void SetRtpStateForSsrc(int video_channel, + uint32_t ssrc, + const RtpState& rtp_state) override; + RtpState GetRtpStateForSsrc(int video_channel, uint32_t ssrc) override; virtual int SetRTCPStatus(const int video_channel, const ViERTCPMode rtcp_mode); virtual int GetRTCPStatus(const int video_channel, @@ -101,6 +99,12 @@ class ViERTP_RTCPImpl virtual int SetReceiveAbsoluteSendTimeStatus(int video_channel, bool enable, int id); + virtual int SetSendVideoRotationStatus(int video_channel, + bool enable, + int id); + virtual int SetReceiveVideoRotationStatus(int video_channel, + bool enable, + int id); virtual int SetRtcpXrRrtrStatus(int video_channel, bool enable); virtual int SetTransmissionSmoothingStatus(int video_channel, bool enable); virtual int SetMinTransmitBitrate(int video_channel, @@ -109,17 +113,19 @@ class ViERTP_RTCPImpl int video_channel, unsigned int reserved_transmit_bitrate_bps); virtual int GetReceiveChannelRtcpStatistics(const int video_channel, RtcpStatistics& basic_stats, - int& rtt_ms) const; + int64_t& rtt_ms) const; virtual int GetSendChannelRtcpStatistics(const int video_channel, RtcpStatistics& basic_stats, - int& rtt_ms) const; + int64_t& rtt_ms) const; virtual int GetRtpStatistics(const int video_channel, StreamDataCounters& sent, StreamDataCounters& received) const; - virtual int GetRtcpPacketTypeCounters( + virtual int GetSendRtcpPacketTypeCounter( int video_channel, - RtcpPacketTypeCounter* packets_sent, - RtcpPacketTypeCounter* packets_received) const; + RtcpPacketTypeCounter* packet_counter) const; + virtual int GetReceiveRtcpPacketTypeCounter( + int video_channel, + RtcpPacketTypeCounter* packet_counter) const; virtual int GetRemoteRTCPSenderInfo(const int video_channel, SenderInfo* sender_info) const; virtual int GetBandwidthUsage(const int video_channel, @@ -133,10 +139,8 @@ class ViERTP_RTCPImpl virtual int GetEstimatedReceiveBandwidth( const int video_channel, unsigned int* estimated_bandwidth) const; - virtual int GetReceiveBandwidthEstimatorStats( - const int video_channel, ReceiveBandwidthEstimatorStats* output) const; virtual int GetPacerQueuingDelayMs(const int video_channel, - int* delay_ms) const; + int64_t* delay_ms) const; virtual int StartRTPDump(const int video_channel, const char file_nameUTF8[1024], RTPDirections direction); @@ -144,18 +148,15 @@ class ViERTP_RTCPImpl virtual int RegisterRTPObserver(const int video_channel, ViERTPObserver& observer); virtual int DeregisterRTPObserver(const int video_channel); - virtual int RegisterRTCPObserver(const int video_channel, - ViERTCPObserver& observer); - virtual int DeregisterRTCPObserver(const int video_channel); virtual int RegisterSendChannelRtcpStatisticsCallback( int channel, RtcpStatisticsCallback* callback); virtual int DeregisterSendChannelRtcpStatisticsCallback( int channel, RtcpStatisticsCallback* callback); virtual int RegisterReceiveChannelRtcpStatisticsCallback( - int channel, RtcpStatisticsCallback* callback); - virtual int DeregisterReceiveChannelRtcpStatisticsCallback( - int channel, RtcpStatisticsCallback* callback); + int channel, RtcpStatisticsCallback* callback); + virtual int DeregisterReceiveChannelRtcpStatisticsCallback( + int channel, RtcpStatisticsCallback* callback); virtual int RegisterSendChannelRtpStatisticsCallback( int channel, StreamDataCountersCallback* callback); virtual int DeregisterSendChannelRtpStatisticsCallback( @@ -172,6 +173,9 @@ class ViERTP_RTCPImpl int channel, FrameCountObserver* callback); virtual int DeregisterSendFrameCountObserver( int channel, FrameCountObserver* callback); + int RegisterRtcpPacketTypeCounterObserver( + int video_channel, + RtcpPacketTypeCounterObserver* observer) override; protected: explicit ViERTP_RTCPImpl(ViESharedData* shared_data); diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_sender.cc b/media/webrtc/trunk/webrtc/video_engine/vie_sender.cc index 28bf390334..db7a5b116d 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_sender.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_sender.cc @@ -85,7 +85,7 @@ int ViESender::StopRTPDump() { return 0; } -int ViESender::SendPacket(int vie_id, const void* data, int len) { +int ViESender::SendPacket(int vie_id, const void* data, size_t len) { CriticalSectionScoped cs(critsect_.get()); if (!transport_) { // No transport @@ -94,14 +94,13 @@ int ViESender::SendPacket(int vie_id, const void* data, int len) { assert(ChannelId(vie_id) == channel_id_); if (rtp_dump_) { - rtp_dump_->DumpPacket(static_cast(data), - static_cast(len)); + rtp_dump_->DumpPacket(static_cast(data), len); } return transport_->SendPacket(channel_id_, data, len); } -int ViESender::SendRTCPPacket(int vie_id, const void* data, int len) { +int ViESender::SendRTCPPacket(int vie_id, const void* data, size_t len) { CriticalSectionScoped cs(critsect_.get()); if (!transport_) { return -1; @@ -109,8 +108,7 @@ int ViESender::SendRTCPPacket(int vie_id, const void* data, int len) { assert(ChannelId(vie_id) == channel_id_); if (rtp_dump_) { - rtp_dump_->DumpPacket(static_cast(data), - static_cast(len)); + rtp_dump_->DumpPacket(static_cast(data), len); } return transport_->SendRTCPPacket(channel_id_, data, len); diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_sender.h b/media/webrtc/trunk/webrtc/video_engine/vie_sender.h index f910cb1af6..3e6bd95549 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_sender.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_sender.h @@ -13,9 +13,9 @@ #ifndef WEBRTC_VIDEO_ENGINE_VIE_SENDER_H_ #define WEBRTC_VIDEO_ENGINE_VIE_SENDER_H_ +#include "webrtc/base/scoped_ptr.h" #include "webrtc/common_types.h" #include "webrtc/engine_configurations.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/typedefs.h" #include "webrtc/video_engine/vie_defines.h" @@ -40,13 +40,13 @@ class ViESender: public Transport { int StopRTPDump(); // Implements Transport. - virtual int SendPacket(int vie_id, const void* data, int len) OVERRIDE; - virtual int SendRTCPPacket(int vie_id, const void* data, int len) OVERRIDE; + int SendPacket(int vie_id, const void* data, size_t len) override; + int SendRTCPPacket(int vie_id, const void* data, size_t len) override; private: const int32_t channel_id_; - scoped_ptr critsect_; + rtc::scoped_ptr critsect_; Transport* transport_; RtpDump* rtp_dump_; diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_shared_data.cc b/media/webrtc/trunk/webrtc/video_engine/vie_shared_data.cc index 6a6989430e..39ad2843dc 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_shared_data.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_shared_data.cc @@ -24,12 +24,12 @@ ViESharedData::ViESharedData(const Config& config) channel_manager_(new ViEChannelManager(0, number_cores_, config)), input_manager_(new ViEInputManager(0, config)), render_manager_(new ViERenderManager(0)), - module_process_thread_(ProcessThread::CreateProcessThread()), + module_process_thread_(ProcessThread::Create()), load_manager_(NULL), last_error_(0) { Trace::CreateTrace(); - channel_manager_->SetModuleProcessThread(module_process_thread_); - input_manager_->SetModuleProcessThread(module_process_thread_); + channel_manager_->SetModuleProcessThread(module_process_thread_.get()); + input_manager_->SetModuleProcessThread(module_process_thread_.get()); module_process_thread_->Start(); } @@ -40,7 +40,6 @@ ViESharedData::~ViESharedData() { render_manager_.reset(); module_process_thread_->Stop(); - ProcessThread::DestroyProcessThread(module_process_thread_); Trace::ReturnTrace(); } diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_shared_data.h b/media/webrtc/trunk/webrtc/video_engine/vie_shared_data.h index 1eac5c8daa..53d4f2d96c 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_shared_data.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_shared_data.h @@ -16,7 +16,7 @@ #include -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/base/scoped_ptr.h" namespace webrtc { @@ -51,10 +51,10 @@ class ViESharedData { private: const int number_cores_; - scoped_ptr channel_manager_; - scoped_ptr input_manager_; - scoped_ptr render_manager_; - ProcessThread* module_process_thread_; + rtc::scoped_ptr channel_manager_; + rtc::scoped_ptr input_manager_; + rtc::scoped_ptr render_manager_; + rtc::scoped_ptr module_process_thread_; // Owned by PeerConnection, not ViEEngine CPULoadStateCallbackInvoker* load_manager_; mutable int last_error_; diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_sync_module.cc b/media/webrtc/trunk/webrtc/video_engine/vie_sync_module.cc index c24087139f..cf592927a8 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_sync_module.cc +++ b/media/webrtc/trunk/webrtc/video_engine/vie_sync_module.cc @@ -22,8 +22,6 @@ namespace webrtc { -enum { kSyncInterval = 1000}; - int UpdateMeasurements(StreamSynchronization::Measurements* stream, const RtpRtcp& rtp_rtcp, const RtpReceiver& receiver) { if (!receiver.Timestamp(&stream->latest_timestamp)) @@ -93,9 +91,9 @@ int ViESyncModule::VoiceChannel() { return voe_channel_id_; } -int32_t ViESyncModule::TimeUntilNextProcess() { - return static_cast(kSyncInterval - - (TickTime::Now() - last_sync_time_).Milliseconds()); +int64_t ViESyncModule::TimeUntilNextProcess() { + const int64_t kSyncIntervalMs = 1000; + return kSyncIntervalMs - (TickTime::Now() - last_sync_time_).Milliseconds(); } int32_t ViESyncModule::Process() { diff --git a/media/webrtc/trunk/webrtc/video_engine/vie_sync_module.h b/media/webrtc/trunk/webrtc/video_engine/vie_sync_module.h index e6ca5fd275..a75d716c08 100644 --- a/media/webrtc/trunk/webrtc/video_engine/vie_sync_module.h +++ b/media/webrtc/trunk/webrtc/video_engine/vie_sync_module.h @@ -14,8 +14,8 @@ #ifndef WEBRTC_VIDEO_ENGINE_VIE_SYNC_MODULE_H_ #define WEBRTC_VIDEO_ENGINE_VIE_SYNC_MODULE_H_ +#include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/interface/module.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/tick_util.h" #include "webrtc/video_engine/stream_synchronization.h" #include "webrtc/voice_engine/include/voe_video_sync.h" @@ -45,11 +45,11 @@ class ViESyncModule : public Module { int SetTargetBufferingDelay(int target_delay_ms); // Implements Module. - virtual int32_t TimeUntilNextProcess() OVERRIDE; - virtual int32_t Process() OVERRIDE; + int64_t TimeUntilNextProcess() override; + int32_t Process() override; private: - scoped_ptr data_cs_; + rtc::scoped_ptr data_cs_; VideoCodingModule* vcm_; ViEChannel* vie_channel_; RtpReceiver* video_receiver_; @@ -57,7 +57,7 @@ class ViESyncModule : public Module { int voe_channel_id_; VoEVideoSync* voe_sync_interface_; TickTime last_sync_time_; - scoped_ptr sync_; + rtc::scoped_ptr sync_; StreamSynchronization::Measurements audio_measurement_; StreamSynchronization::Measurements video_measurement_; }; diff --git a/media/webrtc/trunk/webrtc/video_engine_tests.isolate b/media/webrtc/trunk/webrtc/video_engine_tests.isolate index fc840829b9..5aa962323d 100644 --- a/media/webrtc/trunk/webrtc/video_engine_tests.isolate +++ b/media/webrtc/trunk/webrtc/video_engine_tests.isolate @@ -7,11 +7,10 @@ # be found in the AUTHORS file in the root of the source tree. { 'conditions': [ - ['OS=="android"', { + ['OS=="linux" or OS=="mac" or OS=="win" or OS=="android"', { 'variables': { 'files': [ - '<(DEPTH)/data/', - '<(DEPTH)/resources/', + '<(DEPTH)/resources/foreman_cif_short.yuv', ], }, }], @@ -22,7 +21,6 @@ ], 'files': [ '<(DEPTH)/DEPS', - '<(DEPTH)/resources/foreman_cif_short.yuv', '<(PRODUCT_DIR)/video_engine_tests<(EXECUTABLE_SUFFIX)', ], }, diff --git a/media/webrtc/trunk/webrtc/video_frame.h b/media/webrtc/trunk/webrtc/video_frame.h index f76b9af373..bd3e2b8a63 100644 --- a/media/webrtc/trunk/webrtc/video_frame.h +++ b/media/webrtc/trunk/webrtc/video_frame.h @@ -11,160 +11,161 @@ #ifndef WEBRTC_VIDEO_FRAME_H_ #define WEBRTC_VIDEO_FRAME_H_ -#include - -#include "webrtc/common_video/plane.h" -// TODO(pbos): Remove scoped_refptr include (and AddRef/Release if they're not -// used). -#include "webrtc/system_wrappers/interface/scoped_refptr.h" +#include "webrtc/base/scoped_ref_ptr.h" +#include "webrtc/common_video/interface/native_handle.h" +#include "webrtc/common_video/interface/video_frame_buffer.h" +#include "webrtc/common_video/rotation.h" #include "webrtc/typedefs.h" namespace webrtc { -enum PlaneType { - kYPlane = 0, - kUPlane = 1, - kVPlane = 2, - kNumOfPlanes = 3 -}; - class I420VideoFrame { public: I420VideoFrame(); - virtual ~I420VideoFrame(); - // Infrastructure for refCount implementation. - // Implements dummy functions for reference counting so that non reference - // counted instantiation can be done. These functions should not be called - // when creating the frame with new I420VideoFrame(). - // Note: do not pass a I420VideoFrame created with new I420VideoFrame() or - // equivalent to a scoped_refptr or memory leak will occur. - virtual int32_t AddRef() { - assert(false); - return -1; - } - virtual int32_t Release() { - assert(false); - return -1; - } + I420VideoFrame(const rtc::scoped_refptr& buffer, + uint32_t timestamp, + int64_t render_time_ms, + VideoRotation rotation); + I420VideoFrame(NativeHandle* handle, + int width, + int height, + uint32_t timestamp, + int64_t render_time_ms); + + // TODO(pbos): Make all create/copy functions void, they should not be able to + // fail (which should be DCHECK/CHECKed instead). // CreateEmptyFrame: Sets frame dimensions and allocates buffers based // on set dimensions - height and plane stride. // If required size is bigger than the allocated one, new buffers of adequate // size will be allocated. // Return value: 0 on success, -1 on error. - virtual int CreateEmptyFrame(int width, - int height, - int stride_y, - int stride_u, - int stride_v); + int CreateEmptyFrame(int width, + int height, + int stride_y, + int stride_u, + int stride_v); // CreateFrame: Sets the frame's members and buffers. If required size is // bigger than allocated one, new buffers of adequate size will be allocated. // Return value: 0 on success, -1 on error. - virtual int CreateFrame(int size_y, - const uint8_t* buffer_y, - int size_u, - const uint8_t* buffer_u, - int size_v, - const uint8_t* buffer_v, - int width, - int height, - int stride_y, - int stride_u, - int stride_v); + int CreateFrame(const uint8_t* buffer_y, + const uint8_t* buffer_u, + const uint8_t* buffer_v, + int width, + int height, + int stride_y, + int stride_u, + int stride_v); - // Copy frame: If required size is bigger than allocated one, new buffers of - // adequate size will be allocated. + // TODO(guoweis): remove the previous CreateFrame when chromium has this code. + int CreateFrame(const uint8_t* buffer_y, + const uint8_t* buffer_u, + const uint8_t* buffer_v, + int width, + int height, + int stride_y, + int stride_u, + int stride_v, + VideoRotation rotation); + + // CreateFrame: Sets the frame's members and buffers. If required size is + // bigger than allocated one, new buffers of adequate size will be allocated. + // |buffer| must be a packed I420 buffer. // Return value: 0 on success, -1 on error. - virtual int CopyFrame(const I420VideoFrame& videoFrame); + int CreateFrame(const uint8_t* buffer, + int width, + int height, + VideoRotation rotation); - // Make a copy of |this|. The caller owns the returned frame. - // Return value: a new frame on success, NULL on error. - virtual I420VideoFrame* CloneFrame() const; + // Deep copy frame: If required size is bigger than allocated one, new + // buffers of adequate size will be allocated. + // Return value: 0 on success, -1 on error. + int CopyFrame(const I420VideoFrame& videoFrame); - // Swap Frame. - virtual void SwapFrame(I420VideoFrame* videoFrame); + // Creates a shallow copy of |videoFrame|, i.e, the this object will retain a + // reference to the video buffer also retained by |videoFrame|. + void ShallowCopy(const I420VideoFrame& videoFrame); + + // Release frame buffer and reset time stamps. + void Reset(); // Get pointer to buffer per plane. - virtual uint8_t* buffer(PlaneType type); + uint8_t* buffer(PlaneType type); // Overloading with const. - virtual const uint8_t* buffer(PlaneType type) const; + const uint8_t* buffer(PlaneType type) const; // Get allocated size per plane. - virtual int allocated_size(PlaneType type) const; + int allocated_size(PlaneType type) const; // Get allocated stride per plane. - virtual int stride(PlaneType type) const; - - // Set frame width. - virtual int set_width(int width); - - // Set frame height. - virtual int set_height(int height); + int stride(PlaneType type) const; // Get frame width. - virtual int width() const { return width_; } + int width() const; // Get frame height. - virtual int height() const { return height_; } + int height() const; // Set frame timestamp (90kHz). - virtual void set_timestamp(uint32_t timestamp) { timestamp_ = timestamp; } + void set_timestamp(uint32_t timestamp) { timestamp_ = timestamp; } // Get frame timestamp (90kHz). - virtual uint32_t timestamp() const { return timestamp_; } + uint32_t timestamp() const { return timestamp_; } // Set capture ntp time in miliseconds. - virtual void set_ntp_time_ms(int64_t ntp_time_ms) { + void set_ntp_time_ms(int64_t ntp_time_ms) { ntp_time_ms_ = ntp_time_ms; } // Get capture ntp time in miliseconds. - virtual int64_t ntp_time_ms() const { return ntp_time_ms_; } + int64_t ntp_time_ms() const { return ntp_time_ms_; } + + // Naming convention for Coordination of Video Orientation. Please see + // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ts_126114v120700p.pdf + // + // "pending rotation" or "pending" = a frame that has a VideoRotation > 0. + // + // "not pending" = a frame that has a VideoRotation == 0. + // + // "apply rotation" = modify a frame from being "pending" to being "not + // pending" rotation (a no-op for "unrotated"). + // + VideoRotation rotation() const { return rotation_; } + void set_rotation(VideoRotation rotation) { + rotation_ = rotation; + } // Set render time in miliseconds. - virtual void set_render_time_ms(int64_t render_time_ms) { + void set_render_time_ms(int64_t render_time_ms) { render_time_ms_ = render_time_ms; } // Get render time in miliseconds. - virtual int64_t render_time_ms() const { return render_time_ms_; } + int64_t render_time_ms() const { return render_time_ms_; } // Return true if underlying plane buffers are of zero size, false if not. - virtual bool IsZeroSize() const; - - // Reset underlying plane buffers sizes to 0. This function doesn't - // clear memory. - virtual void ResetSize(); + bool IsZeroSize() const; // Return the handle of the underlying video frame. This is used when the // frame is backed by a texture. The object should be destroyed when it is no // longer in use, so the underlying resource can be freed. - virtual void* native_handle() const; + void* native_handle() const; - protected: - // Verifies legality of parameters. - // Return value: 0 on success, -1 on error. - virtual int CheckDimensions(int width, - int height, - int stride_y, - int stride_u, - int stride_v); + // Return the underlying buffer. + rtc::scoped_refptr video_frame_buffer() const; + + // Set the underlying buffer. + void set_video_frame_buffer( + const rtc::scoped_refptr& buffer); private: - // Get the pointer to a specific plane. - const Plane* GetPlane(PlaneType type) const; - // Overloading with non-const. - Plane* GetPlane(PlaneType type); - - Plane y_plane_; - Plane u_plane_; - Plane v_plane_; - int width_; - int height_; + // An opaque reference counted handle that stores the pixel data. + rtc::scoped_refptr video_frame_buffer_; uint32_t timestamp_; int64_t ntp_time_ms_; int64_t render_time_ms_; + VideoRotation rotation_; }; enum VideoFrameType { @@ -178,42 +179,23 @@ enum VideoFrameType { // TODO(pbos): Rename EncodedFrame and reformat this class' members. class EncodedImage { public: - EncodedImage() - : _encodedWidth(0), - _encodedHeight(0), - _timeStamp(0), - capture_time_ms_(0), - _frameType(kDeltaFrame), - _buffer(NULL), - _length(0), - _size(0), - _completeFrame(false) {} + EncodedImage() : EncodedImage(nullptr, 0, 0) {} + EncodedImage(uint8_t* buffer, size_t length, size_t size) + : _buffer(buffer), _length(length), _size(size) {} - EncodedImage(uint8_t* buffer, uint32_t length, uint32_t size) - : _encodedWidth(0), - _encodedHeight(0), - _timeStamp(0), - ntp_time_ms_(0), - capture_time_ms_(0), - _frameType(kDeltaFrame), - _buffer(buffer), - _length(length), - _size(size), - _completeFrame(false) {} - - uint32_t _encodedWidth; - uint32_t _encodedHeight; - uint32_t _timeStamp; + uint32_t _encodedWidth = 0; + uint32_t _encodedHeight = 0; + uint32_t _timeStamp = 0; // NTP time of the capture time in local timebase in milliseconds. - int64_t ntp_time_ms_; - int64_t capture_time_ms_; - VideoFrameType _frameType; + int64_t ntp_time_ms_ = 0; + int64_t capture_time_ms_ = 0; + // TODO(pbos): Use webrtc::FrameType directly (and remove VideoFrameType). + VideoFrameType _frameType = kDeltaFrame; uint8_t* _buffer; - uint32_t _length; - uint32_t _size; - bool _completeFrame; + size_t _length; + size_t _size; + bool _completeFrame = false; }; } // namespace webrtc #endif // WEBRTC_VIDEO_FRAME_H_ - diff --git a/media/webrtc/trunk/webrtc/video_receive_stream.h b/media/webrtc/trunk/webrtc/video_receive_stream.h index a8620d98c3..0f2151df03 100644 --- a/media/webrtc/trunk/webrtc/video_receive_stream.h +++ b/media/webrtc/trunk/webrtc/video_receive_stream.h @@ -39,8 +39,9 @@ class VideoReceiveStream { Decoder() : decoder(NULL), payload_type(0), - renderer(false), + is_renderer(false), expected_delay_ms(0) {} + std::string ToString() const; // The actual decoder instance. VideoDecoder* decoder; @@ -54,7 +55,7 @@ class VideoReceiveStream { std::string payload_name; // 'true' if the decoder handles rendering as well. - bool renderer; + bool is_renderer; // The expected delay for decoding and rendering, i.e. the frame will be // delivered this many milliseconds, if possible, earlier than the ideal @@ -63,22 +64,29 @@ class VideoReceiveStream { int expected_delay_ms; }; - struct Stats : public SsrcStats { - Stats() - : network_frame_rate(0), - decode_frame_rate(0), - render_frame_rate(0), - avg_delay_ms(0), - discarded_packets(0), - ssrc(0) {} + struct Stats { + int network_frame_rate = 0; + int decode_frame_rate = 0; + int render_frame_rate = 0; - int network_frame_rate; - int decode_frame_rate; - int render_frame_rate; - int avg_delay_ms; - int discarded_packets; - uint32_t ssrc; + // Decoder stats. + FrameCounts frame_counts; + int decode_ms = 0; + int max_decode_ms = 0; + int current_delay_ms = 0; + int target_delay_ms = 0; + int jitter_buffer_ms = 0; + int min_playout_delay_ms = 0; + int render_delay_ms = 0; + + int total_bitrate_bps = 0; + int discarded_packets = 0; + + uint32_t ssrc = 0; std::string c_name; + StreamDataCounters rtp_stats; + RtcpPacketTypeCounter rtcp_packet_type_counts; + RtcpStatistics rtcp_stats; }; struct Config { @@ -89,6 +97,7 @@ class VideoReceiveStream { pre_decode_callback(NULL), pre_render_callback(NULL), target_delay_ms(0) {} + std::string ToString() const; // Decoders for every payload that we can receive. std::vector decoders; @@ -100,6 +109,7 @@ class VideoReceiveStream { local_ssrc(0), rtcp_mode(newapi::kRtcpReducedSize), remb(true) {} + std::string ToString() const; // Synchronization source (stream identifier) to be received. uint32_t remote_ssrc; diff --git a/media/webrtc/trunk/webrtc/video_renderer.h b/media/webrtc/trunk/webrtc/video_renderer.h index 3946499475..34d339a508 100644 --- a/media/webrtc/trunk/webrtc/video_renderer.h +++ b/media/webrtc/trunk/webrtc/video_renderer.h @@ -23,6 +23,8 @@ class VideoRenderer { virtual void RenderFrame(const I420VideoFrame& video_frame, int time_to_render_ms) = 0; + virtual bool IsTextureSupported() const = 0; + protected: virtual ~VideoRenderer() {} }; diff --git a/media/webrtc/trunk/webrtc/video_send_stream.h b/media/webrtc/trunk/webrtc/video_send_stream.h index a9aba94526..4ae0b6b58a 100644 --- a/media/webrtc/trunk/webrtc/video_send_stream.h +++ b/media/webrtc/trunk/webrtc/video_send_stream.h @@ -29,7 +29,7 @@ class VideoSendStreamInput { // These methods do not lock internally and must be called sequentially. // If your application switches input sources synchronization must be done // externally to make sure that any old frames are not delivered concurrently. - virtual void SwapFrame(I420VideoFrame* video_frame) = 0; + virtual void IncomingCapturedFrame(const I420VideoFrame& video_frame) = 0; protected: virtual ~VideoSendStreamInput() {} @@ -37,17 +37,37 @@ class VideoSendStreamInput { class VideoSendStream { public: + struct StreamStats { + FrameCounts frame_counts; + int width = 0; + int height = 0; + // TODO(holmer): Move bitrate_bps out to the webrtc::Call layer. + int total_bitrate_bps = 0; + int retransmit_bitrate_bps = 0; + int avg_delay_ms = 0; + int max_delay_ms = 0; + StreamDataCounters rtp_stats; + RtcpPacketTypeCounter rtcp_packet_type_counts; + RtcpStatistics rtcp_stats; + }; + struct Stats { Stats() : input_frame_rate(0), encode_frame_rate(0), + avg_encode_time_ms(0), + encode_usage_percent(0), + target_media_bitrate_bps(0), media_bitrate_bps(0), suspended(false) {} int input_frame_rate; int encode_frame_rate; + int avg_encode_time_ms; + int encode_usage_percent; + int target_media_bitrate_bps; int media_bitrate_bps; bool suspended; - std::map substreams; + std::map substreams; }; struct Config { @@ -70,7 +90,7 @@ class VideoSendStream { // Uninitialized VideoEncoder instance to be used for encoding. Will be // initialized from inside the VideoSendStream. - webrtc::VideoEncoder* encoder; + VideoEncoder* encoder; } encoder_settings; static const size_t kDefaultMaxPacketSize = 1500 - 40; // TCP over IPv4. @@ -95,17 +115,13 @@ class VideoSendStream { // Settings for RTP retransmission payload format, see RFC 4588 for // details. struct Rtx { - Rtx() : payload_type(-1), pad_with_redundant_payloads(false) {} + Rtx() : payload_type(-1) {} std::string ToString() const; // SSRCs to use for the RTX streams. std::vector ssrcs; // Payload type to use for the RTX stream. int payload_type; - // Use redundant payloads to pad the bitrate. Instead of padding with - // randomized packets, we will preemptively retransmit media packets on - // the RTX stream. - bool pad_with_redundant_payloads; } rtx; // RTCP CNAME, see RFC 3550. @@ -151,7 +167,7 @@ class VideoSendStream { // with the VideoStream settings. virtual bool ReconfigureVideoEncoder(const VideoEncoderConfig& config) = 0; - virtual Stats GetStats() const = 0; + virtual Stats GetStats() = 0; protected: virtual ~VideoSendStream() {} diff --git a/media/webrtc/trunk/webrtc/voice_engine/BUILD.gn b/media/webrtc/trunk/webrtc/voice_engine/BUILD.gn index 126d2c811e..c55dc8ed07 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/BUILD.gn +++ b/media/webrtc/trunk/webrtc/voice_engine/BUILD.gn @@ -11,9 +11,6 @@ import("../build/webrtc.gni") source_set("voice_engine") { sources = [ - "../common_types.h", - "../engine_configurations.h", - "../typedefs.h", "include/voe_audio_processing.h", "include/voe_base.h", "include/voe_codec.h", @@ -82,6 +79,11 @@ source_set("voice_engine") { if (is_win) { defines = [ "WEBRTC_DRIFT_COMPENSATION_SUPPORTED" ] + + cflags = [ + # TODO(kjellander): Bug 261: fix this warning. + "/wd4373", # virtual function override. + ] } configs += [ "..:common_config" ] @@ -94,6 +96,7 @@ source_set("voice_engine") { } deps = [ + "..:webrtc_common", "../common_audio", "../modules/audio_coding", "../modules/audio_conference_mixer", diff --git a/media/webrtc/trunk/webrtc/voice_engine/channel.cc b/media/webrtc/trunk/webrtc/voice_engine/channel.cc index d97bad3880..c4ddd2fe94 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/channel.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/channel.cc @@ -10,6 +10,7 @@ #include "webrtc/voice_engine/channel.h" +#include "webrtc/base/format_macros.h" #include "webrtc/base/timeutils.h" #include "webrtc/common.h" #include "webrtc/modules/audio_device/include/audio_device.h" @@ -58,8 +59,8 @@ class StatisticsProxy : public RtcpStatisticsCallback { ssrc_(ssrc) {} virtual ~StatisticsProxy() {} - virtual void StatisticsUpdated(const RtcpStatistics& statistics, - uint32_t ssrc) OVERRIDE { + void StatisticsUpdated(const RtcpStatistics& statistics, + uint32_t ssrc) override { if (ssrc != ssrc_) return; @@ -70,6 +71,8 @@ class StatisticsProxy : public RtcpStatisticsCallback { } } + void CNameChanged(const char* cname, uint32_t ssrc) override {} + void ResetStatistics() { CriticalSectionScoped cs(stats_lock_.get()); stats_ = ChannelStatistics(); @@ -84,27 +87,63 @@ class StatisticsProxy : public RtcpStatisticsCallback { // StatisticsUpdated calls are triggered from threads in the RTP module, // while GetStats calls can be triggered from the public voice engine API, // hence synchronization is needed. - scoped_ptr stats_lock_; + rtc::scoped_ptr stats_lock_; const uint32_t ssrc_; ChannelStatistics stats_; }; -class VoEBitrateObserver : public BitrateObserver { +class VoERtcpObserver : public RtcpBandwidthObserver { public: - explicit VoEBitrateObserver(Channel* owner) - : owner_(owner) {} - virtual ~VoEBitrateObserver() {} + explicit VoERtcpObserver(Channel* owner) : owner_(owner) {} + virtual ~VoERtcpObserver() {} - // Implements BitrateObserver. - virtual void OnNetworkChanged(const uint32_t bitrate_bps, - const uint8_t fraction_lost, - const uint32_t rtt) OVERRIDE { - // |fraction_lost| has a scale of 0 - 255. - owner_->OnNetworkChanged(bitrate_bps, fraction_lost, rtt); + void OnReceivedEstimatedBitrate(uint32_t bitrate) override { + // Not used for Voice Engine. + } + + void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks, + int64_t rtt, + int64_t now_ms) override { + // TODO(mflodman): Do we need to aggregate reports here or can we jut send + // what we get? I.e. do we ever get multiple reports bundled into one RTCP + // report for VoiceEngine? + if (report_blocks.empty()) + return; + + int fraction_lost_aggregate = 0; + int total_number_of_packets = 0; + + // If receiving multiple report blocks, calculate the weighted average based + // on the number of packets a report refers to. + for (ReportBlockList::const_iterator block_it = report_blocks.begin(); + block_it != report_blocks.end(); ++block_it) { + // Find the previous extended high sequence number for this remote SSRC, + // to calculate the number of RTP packets this report refers to. Ignore if + // we haven't seen this SSRC before. + std::map::iterator seq_num_it = + extended_max_sequence_number_.find(block_it->sourceSSRC); + int number_of_packets = 0; + if (seq_num_it != extended_max_sequence_number_.end()) { + number_of_packets = block_it->extendedHighSeqNum - seq_num_it->second; + } + fraction_lost_aggregate += number_of_packets * block_it->fractionLost; + total_number_of_packets += number_of_packets; + + extended_max_sequence_number_[block_it->sourceSSRC] = + block_it->extendedHighSeqNum; + } + int weighted_fraction_lost = 0; + if (total_number_of_packets > 0) { + weighted_fraction_lost = (fraction_lost_aggregate + + total_number_of_packets / 2) / total_number_of_packets; + } + owner_->OnIncomingFractionLoss(weighted_fraction_lost); } private: Channel* owner_; + // Maps remote side ssrc to extended highest sequence number received. + std::map extended_max_sequence_number_; }; int32_t @@ -112,13 +151,14 @@ Channel::SendData(FrameType frameType, uint8_t payloadType, uint32_t timeStamp, const uint8_t* payloadData, - uint16_t payloadSize, + size_t payloadSize, const RTPFragmentationHeader* fragmentation) { WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), "Channel::SendData(frameType=%u, payloadType=%u, timeStamp=%u," - " payloadSize=%u, fragmentation=0x%x)", - frameType, payloadType, timeStamp, payloadSize, fragmentation); + " payloadSize=%" PRIuS ", fragmentation=0x%x)", + frameType, payloadType, timeStamp, + payloadSize, fragmentation); if (_includeAudioLevelIndication) { @@ -155,14 +195,13 @@ Channel::SendData(FrameType frameType, } int32_t -Channel::InFrameType(int16_t frameType) +Channel::InFrameType(FrameType frame_type) { WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), - "Channel::InFrameType(frameType=%d)", frameType); + "Channel::InFrameType(frame_type=%d)", frame_type); CriticalSectionScoped cs(&_callbackCritSect); - // 1 indicates speech - _sendFrameType = (frameType == 1) ? 1 : 0; + _sendFrameType = (frame_type == kAudioFrameSpeech); return 0; } @@ -182,13 +221,14 @@ Channel::OnRxVadDetected(int vadDecision) } int -Channel::SendPacket(int channel, const void *data, int len) +Channel::SendPacket(int channel, const void *data, size_t len) { channel = VoEChannelId(channel); assert(channel == _channelId); WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), - "Channel::SendPacket(channel=%d, len=%d)", channel, len); + "Channel::SendPacket(channel=%d, len=%" PRIuS ")", channel, + len); CriticalSectionScoped cs(&_callbackCritSect); @@ -201,7 +241,7 @@ Channel::SendPacket(int channel, const void *data, int len) } uint8_t* bufferToSendPtr = (uint8_t*)data; - int32_t bufferLength = len; + size_t bufferLength = len; // Dump the RTP packet to a file (if RTP dump is enabled). if (_rtpDumpOut.DumpPacket((const uint8_t*)data, len) == -1) @@ -226,13 +266,14 @@ Channel::SendPacket(int channel, const void *data, int len) } int -Channel::SendRTCPPacket(int channel, const void *data, int len) +Channel::SendRTCPPacket(int channel, const void *data, size_t len) { channel = VoEChannelId(channel); assert(channel == _channelId); WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), - "Channel::SendRTCPPacket(channel=%d, len=%d)", channel, len); + "Channel::SendRTCPPacket(channel=%d, len=%" PRIuS ")", channel, + len); CriticalSectionScoped cs(&_callbackCritSect); if (_transportPtr == NULL) @@ -245,7 +286,7 @@ Channel::SendRTCPPacket(int channel, const void *data, int len) } uint8_t* bufferToSendPtr = (uint8_t*)data; - int32_t bufferLength = len; + size_t bufferLength = len; // Dump the RTCP packet to a file (if RTP dump is enabled). if (_rtpDumpOut.DumpPacket((const uint8_t*)data, len) == -1) @@ -323,36 +364,6 @@ void Channel::ResetStatistics(uint32_t ssrc) { statistics_proxy_->ResetStatistics(); } -void -Channel::OnApplicationDataReceived(int32_t id, - uint8_t subType, - uint32_t name, - uint16_t length, - const uint8_t* data) -{ - WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), - "Channel::OnApplicationDataReceived(id=%d, subType=%u," - " name=%u, length=%u)", - id, subType, name, length); - - int32_t channel = VoEChannelId(id); - assert(channel == _channelId); - - if (_rtcpObserver) - { - CriticalSectionScoped cs(&_callbackCritSect); - - if (_rtcpObserverPtr) - { - _rtcpObserverPtr->OnApplicationDataReceived(channel, - subType, - name, - data, - length); - } - } -} - int32_t Channel::OnInitializeDecoder( int32_t id, @@ -397,11 +408,11 @@ Channel::OnInitializeDecoder( int32_t Channel::OnReceivedPayloadData(const uint8_t* payloadData, - uint16_t payloadSize, + size_t payloadSize, const WebRtcRTPHeader* rtpHeader) { WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), - "Channel::OnReceivedPayloadData(payloadSize=%d," + "Channel::OnReceivedPayloadData(payloadSize=%" PRIuS "," " payloadType=%u, audioChannel=%u)", payloadSize, rtpHeader->header.payloadType, @@ -434,7 +445,7 @@ Channel::OnReceivedPayloadData(const uint8_t* payloadData, UpdatePacketDelay(rtpHeader->header.timestamp, rtpHeader->header.sequenceNumber); - uint16_t round_trip_time = 0; + int64_t round_trip_time = 0; _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), &round_trip_time, NULL, NULL, NULL); @@ -449,7 +460,7 @@ Channel::OnReceivedPayloadData(const uint8_t* payloadData, } bool Channel::OnRecoveredPacket(const uint8_t* rtp_packet, - int rtp_packet_length) { + size_t rtp_packet_length) { RTPHeader header; if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) { WEBRTC_TRACE(kTraceDebug, webrtc::kTraceVoice, _channelId, @@ -790,10 +801,8 @@ Channel::Channel(int32_t channelId, _rxVadObserverPtr(NULL), _oldVadDecision(-1), _sendFrameType(0), - _rtcpObserverPtr(NULL), _externalMixing(false), _mixFileWithMicrophone(false), - _rtcpObserver(false), _mute(false), _panLeft(1.0f), _panRight(1.0f), @@ -815,12 +824,7 @@ Channel::Channel(int32_t channelId, _rxAgcIsEnabled(false), _rxNsIsEnabled(false), restored_packet_in_use_(false), - bitrate_controller_( - BitrateController::CreateBitrateController(Clock::GetRealTimeClock(), - true)), - rtcp_bandwidth_observer_( - bitrate_controller_->CreateRtcpBandwidthObserver()), - send_bitrate_observer_(new VoEBitrateObserver(this)), + rtcp_observer_(new VoERtcpObserver(this)), network_predictor_(new NetworkPredictor(Clock::GetRealTimeClock())) { WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId), @@ -833,10 +837,9 @@ Channel::Channel(int32_t channelId, configuration.id = VoEModuleId(instanceId, channelId); configuration.audio = true; configuration.outgoing_transport = this; - configuration.rtcp_feedback = this; configuration.audio_messages = this; configuration.receive_statistics = rtp_receive_statistics_.get(); - configuration.bandwidth_callback = rtcp_bandwidth_observer_.get(); + configuration.bandwidth_callback = rtcp_observer_.get(); _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration)); @@ -846,6 +849,10 @@ Channel::Channel(int32_t channelId, Config audioproc_config; audioproc_config.Set(new ExperimentalAgc(false)); + audioproc_config.Set( + new ExtendedFilter(config.Get().enabled)); + audioproc_config.Set( + new DelayAgnostic(config.Get().enabled)); rx_audioproc_.reset(AudioProcessing::Create(audioproc_config)); } @@ -910,12 +917,8 @@ Channel::~Channel() " (Audio coding module)"); } // De-register modules in process thread - if (_moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get()) == -1) - { - WEBRTC_TRACE(kTraceInfo, kTraceVoice, - VoEId(_instanceId,_channelId), - "~Channel() failed to deregister RTP/RTCP module"); - } + _moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get()); + // End of modules shutdown // Delete other objects @@ -951,24 +954,16 @@ Channel::Init() // --- Add modules to process thread (for periodic schedulation) - const bool processThreadFail = - ((_moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get()) != 0) || - false); - if (processThreadFail) - { - _engineStatisticsPtr->SetLastError( - VE_CANNOT_INIT_CHANNEL, kTraceError, - "Channel::Init() modules not registered"); - return -1; - } + _moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get()); + // --- ACM initialization - if ((audio_coding_->InitializeReceiver() == -1) || + if ((audio_coding_->InitializeReceiver() == -1) #ifdef WEBRTC_CODEC_AVT // out-of-band Dtmf tones are played out by default - (audio_coding_->SetDtmfPlayoutStatus(true) == -1) || + || (audio_coding_->SetDtmfPlayoutStatus(true) == -1) #endif - (audio_coding_->InitializeSender() == -1)) + ) { _engineStatisticsPtr->SetLastError( VE_AUDIO_CODING_MODULE_ERROR, kTraceError, @@ -985,15 +980,8 @@ Channel::Init() // be transmitted since the Transport object will then be invalid. telephone_event_handler_->SetTelephoneEventForwardToDecoder(true); // RTCP is enabled by default. - if (_rtpRtcpModule->SetRTCPStatus(kRtcpCompound) == -1) - { - _engineStatisticsPtr->SetLastError( - VE_RTP_RTCP_MODULE_ERROR, kTraceError, - "Channel::Init() RTP/RTCP module not initialized"); - return -1; - } - - // --- Register all permanent callbacks + _rtpRtcpModule->SetRTCPStatus(kRtcpCompound); + // --- Register all permanent callbacks const bool fail = (audio_coding_->RegisterTransportCallback(this) == -1) || (audio_coding_->RegisterVADCallback(this) == -1); @@ -1356,28 +1344,16 @@ Channel::SetSendCodec(const CodecInst& codec) return -1; } - bitrate_controller_->SetBitrateObserver(send_bitrate_observer_.get(), - codec.rate, 0, 0); - return 0; } -void -Channel::OnNetworkChanged(const uint32_t bitrate_bps, - const uint8_t fraction_lost, // 0 - 255. - const uint32_t rtt) { - WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), - "Channel::OnNetworkChanged(bitrate_bps=%d, fration_lost=%d, rtt=%d)", - bitrate_bps, fraction_lost, rtt); - // |fraction_lost| from BitrateObserver is short time observation of packet - // loss rate from past. We use network predictor to make a more reasonable - // loss rate estimation. +void Channel::OnIncomingFractionLoss(int fraction_lost) { network_predictor_->UpdatePacketLossRate(fraction_lost); - uint8_t loss_rate = network_predictor_->GetLossRate(); + uint8_t average_fraction_loss = network_predictor_->GetLossRate(); + // Normalizes rate to 0 - 100. - if (audio_coding_->SetPacketLossRate(100 * loss_rate / 255) != 0) { - _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR, - kTraceError, "OnNetworkChanged() failed to set packet loss rate"); + if (audio_coding_->SetPacketLossRate( + 100 * average_fraction_loss / 255) != 0) { assert(false); // This should not happen. } } @@ -1387,6 +1363,7 @@ Channel::SetVADStatus(bool enableVAD, ACMVADMode mode, bool disableDTX) { WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), "Channel::SetVADStatus(mode=%d)", mode); + assert(!(disableDTX && enableVAD)); // disableDTX mode is deprecated. // To disable VAD, DTX must be disabled too disableDTX = ((enableVAD == false) ? true : disableDTX); if (audio_coding_->SetVAD(!disableDTX, enableVAD, mode) != 0) @@ -1527,7 +1504,7 @@ Channel::GetRecPayloadType(CodecInst& codec) } codec.pltype = payloadType; WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId), - "Channel::GetRecPayloadType() => pltype=%u", codec.pltype); + "Channel::GetRecPayloadType() => pltype=%d", codec.pltype); return 0; } @@ -1593,6 +1570,19 @@ int Channel::SetOpusMaxPlaybackRate(int frequency_hz) { return 0; } +int Channel::SetOpusDtx(bool enable_dtx) { + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), + "Channel::SetOpusDtx(%d)", enable_dtx); + int ret = enable_dtx ? audio_coding_->EnableOpusDtx(true) + : audio_coding_->DisableOpusDtx(); + if (ret != 0) { + _engineStatisticsPtr->SetLastError( + VE_AUDIO_CODING_MODULE_ERROR, kTraceError, "SetOpusDtx() failed"); + return -1; + } + return 0; +} + int32_t Channel::RegisterExternalTransport(Transport& transport) { WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), @@ -1635,7 +1625,7 @@ Channel::DeRegisterExternalTransport() return 0; } -int32_t Channel::ReceivedRTPPacket(const int8_t* data, int32_t length, +int32_t Channel::ReceivedRTPPacket(const int8_t* data, size_t length, const PacketTime& packet_time) { WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), "Channel::ReceivedRTPPacket()"); @@ -1676,7 +1666,7 @@ int32_t Channel::ReceivedRTPPacket(const int8_t* data, int32_t length, } else { arrival_time_ms = TickTime::MillisecondTimestamp(); } - int payload_length = length - header.headerLength; + size_t payload_length = length - header.headerLength; vie_network_->ReceivedBWEPacket(video_channel_, arrival_time_ms, payload_length, header); } @@ -1686,15 +1676,15 @@ int32_t Channel::ReceivedRTPPacket(const int8_t* data, int32_t length, } bool Channel::ReceivePacket(const uint8_t* packet, - int packet_length, + size_t packet_length, const RTPHeader& header, bool in_order) { - if (rtp_payload_registry_->IsEncapsulated(header)) { - return HandleEncapsulation(packet, packet_length, header); + if (rtp_payload_registry_->IsRtx(header)) { + return HandleRtxPacket(packet, packet_length, header); } const uint8_t* payload = packet + header.headerLength; - int payload_length = packet_length - header.headerLength; - assert(payload_length >= 0); + assert(packet_length >= header.headerLength); + size_t payload_length = packet_length - header.headerLength; PayloadUnion payload_specific; if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType, &payload_specific)) { @@ -1704,9 +1694,9 @@ bool Channel::ReceivePacket(const uint8_t* packet, payload_specific, in_order); } -bool Channel::HandleEncapsulation(const uint8_t* packet, - int packet_length, - const RTPHeader& header) { +bool Channel::HandleRtxPacket(const uint8_t* packet, + size_t packet_length, + const RTPHeader& header) { if (!rtp_payload_registry_->IsRtx(header)) return false; @@ -1752,29 +1742,27 @@ bool Channel::IsPacketRetransmitted(const RTPHeader& header, if (!statistician) return false; // Check if this is a retransmission. - uint16_t min_rtt = 0; + int64_t min_rtt = 0; _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL); return !in_order && statistician->IsRetransmitOfOldPacket(header, min_rtt); } -int32_t Channel::ReceivedRTCPPacket(const int8_t* data, int32_t length) { +int32_t Channel::ReceivedRTCPPacket(const int8_t* data, size_t length) { WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), "Channel::ReceivedRTCPPacket()"); // Store playout timestamp for the received RTCP packet UpdatePlayoutTimestamp(true); // Dump the RTCP packet to a file (if RTP dump is enabled). - if (_rtpDumpIn.DumpPacket((const uint8_t*)data, - (uint16_t)length) == -1) { + if (_rtpDumpIn.DumpPacket((const uint8_t*)data, length) == -1) { WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId), "Channel::SendPacket() RTCP dump to input file failed"); } // Deliver RTCP packet to RTP/RTCP module for parsing - if (_rtpRtcpModule->IncomingRtcpPacket((const uint8_t*)data, - (uint16_t)length) == -1) { + if (_rtpRtcpModule->IncomingRtcpPacket((const uint8_t*)data, length) == -1) { _engineStatisticsPtr->SetLastError( VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning, "Channel::IncomingRTPPacket() RTCP packet is invalid"); @@ -1782,7 +1770,7 @@ int32_t Channel::ReceivedRTCPPacket(const int8_t* data, int32_t length) { { CriticalSectionScoped lock(ts_stats_lock_.get()); - uint16_t rtt = GetRTT(); + int64_t rtt = GetRTT(); if (rtt == 0) { // Waiting for valid RTT. return 0; @@ -2872,48 +2860,6 @@ Channel::GetRxNsStatus(bool& enabled, NsModes& mode) #endif // #ifdef WEBRTC_VOICE_ENGINE_NR -int -Channel::RegisterRTCPObserver(VoERTCPObserver& observer) -{ - WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), - "Channel::RegisterRTCPObserver()"); - CriticalSectionScoped cs(&_callbackCritSect); - - if (_rtcpObserverPtr) - { - _engineStatisticsPtr->SetLastError( - VE_INVALID_OPERATION, kTraceError, - "RegisterRTCPObserver() observer already enabled"); - return -1; - } - - _rtcpObserverPtr = &observer; - _rtcpObserver = true; - - return 0; -} - -int -Channel::DeRegisterRTCPObserver() -{ - WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), - "Channel::DeRegisterRTCPObserver()"); - CriticalSectionScoped cs(&_callbackCritSect); - - if (!_rtcpObserverPtr) - { - _engineStatisticsPtr->SetLastError( - VE_INVALID_OPERATION, kTraceWarning, - "DeRegisterRTCPObserver() observer already disabled"); - return 0; - } - - _rtcpObserver = false; - _rtcpObserverPtr = NULL; - - return 0; -} - int Channel::SetLocalSSRC(unsigned int ssrc) { @@ -2980,20 +2926,10 @@ int Channel::SetReceiveAbsoluteSenderTimeStatus(bool enable, unsigned char id) { return 0; } -int -Channel::SetRTCPStatus(bool enable) -{ - WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), - "Channel::SetRTCPStatus()"); - if (_rtpRtcpModule->SetRTCPStatus(enable ? - kRtcpCompound : kRtcpOff) != 0) - { - _engineStatisticsPtr->SetLastError( - VE_RTP_RTCP_MODULE_ERROR, kTraceError, - "SetRTCPStatus() failed to set RTCP status"); - return -1; - } - return 0; +void Channel::SetRTCPStatus(bool enable) { + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), + "Channel::SetRTCPStatus()"); + _rtpRtcpModule->SetRTCPStatus(enable ? kRtcpCompound : kRtcpOff); } int @@ -3112,8 +3048,8 @@ Channel::GetRemoteRTCPReceiverInfo( "fractionLost = %lu, cumulativeLost = %lu", jitter, fractionLost, cumulativeLost); - uint16_t dummy; - uint16_t rtt = 0; + int64_t dummy; + int64_t rtt = 0; if (_rtpRtcpModule->RTT(remoteSSRC, &rtt, &dummy, &dummy, &dummy) != 0) { @@ -3289,16 +3225,19 @@ Channel::GetRTPStatistics(CallStatistics& stats) // --- RTT stats.rttMs = GetRTT(); - - WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, - VoEId(_instanceId, _channelId), - "GetRTPStatistics() => rttMs=%d", stats.rttMs); + if (stats.rttMs == 0) { + WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId), + "GetRTPStatistics() failed to get RTT"); + } else { + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId), + "GetRTPStatistics() => rttMs=%" PRId64, stats.rttMs); + } // --- Data counters - uint32_t bytesSent(0); + size_t bytesSent(0); uint32_t packetsSent(0); - uint32_t bytesReceived(0); + size_t bytesReceived(0); uint32_t packetsReceived(0); if (statistician) { @@ -3321,8 +3260,8 @@ Channel::GetRTPStatistics(CallStatistics& stats) WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId), - "GetRTPStatistics() => bytesSent=%d, packetsSent=%d," - " bytesReceived=%d, packetsReceived=%d)", + "GetRTPStatistics() => bytesSent=%" PRIuS ", packetsSent=%d," + " bytesReceived=%" PRIuS ", packetsReceived=%d)", stats.bytesSent, stats.packetsSent, stats.bytesReceived, stats.packetsReceived); @@ -3378,6 +3317,7 @@ Channel::GetREDStatus(bool& enabled, int& redPayloadtype) "module"); return -1; } + redPayloadtype = payloadType; WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId), "GetREDStatus() => enabled=%d, redPayloadtype=%d", @@ -3623,7 +3563,10 @@ Channel::EncodeAndSend() // The ACM resamples internally. _audioFrame.timestamp_ = _timeStamp; - if (audio_coding_->Add10MsData((AudioFrame&)_audioFrame) != 0) + // This call will trigger AudioPacketizationCallback::SendData if encoding + // is done and payload is ready for packetization and transmission. + // Otherwise, it will return without invoking the callback. + if (audio_coding_->Add10MsData((AudioFrame&)_audioFrame) < 0) { WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), "Channel::EncodeAndSend() ACM encoding failed"); @@ -3631,12 +3574,7 @@ Channel::EncodeAndSend() } _timeStamp += _audioFrame.samples_per_channel_; - - // --- Encode if complete frame is ready - - // This call will trigger AudioPacketizationCallback::SendData if encoding - // is done and payload is ready for packetization and transmission. - return audio_coding_->Process(); + return 0; } int Channel::RegisterExternalMediaProcessing( @@ -3737,12 +3675,7 @@ Channel::GetNetworkStatistics(NetworkStatistics& stats) { WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), "Channel::GetNetworkStatistics()"); - ACMNetworkStatistics acm_stats; - int return_value = audio_coding_->NetworkStatistics(&acm_stats); - if (return_value >= 0) { - memcpy(&stats, &acm_stats, sizeof(NetworkStatistics)); - } - return return_value; + return audio_coding_->GetNetworkStatistics(&stats); } void Channel::GetDecodingCallStatistics(AudioDecodingCallStats* stats) const { @@ -3865,47 +3798,28 @@ int Channel::GetPlayoutTimestamp(unsigned int& timestamp) { return 0; } -int -Channel::SetInitTimestamp(unsigned int timestamp) -{ - WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), +int Channel::SetInitTimestamp(unsigned int timestamp) { + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), "Channel::SetInitTimestamp()"); - if (channel_state_.Get().sending) - { - _engineStatisticsPtr->SetLastError( - VE_SENDING, kTraceError, "SetInitTimestamp() already sending"); - return -1; - } - if (_rtpRtcpModule->SetStartTimestamp(timestamp) != 0) - { - _engineStatisticsPtr->SetLastError( - VE_RTP_RTCP_MODULE_ERROR, kTraceError, - "SetInitTimestamp() failed to set timestamp"); - return -1; - } - return 0; + if (channel_state_.Get().sending) { + _engineStatisticsPtr->SetLastError(VE_SENDING, kTraceError, + "SetInitTimestamp() already sending"); + return -1; + } + _rtpRtcpModule->SetStartTimestamp(timestamp); + return 0; } -int -Channel::SetInitSequenceNumber(short sequenceNumber) -{ - WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), - "Channel::SetInitSequenceNumber()"); - if (channel_state_.Get().sending) - { - _engineStatisticsPtr->SetLastError( - VE_SENDING, kTraceError, - "SetInitSequenceNumber() already sending"); - return -1; - } - if (_rtpRtcpModule->SetSequenceNumber(sequenceNumber) != 0) - { - _engineStatisticsPtr->SetLastError( - VE_RTP_RTCP_MODULE_ERROR, kTraceError, - "SetInitSequenceNumber() failed to set sequence number"); - return -1; - } - return 0; +int Channel::SetInitSequenceNumber(short sequenceNumber) { + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), + "Channel::SetInitSequenceNumber()"); + if (channel_state_.Get().sending) { + _engineStatisticsPtr->SetLastError( + VE_SENDING, kTraceError, "SetInitSequenceNumber() already sending"); + return -1; + } + _rtpRtcpModule->SetSequenceNumber(sequenceNumber); + return 0; } int @@ -3923,7 +3837,7 @@ Channel::GetRtpRtcp(RtpRtcp** rtpRtcpModule, RtpReceiver** rtp_receiver) const int32_t Channel::MixOrReplaceAudioWithFile(int mixingFrequency) { - scoped_ptr fileBuffer(new int16_t[640]); + rtc::scoped_ptr fileBuffer(new int16_t[640]); int fileSamples(0); { @@ -3993,7 +3907,7 @@ Channel::MixAudioWithFile(AudioFrame& audioFrame, { assert(mixingFrequency <= 48000); - scoped_ptr fileBuffer(new int16_t[960]); + rtc::scoped_ptr fileBuffer(new int16_t[960]); int fileSamples(0); { @@ -4116,7 +4030,7 @@ Channel::InsertInbandDtmfTone() } int32_t -Channel::SendPacketRaw(const void *data, int len, bool RTCP) +Channel::SendPacketRaw(const void *data, size_t len, bool RTCP) { CriticalSectionScoped cs(&_callbackCritSect); if (_transportPtr == NULL) @@ -4228,47 +4142,6 @@ Channel::RegisterReceiveCodecsToRTPModule() } } -int Channel::SetSecondarySendCodec(const CodecInst& codec, - int red_payload_type) { - // Sanity check for payload type. - if (red_payload_type < 0 || red_payload_type > 127) { - _engineStatisticsPtr->SetLastError( - VE_PLTYPE_ERROR, kTraceError, - "SetRedPayloadType() invalid RED payload type"); - return -1; - } - - if (SetRedPayloadType(red_payload_type) < 0) { - _engineStatisticsPtr->SetLastError( - VE_AUDIO_CODING_MODULE_ERROR, kTraceError, - "SetSecondarySendCodec() Failed to register RED ACM"); - return -1; - } - if (audio_coding_->RegisterSecondarySendCodec(codec) < 0) { - _engineStatisticsPtr->SetLastError( - VE_AUDIO_CODING_MODULE_ERROR, kTraceError, - "SetSecondarySendCodec() Failed to register secondary send codec in " - "ACM"); - return -1; - } - - return 0; -} - -void Channel::RemoveSecondarySendCodec() { - audio_coding_->UnregisterSecondarySendCodec(); -} - -int Channel::GetSecondarySendCodec(CodecInst* codec) { - if (audio_coding_->SecondarySendCodec(codec) < 0) { - _engineStatisticsPtr->SetLastError( - VE_AUDIO_CODING_MODULE_ERROR, kTraceError, - "GetSecondarySendCodec() Failed to get secondary sent codec from ACM"); - return -1; - } - return 0; -} - // Assuming this method is called with valid payload type. int Channel::SetRedPayloadType(int red_payload_type) { CodecInst codec; @@ -4339,22 +4212,14 @@ int32_t Channel::GetPlayoutFrequency() { return playout_frequency; } -int Channel::GetRTT() const { +int64_t Channel::GetRTT() const { RTCPMethod method = _rtpRtcpModule->RTCP(); if (method == kRtcpOff) { - WEBRTC_TRACE(kTraceWarning, kTraceVoice, - VoEId(_instanceId, _channelId), - "GetRTPStatistics() RTCP is disabled => valid RTT " - "measurements cannot be retrieved"); return 0; } std::vector report_blocks; _rtpRtcpModule->RemoteRTCPStat(&report_blocks); if (report_blocks.empty()) { - WEBRTC_TRACE(kTraceWarning, kTraceVoice, - VoEId(_instanceId, _channelId), - "GetRTPStatistics() failed to measure RTT since no " - "RTCP packets have been received yet"); return 0; } @@ -4371,19 +4236,15 @@ int Channel::GetRTT() const { // the SSRC of the other end. remoteSSRC = report_blocks[0].remoteSSRC; } - uint16_t rtt = 0; - uint16_t avg_rtt = 0; - uint16_t max_rtt= 0; - uint16_t min_rtt = 0; + int64_t rtt = 0; + int64_t avg_rtt = 0; + int64_t max_rtt= 0; + int64_t min_rtt = 0; if (_rtpRtcpModule->RTT(remoteSSRC, &rtt, &avg_rtt, &min_rtt, &max_rtt) != 0) { - WEBRTC_TRACE(kTraceWarning, kTraceVoice, - VoEId(_instanceId, _channelId), - "GetRTPStatistics() failed to retrieve RTT from " - "the RTP/RTCP module"); return 0; } - return static_cast(rtt); + return rtt; } } // namespace voe diff --git a/media/webrtc/trunk/webrtc/voice_engine/channel.h b/media/webrtc/trunk/webrtc/voice_engine/channel.h index e44b4420e3..5e8c50e27a 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/channel.h +++ b/media/webrtc/trunk/webrtc/voice_engine/channel.h @@ -11,6 +11,7 @@ #ifndef WEBRTC_VOICE_ENGINE_CHANNEL_H_ #define WEBRTC_VOICE_ENGINE_CHANNEL_H_ +#include "webrtc/base/scoped_ptr.h" #include "webrtc/common_audio/resampler/include/push_resampler.h" #include "webrtc/common_types.h" #include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h" @@ -22,7 +23,6 @@ #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" #include "webrtc/modules/utility/interface/file_player.h" #include "webrtc/modules/utility/interface/file_recorder.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/voice_engine/dtmf_inband.h" #include "webrtc/voice_engine/dtmf_inband_queue.h" #include "webrtc/voice_engine/include/voe_audio_processing.h" @@ -59,7 +59,6 @@ class RtpRtcp; class TelephoneEventHandler; class ViENetwork; class VoEMediaProcess; -class VoERTCPObserver; class VoERTPObserver; class VoiceEngineObserver; @@ -69,10 +68,11 @@ struct SenderInfo; namespace voe { +class OutputMixer; class Statistics; class StatisticsProxy; class TransmitMixer; -class OutputMixer; +class VoERtcpObserver; // Helper class to simplify locking scheme for members that are accessed from // multiple threads. @@ -149,14 +149,13 @@ class ChannelState { } private: - scoped_ptr lock_; + rtc::scoped_ptr lock_; State state_; }; class Channel: public RtpData, public RtpFeedback, - public RtcpFeedback, public FileCallback, // receiving notification from file player & recorder public Transport, public RtpAudioFeedback, @@ -165,6 +164,8 @@ class Channel: public MixerParticipant // supplies output mixer with audio frames { public: + friend class VoERtcpObserver; + enum {KNumSocketThreads = 1}; enum {KNumberOfSocketBuffers = 8}; virtual ~Channel(); @@ -207,18 +208,14 @@ public: int32_t GetRecPayloadType(CodecInst& codec); int32_t SetSendCNPayloadType(int type, PayloadFrequencies frequency); int SetOpusMaxPlaybackRate(int frequency_hz); - - // VoE dual-streaming. - int SetSecondarySendCodec(const CodecInst& codec, int red_payload_type); - void RemoveSecondarySendCodec(); - int GetSecondarySendCodec(CodecInst* codec); + int SetOpusDtx(bool enable_dtx); // VoENetwork int32_t RegisterExternalTransport(Transport& transport); int32_t DeRegisterExternalTransport(); - int32_t ReceivedRTPPacket(const int8_t* data, int32_t length, + int32_t ReceivedRTPPacket(const int8_t* data, size_t length, const PacketTime& packet_time); - int32_t ReceivedRTCPPacket(const int8_t* data, int32_t length); + int32_t ReceivedRTCPPacket(const int8_t* data, size_t length); // VoEFile int StartPlayingFileLocally(const char* fileName, bool loop, @@ -316,8 +313,6 @@ public: #endif // VoERTP_RTCP - int RegisterRTCPObserver(VoERTCPObserver& observer); - int DeRegisterRTCPObserver(); int SetLocalSSRC(unsigned int ssrc); int GetLocalSSRC(unsigned int& ssrc); int GetRemoteSSRC(unsigned int& ssrc); @@ -325,7 +320,7 @@ public: int SetReceiveAudioLevelIndicationStatus(bool enable, unsigned char id); int SetSendAbsoluteSenderTimeStatus(bool enable, unsigned char id); int SetReceiveAbsoluteSenderTimeStatus(bool enable, unsigned char id); - int SetRTCPStatus(bool enable); + void SetRTCPStatus(bool enable); int GetRTCPStatus(bool& enabled); int SetRTCP_CNAME(const char cName[256]); int GetRemoteRTCP_CNAME(char cName[256]); @@ -357,69 +352,55 @@ public: void SetVideoEngineBWETarget(ViENetwork* vie_network, int video_channel); // From AudioPacketizationCallback in the ACM - virtual int32_t SendData( - FrameType frameType, - uint8_t payloadType, - uint32_t timeStamp, - const uint8_t* payloadData, - uint16_t payloadSize, - const RTPFragmentationHeader* fragmentation) OVERRIDE; + int32_t SendData(FrameType frameType, + uint8_t payloadType, + uint32_t timeStamp, + const uint8_t* payloadData, + size_t payloadSize, + const RTPFragmentationHeader* fragmentation) override; // From ACMVADCallback in the ACM - virtual int32_t InFrameType(int16_t frameType) OVERRIDE; + int32_t InFrameType(FrameType frame_type) override; int32_t OnRxVadDetected(int vadDecision); // From RtpData in the RTP/RTCP module - virtual int32_t OnReceivedPayloadData( - const uint8_t* payloadData, - uint16_t payloadSize, - const WebRtcRTPHeader* rtpHeader) OVERRIDE; - virtual bool OnRecoveredPacket(const uint8_t* packet, - int packet_length) OVERRIDE; + int32_t OnReceivedPayloadData(const uint8_t* payloadData, + size_t payloadSize, + const WebRtcRTPHeader* rtpHeader) override; + bool OnRecoveredPacket(const uint8_t* packet, + size_t packet_length) override; // From RtpFeedback in the RTP/RTCP module - virtual int32_t OnInitializeDecoder( - int32_t id, - int8_t payloadType, - const char payloadName[RTP_PAYLOAD_NAME_SIZE], - int frequency, - uint8_t channels, - uint32_t rate) OVERRIDE; - virtual void OnIncomingSSRCChanged(int32_t id, - uint32_t ssrc) OVERRIDE; - virtual void OnIncomingCSRCChanged(int32_t id, - uint32_t CSRC, bool added) OVERRIDE; - virtual void ResetStatistics(uint32_t ssrc) OVERRIDE; - - // From RtcpFeedback in the RTP/RTCP module - virtual void OnApplicationDataReceived(int32_t id, - uint8_t subType, - uint32_t name, - uint16_t length, - const uint8_t* data) OVERRIDE; + int32_t OnInitializeDecoder(int32_t id, + int8_t payloadType, + const char payloadName[RTP_PAYLOAD_NAME_SIZE], + int frequency, + uint8_t channels, + uint32_t rate) override; + void OnIncomingSSRCChanged(int32_t id, uint32_t ssrc) override; + void OnIncomingCSRCChanged(int32_t id, uint32_t CSRC, bool added) override; + void ResetStatistics(uint32_t ssrc) override; // From RtpAudioFeedback in the RTP/RTCP module - virtual void OnPlayTelephoneEvent(int32_t id, - uint8_t event, - uint16_t lengthMs, - uint8_t volume) OVERRIDE; + void OnPlayTelephoneEvent(int32_t id, + uint8_t event, + uint16_t lengthMs, + uint8_t volume) override; // From Transport (called by the RTP/RTCP module) - virtual int SendPacket(int /*channel*/, const void *data, int len) OVERRIDE; - virtual int SendRTCPPacket(int /*channel*/, - const void *data, - int len) OVERRIDE; + int SendPacket(int /*channel*/, const void* data, size_t len) override; + int SendRTCPPacket(int /*channel*/, const void* data, size_t len) override; // From MixerParticipant - virtual int32_t GetAudioFrame(int32_t id, AudioFrame& audioFrame) OVERRIDE; - virtual int32_t NeededFrequency(int32_t id) OVERRIDE; + int32_t GetAudioFrame(int32_t id, AudioFrame& audioFrame) override; + int32_t NeededFrequency(int32_t id) override; // From FileCallback - virtual void PlayNotification(int32_t id, uint32_t durationMs) OVERRIDE; - virtual void RecordNotification(int32_t id, uint32_t durationMs) OVERRIDE; - virtual void PlayFileEnded(int32_t id) OVERRIDE; - virtual void RecordFileEnded(int32_t id) OVERRIDE; + void PlayNotification(int32_t id, uint32_t durationMs) override; + void RecordNotification(int32_t id, uint32_t durationMs) override; + void PlayFileEnded(int32_t id) override; + void RecordFileEnded(int32_t id) override; uint32_t InstanceId() const { @@ -469,24 +450,22 @@ public: uint32_t PrepareEncodeAndSend(int mixingFrequency); uint32_t EncodeAndSend(); - // From BitrateObserver (called by the RTP/RTCP module). - void OnNetworkChanged(const uint32_t bitrate_bps, - const uint8_t fraction_lost, // 0 - 255. - const uint32_t rtt); +protected: + void OnIncomingFractionLoss(int fraction_lost); private: - bool ReceivePacket(const uint8_t* packet, int packet_length, + bool ReceivePacket(const uint8_t* packet, size_t packet_length, const RTPHeader& header, bool in_order); - bool HandleEncapsulation(const uint8_t* packet, - int packet_length, - const RTPHeader& header); + bool HandleRtxPacket(const uint8_t* packet, + size_t packet_length, + const RTPHeader& header); bool IsPacketInOrder(const RTPHeader& header) const; bool IsPacketRetransmitted(const RTPHeader& header, bool in_order) const; int ResendPackets(const uint16_t* sequence_numbers, int length); int InsertInbandDtmfTone(); int32_t MixOrReplaceAudioWithFile(int mixingFrequency); int32_t MixAudioWithFile(AudioFrame& audioFrame, int mixingFrequency); - int32_t SendPacketRaw(const void *data, int len, bool RTCP); + int32_t SendPacketRaw(const void *data, size_t len, bool RTCP); void UpdatePacketDelay(uint32_t timestamp, uint16_t sequenceNumber); void RegisterReceiveCodecsToRTPModule(); @@ -496,7 +475,7 @@ private: unsigned char id); int32_t GetPlayoutFrequency(); - int GetRTT() const; + int64_t GetRTT() const; CriticalSectionWrapper& _fileCritSect; CriticalSectionWrapper& _callbackCritSect; @@ -506,20 +485,20 @@ private: ChannelState channel_state_; - scoped_ptr rtp_header_parser_; - scoped_ptr rtp_payload_registry_; - scoped_ptr rtp_receive_statistics_; - scoped_ptr statistics_proxy_; - scoped_ptr rtp_receiver_; + rtc::scoped_ptr rtp_header_parser_; + rtc::scoped_ptr rtp_payload_registry_; + rtc::scoped_ptr rtp_receive_statistics_; + rtc::scoped_ptr statistics_proxy_; + rtc::scoped_ptr rtp_receiver_; TelephoneEventHandler* telephone_event_handler_; - scoped_ptr _rtpRtcpModule; - scoped_ptr audio_coding_; + rtc::scoped_ptr _rtpRtcpModule; + rtc::scoped_ptr audio_coding_; RtpDump& _rtpDumpIn; RtpDump& _rtpDumpOut; AudioLevel _outputAudioLevel; bool _externalTransport; AudioFrame _audioFrame; - scoped_ptr mono_recording_audio_; + rtc::scoped_ptr mono_recording_audio_; // Downsamples to the codec rate if necessary. PushResampler input_resampler_; FilePlayer* _inputFilePlayerPtr; @@ -548,9 +527,9 @@ private: uint16_t send_sequence_number_; uint8_t restored_packet_[kVoiceEngineMaxIpPacketSizeBytes]; - scoped_ptr ts_stats_lock_; + rtc::scoped_ptr ts_stats_lock_; - scoped_ptr rtp_ts_wraparound_handler_; + rtc::scoped_ptr rtp_ts_wraparound_handler_; // The rtp timestamp of the first played out audio frame. int64_t capture_start_rtp_time_stamp_; // The capture ntp time (in local timebase) of the first played out audio @@ -567,15 +546,13 @@ private: CriticalSectionWrapper* _callbackCritSectPtr; // owned by base Transport* _transportPtr; // WebRtc socket or external transport RMSLevel rms_level_; - scoped_ptr rx_audioproc_; // far end AudioProcessing + rtc::scoped_ptr rx_audioproc_; // far end AudioProcessing VoERxVadCallback* _rxVadObserverPtr; int32_t _oldVadDecision; int32_t _sendFrameType; // Send data is voice, 1-voice, 0-otherwise - VoERTCPObserver* _rtcpObserverPtr; // VoEBase bool _externalMixing; bool _mixFileWithMicrophone; - bool _rtcpObserver; // VoEVolumeControl bool _mute; float _panLeft; @@ -604,10 +581,8 @@ private: bool _rxNsIsEnabled; bool restored_packet_in_use_; // RtcpBandwidthObserver - scoped_ptr bitrate_controller_; - scoped_ptr rtcp_bandwidth_observer_; - scoped_ptr send_bitrate_observer_; - scoped_ptr network_predictor_; + rtc::scoped_ptr rtcp_observer_; + rtc::scoped_ptr network_predictor_; }; } // namespace voe diff --git a/media/webrtc/trunk/webrtc/voice_engine/channel_manager.cc b/media/webrtc/trunk/webrtc/voice_engine/channel_manager.cc index 9386257476..78c484f3dc 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/channel_manager.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/channel_manager.cc @@ -46,10 +46,11 @@ ChannelOwner::ChannelRef::ChannelRef(class Channel* channel) : channel(channel), ref_count(1) {} ChannelManager::ChannelManager(uint32_t instance_id, const Config& config) - : instance_id_(instance_id), + : config_(config), + instance_id_(instance_id), last_channel_id_(-1), - lock_(CriticalSectionWrapper::CreateCriticalSection()), - config_(config) {} + lock_(CriticalSectionWrapper::CreateCriticalSection()) + {} ChannelOwner ChannelManager::CreateChannel() { return CreateChannelInternal(config_); diff --git a/media/webrtc/trunk/webrtc/voice_engine/channel_manager.h b/media/webrtc/trunk/webrtc/voice_engine/channel_manager.h index 3c0f68147e..27e2865baf 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/channel_manager.h +++ b/media/webrtc/trunk/webrtc/voice_engine/channel_manager.h @@ -14,9 +14,9 @@ #include #include "webrtc/base/constructormagic.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/system_wrappers/interface/atomic32.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -60,7 +60,7 @@ class ChannelOwner { // deleted when no references to them are held. struct ChannelRef { ChannelRef(Channel* channel); - const scoped_ptr channel; + const rtc::scoped_ptr channel; Atomic32 ref_count; }; @@ -109,6 +109,7 @@ class ChannelManager { void DestroyAllChannels(); size_t NumOfChannels() const; + const Config& config_; private: // Create a channel given a configuration, |config|. @@ -118,11 +119,9 @@ class ChannelManager { Atomic32 last_channel_id_; - scoped_ptr lock_; + rtc::scoped_ptr lock_; std::vector channels_; - const Config& config_; - DISALLOW_COPY_AND_ASSIGN(ChannelManager); }; } // namespace voe diff --git a/media/webrtc/trunk/webrtc/voice_engine/include/mock/fake_voe_external_media.h b/media/webrtc/trunk/webrtc/voice_engine/include/mock/fake_voe_external_media.h index b7946eeec9..40f88b0076 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/include/mock/fake_voe_external_media.h +++ b/media/webrtc/trunk/webrtc/voice_engine/include/mock/fake_voe_external_media.h @@ -13,7 +13,7 @@ #include -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/test/fake_common.h" #include "webrtc/voice_engine/include/voe_external_media.h" @@ -56,7 +56,7 @@ class FakeVoEExternalMedia : public VoEExternalMedia { int samples_per_channel, int sample_rate_hz, int num_channels) { const int length = samples_per_channel * num_channels; - scoped_ptr data; + rtc::scoped_ptr data; if (!audio) { data.reset(new int16_t[length]); memset(data.get(), 0, length * sizeof(data[0])); diff --git a/media/webrtc/trunk/webrtc/voice_engine/include/voe_audio_processing.h b/media/webrtc/trunk/webrtc/voice_engine/include/voe_audio_processing.h index 8b40360ae6..162848c282 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/include/voe_audio_processing.h +++ b/media/webrtc/trunk/webrtc/voice_engine/include/voe_audio_processing.h @@ -185,9 +185,11 @@ public: virtual int GetEchoMetrics(int& ERL, int& ERLE, int& RERL, int& A_NLP) = 0; // Gets the EC internal |delay_median| and |delay_std| in ms between - // near-end and far-end. The values are calculated over the time period - // since the last GetEcDelayMetrics() call. - virtual int GetEcDelayMetrics(int& delay_median, int& delay_std) = 0; + // near-end and far-end. The metric |fraction_poor_delays| is the amount of + // delay values that potentially can break the EC. The values are aggregated + // over one second and the last updated metrics are returned. + virtual int GetEcDelayMetrics(int& delay_median, int& delay_std, + float& fraction_poor_delays) = 0; // Enables recording of Audio Processing (AP) debugging information. // The file can later be used for off-line analysis of the AP performance. diff --git a/media/webrtc/trunk/webrtc/voice_engine/include/voe_base.h b/media/webrtc/trunk/webrtc/voice_engine/include/voe_base.h index fa169ead4e..b99f36aa81 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/include/voe_base.h +++ b/media/webrtc/trunk/webrtc/voice_engine/include/voe_base.h @@ -87,7 +87,6 @@ public: #if !defined(WEBRTC_CHROMIUM_BUILD) static int SetAndroidObjects(void* javaVM, void* context); - static int SetAndroidObjects(void* javaVM, void* env, void* context); #endif protected: diff --git a/media/webrtc/trunk/webrtc/voice_engine/include/voe_codec.h b/media/webrtc/trunk/webrtc/voice_engine/include/voe_codec.h index 234596a216..4b9f939ce1 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/include/voe_codec.h +++ b/media/webrtc/trunk/webrtc/voice_engine/include/voe_codec.h @@ -64,23 +64,6 @@ public: // |channel|. virtual int GetSendCodec(int channel, CodecInst& codec) = 0; - // Sets the |codec| as secondary codec for |channel|. Registering a - // secondary send codec enables dual-streaming. In dual-streaming mode, - // payloads of the primary and the secondary codecs are packed in RED - // payloads with |red_payload_type| as payload type. The Secondary codec - // MUST have the same sampling rate as the primary codec, otherwise the - // codec cannot be registered and -1 is returned. This method fails if a - // primary codec is not yet set. - virtual int SetSecondarySendCodec(int channel, const CodecInst& codec, - int red_payload_type) = 0; - - // Removes the secondary codec from |channel|. This will terminate - // dual-streaming. - virtual int RemoveSecondarySendCodec(int channel) = 0; - - // Gets |codec| which is used as secondary codec in |channel|. - virtual int GetSecondarySendCodec(int channel, CodecInst& codec) = 0; - // Gets the currently received |codec| for a specific |channel|. virtual int GetRecCodec(int channel, CodecInst& codec) = 0; @@ -134,6 +117,10 @@ public: return -1; } + // If send codec is Opus on a specified |channel|, set its DTX. Returns 0 if + // success, and -1 if failed. + virtual int SetOpusDtx(int channel, bool enable_dtx) = 0; + // Don't use. To be removed. virtual int SetAMREncFormat(int channel, AmrMode mode) { return -1; } virtual int SetAMRDecFormat(int channel, AmrMode mode) { return -1; } diff --git a/media/webrtc/trunk/webrtc/voice_engine/include/voe_hardware.h b/media/webrtc/trunk/webrtc/voice_engine/include/voe_hardware.h index 043efb28af..d69fa89973 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/include/voe_hardware.h +++ b/media/webrtc/trunk/webrtc/voice_engine/include/voe_hardware.h @@ -69,7 +69,7 @@ public: // (GUID) for the playout device. virtual int GetPlayoutDeviceName(int index, char strNameUTF8[128], char strGuidUTF8[128]) = 0; - + // Checks if the sound card is available to be opened for recording. virtual int GetRecordingDeviceStatus(bool& isAvailable) = 0; @@ -88,7 +88,7 @@ public: // Gets the currently used (active) audio device layer. virtual int GetAudioDeviceLayer(AudioLayers& audioLayer) = 0; - + // Gets the VoiceEngine's current CPU consumption in terms of the percent // of total CPU availability. [Windows only] virtual int GetCPULoad(int& loadPercent) = 0; @@ -112,6 +112,8 @@ public: virtual int SetPlayoutSampleRate(unsigned int samples_per_sec) = 0; virtual int PlayoutSampleRate(unsigned int* samples_per_sec) const = 0; + virtual bool BuiltInAECIsAvailable() const = 0; + // *Experimental - not recommended for use.* // Enables the Windows Core Audio built-in AEC. Fails on other platforms. // @@ -131,7 +133,6 @@ public: virtual int EnableBuiltInAEC(bool enable) = 0; virtual bool BuiltInAECIsEnabled() const = 0; - protected: VoEHardware() {} virtual ~VoEHardware() {} diff --git a/media/webrtc/trunk/webrtc/voice_engine/include/voe_network.h b/media/webrtc/trunk/webrtc/voice_engine/include/voe_network.h index 67429755a7..ff8b8e1f94 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/include/voe_network.h +++ b/media/webrtc/trunk/webrtc/voice_engine/include/voe_network.h @@ -69,10 +69,10 @@ public: // including the RTP-header must also be given to the VoiceEngine. virtual int ReceivedRTPPacket(int channel, const void* data, - unsigned int length) = 0; + size_t length) = 0; virtual int ReceivedRTPPacket(int channel, const void* data, - unsigned int length, + size_t length, const PacketTime& packet_time) { return 0; } @@ -80,8 +80,9 @@ public: // The packets received from the network should be passed to this // function when external transport is enabled. Note that the data // including the RTCP-header must also be given to the VoiceEngine. - virtual int ReceivedRTCPPacket( - int channel, const void* data, unsigned int length) = 0; + virtual int ReceivedRTCPPacket(int channel, + const void* data, + size_t length) = 0; protected: VoENetwork() {} diff --git a/media/webrtc/trunk/webrtc/voice_engine/include/voe_rtp_rtcp.h b/media/webrtc/trunk/webrtc/voice_engine/include/voe_rtp_rtcp.h index 93e6cd4dff..ee0fae0014 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/include/voe_rtp_rtcp.h +++ b/media/webrtc/trunk/webrtc/voice_engine/include/voe_rtp_rtcp.h @@ -61,19 +61,6 @@ protected: virtual ~VoERTPObserver() {} }; -// VoERTCPObserver -class WEBRTC_DLLEXPORT VoERTCPObserver -{ -public: - virtual void OnApplicationDataReceived( - int channel, unsigned char subType, - unsigned int name, const unsigned char* data, - unsigned short dataLengthInBytes) = 0; - -protected: - virtual ~VoERTCPObserver() {} -}; - // CallStatistics struct CallStatistics { @@ -81,10 +68,10 @@ struct CallStatistics unsigned int cumulativeLost; unsigned int extendedMax; unsigned int jitterSamples; - int rttMs; - int bytesSent; + int64_t rttMs; + size_t bytesSent; int packetsSent; - int bytesReceived; + size_t bytesReceived; int packetsReceived; // The capture ntp time (in local timebase) of the first played out audio // frame. @@ -270,9 +257,6 @@ public: virtual int RegisterRTPObserver(int channel, VoERTPObserver& observer) { return -1; }; virtual int DeRegisterRTPObserver(int channel) { return -1; }; - virtual int RegisterRTCPObserver( - int channel, VoERTCPObserver& observer) { return -1; }; - virtual int DeRegisterRTCPObserver(int channel) { return -1; }; virtual int GetRemoteCSRCs(int channel, unsigned int arrCSRC[15]) { return -1; }; virtual int InsertExtraRTPPacket( diff --git a/media/webrtc/trunk/webrtc/voice_engine/monitor_module.cc b/media/webrtc/trunk/webrtc/voice_engine/monitor_module.cc index 88de5c880d..ca358022a5 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/monitor_module.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/monitor_module.cc @@ -28,7 +28,7 @@ MonitorModule::~MonitorModule() delete &_callbackCritSect; } -int32_t +int32_t MonitorModule::RegisterObserver(MonitorObserver& observer) { CriticalSectionScoped lock(&_callbackCritSect); @@ -40,7 +40,7 @@ MonitorModule::RegisterObserver(MonitorObserver& observer) return 0; } -int32_t +int32_t MonitorModule::DeRegisterObserver() { CriticalSectionScoped lock(&_callbackCritSect); @@ -52,22 +52,15 @@ MonitorModule::DeRegisterObserver() return 0; } -int32_t -MonitorModule::ChangeUniqueId(int32_t id) -{ - return 0; -} - -int32_t +int64_t MonitorModule::TimeUntilNextProcess() { - uint32_t now = TickTime::MillisecondTimestamp(); - int32_t timeToNext = - kAverageProcessUpdateTimeMs - (now - _lastProcessTime); - return (timeToNext); + int64_t now = TickTime::MillisecondTimestamp(); + const int64_t kAverageProcessUpdateTimeMs = 1000; + return kAverageProcessUpdateTimeMs - (now - _lastProcessTime); } -int32_t +int32_t MonitorModule::Process() { _lastProcessTime = TickTime::MillisecondTimestamp(); diff --git a/media/webrtc/trunk/webrtc/voice_engine/monitor_module.h b/media/webrtc/trunk/webrtc/voice_engine/monitor_module.h index 693b2e00a9..42ea74d7e2 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/monitor_module.h +++ b/media/webrtc/trunk/webrtc/voice_engine/monitor_module.h @@ -40,16 +40,14 @@ public: virtual ~MonitorModule(); public: // module - virtual int32_t ChangeUniqueId(int32_t id) OVERRIDE; + int64_t TimeUntilNextProcess() override; - virtual int32_t TimeUntilNextProcess() OVERRIDE; + int32_t Process() override; - virtual int32_t Process() OVERRIDE; private: - enum { kAverageProcessUpdateTimeMs = 1000 }; MonitorObserver* _observerPtr; CriticalSectionWrapper& _callbackCritSect; - int32_t _lastProcessTime; + int64_t _lastProcessTime; }; } // namespace voe diff --git a/media/webrtc/trunk/webrtc/voice_engine/network_predictor.cc b/media/webrtc/trunk/webrtc/voice_engine/network_predictor.cc index 4093877343..f8fa2e315c 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/network_predictor.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/network_predictor.cc @@ -19,6 +19,12 @@ NetworkPredictor::NetworkPredictor(Clock* clock) loss_rate_filter_(new rtc::ExpFilter(0.9999f)) { } +uint8_t NetworkPredictor::GetLossRate() { + float value = loss_rate_filter_->filtered(); + return (value == rtc::ExpFilter::kValueUndefined) ? 0 : + static_cast(value + 0.5); +} + void NetworkPredictor::UpdatePacketLossRate(uint8_t loss_rate) { int64_t now_ms = clock_->TimeInMilliseconds(); // Update the recursive average filter. @@ -28,10 +34,5 @@ void NetworkPredictor::UpdatePacketLossRate(uint8_t loss_rate) { last_loss_rate_update_time_ms_ = now_ms; } -uint8_t NetworkPredictor::GetLossRate() { - float value = loss_rate_filter_->filtered(); - return (value == rtc::ExpFilter::kValueUndefined) ? 0 : - static_cast(value + 0.5); -} } // namespace voe } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/voice_engine/network_predictor.h b/media/webrtc/trunk/webrtc/voice_engine/network_predictor.h index d9f0b7b144..0e5068659c 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/network_predictor.h +++ b/media/webrtc/trunk/webrtc/voice_engine/network_predictor.h @@ -38,7 +38,7 @@ class NetworkPredictor { int64_t last_loss_rate_update_time_ms_; // An exponential filter is used to predict packet loss rate. - scoped_ptr loss_rate_filter_; + rtc::scoped_ptr loss_rate_filter_; }; } // namespace voe diff --git a/media/webrtc/trunk/webrtc/voice_engine/network_predictor_unittest.cc b/media/webrtc/trunk/webrtc/voice_engine/network_predictor_unittest.cc index e399f6820f..55ee20da03 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/network_predictor_unittest.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/network_predictor_unittest.cc @@ -23,7 +23,7 @@ class TestNetworkPredictor : public ::testing::Test { : clock_(0), network_predictor_(new NetworkPredictor(&clock_)) {} SimulatedClock clock_; - scoped_ptr network_predictor_; + rtc::scoped_ptr network_predictor_; }; TEST_F(TestNetworkPredictor, TestPacketLossRateFilter) { diff --git a/media/webrtc/trunk/webrtc/voice_engine/shared_data.cc b/media/webrtc/trunk/webrtc/voice_engine/shared_data.cc index 218784474e..ad00e038f6 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/shared_data.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/shared_data.cc @@ -29,7 +29,7 @@ SharedData::SharedData(const Config& config) : _channelManager(_gInstanceCounter, config), _engineStatistics(_gInstanceCounter), _audioDevicePtr(NULL), - _moduleProcessThreadPtr(ProcessThread::CreateProcessThread()), + _moduleProcessThreadPtr(ProcessThread::Create()), _externalRecording(false), _externalPlayout(false) { @@ -55,7 +55,7 @@ SharedData::~SharedData() _audioDevicePtr->Release(); } delete _apiCritPtr; - ProcessThread::DestroyProcessThread(_moduleProcessThreadPtr); + _moduleProcessThreadPtr->Stop(); Trace::ReturnTrace(); } diff --git a/media/webrtc/trunk/webrtc/voice_engine/shared_data.h b/media/webrtc/trunk/webrtc/voice_engine/shared_data.h index dd76e96abd..3ab1d45ac5 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/shared_data.h +++ b/media/webrtc/trunk/webrtc/voice_engine/shared_data.h @@ -11,10 +11,10 @@ #ifndef WEBRTC_VOICE_ENGINE_SHARED_DATA_H #define WEBRTC_VOICE_ENGINE_SHARED_DATA_H +#include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/audio_device/include/audio_device.h" #include "webrtc/modules/audio_processing/include/audio_processing.h" #include "webrtc/modules/utility/interface/process_thread.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/voice_engine/channel_manager.h" #include "webrtc/voice_engine/statistics.h" #include "webrtc/voice_engine/voice_engine_defines.h" @@ -48,7 +48,7 @@ public: void set_ext_recording(bool value) { _externalRecording = value; } bool ext_playout() const { return _externalPlayout; } void set_ext_playout(bool value) { _externalPlayout = value; } - ProcessThread* process_thread() { return _moduleProcessThreadPtr; } + ProcessThread* process_thread() { return _moduleProcessThreadPtr.get(); } AudioDeviceModule::AudioLayer audio_device_layer() const { return _audioDeviceLayer; } @@ -73,8 +73,8 @@ protected: AudioDeviceModule* _audioDevicePtr; OutputMixer* _outputMixerPtr; TransmitMixer* _transmitMixerPtr; - scoped_ptr audioproc_; - ProcessThread* _moduleProcessThreadPtr; + rtc::scoped_ptr audioproc_; + rtc::scoped_ptr _moduleProcessThreadPtr; bool _externalRecording; bool _externalPlayout; diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/android/android_test/jni/android_test.cc b/media/webrtc/trunk/webrtc/voice_engine/test/android/android_test/jni/android_test.cc index 2f04cc57ab..b0a26e06a0 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/android/android_test/jni/android_test.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/test/android/android_test/jni/android_test.cc @@ -139,19 +139,20 @@ class my_transportation : public Transport netw(network) { } - virtual int SendPacket(int channel,const void *data,int len) OVERRIDE; - virtual int SendRTCPPacket(int channel, const void *data, int len) OVERRIDE; + int SendPacket(int channel, const void* data, size_t len) override; + int SendRTCPPacket(int channel, const void* data, size_t len) override; + private: VoENetwork * netw; }; -int my_transportation::SendPacket(int channel,const void *data,int len) +int my_transportation::SendPacket(int channel, const void *data, size_t len) { netw->ReceivedRTPPacket(channel, data, len); return len; } -int my_transportation::SendRTCPPacket(int channel, const void *data, int len) +int my_transportation::SendRTCPPacket(int channel, const void *data, size_t len) { netw->ReceivedRTCPPacket(channel, data, len); return len; @@ -176,27 +177,18 @@ private: static bool Run(void* ptr); bool Process(); private: - ThreadWrapper* _thread; + rtc::scoped_ptr _thread; }; ThreadTest::~ThreadTest() { if (_thread) - { - _thread->SetNotAlive(); - if (_thread->Stop()) - { - delete _thread; - _thread = NULL; - } - } + _thread->Stop(); } -ThreadTest::ThreadTest() : - _thread(NULL) +ThreadTest::ThreadTest() { - _thread = ThreadWrapper::CreateThread(Run, this, kNormalPriority, - "ThreadTest thread"); + _thread = ThreadWrapper::CreateThread(Run, this, "ThreadTest thread"); } bool ThreadTest::Run(void* ptr) @@ -270,7 +262,6 @@ bool ThreadTest::Process() "sending instance started from thread"); #endif - _thread->SetNotAlive(); _thread->Stop(); //res = veData1.jvm->DetachCurrentThread(); @@ -282,8 +273,7 @@ int ThreadTest::RunTest() { if (_thread) { - unsigned int id; - _thread->Start(id); + _thread->Start(); } return 0; } diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/extended/ec_metrics_test.cc b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/extended/ec_metrics_test.cc index feb36ddc08..a202aea280 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/extended/ec_metrics_test.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/extended/ec_metrics_test.cc @@ -41,14 +41,17 @@ TEST_F(EcMetricsTest, ManualTestEcMetrics) { int erl, erle, rerl, a_nlp; int delay_median = 0; int delay_std = 0; + float fraction_poor_delays = 0; for (int i = 0; i < 5; i++) { Sleep(1000); EXPECT_EQ(0, voe_apm_->GetEchoMetrics(erl, erle, rerl, a_nlp)); - EXPECT_EQ(0, voe_apm_->GetEcDelayMetrics(delay_median, delay_std)); + EXPECT_EQ(0, voe_apm_->GetEcDelayMetrics(delay_median, delay_std, + fraction_poor_delays)); TEST_LOG(" Echo : ERL=%5d, ERLE=%5d, RERL=%5d, A_NLP=%5d [dB], " - " delay median=%3d, delay std=%3d [ms]\n", erl, erle, rerl, a_nlp, - delay_median, delay_std); + " delay median=%3d, delay std=%3d [ms], " + "fraction_poor_delays=%3.1f [%%]\n", erl, erle, rerl, a_nlp, + delay_median, delay_std, fraction_poor_delays * 100); } EXPECT_EQ(0, voe_apm_->SetEcMetricsStatus(false)); @@ -63,8 +66,9 @@ TEST_F(EcMetricsTest, GetEcMetricsFailsIfEcNotEnabled) { TEST_F(EcMetricsTest, GetEcDelayMetricsFailsIfEcNotEnabled) { int dummy = 0; + float dummy_f = 0; EXPECT_EQ(0, voe_apm_->SetEcMetricsStatus(true)); - EXPECT_EQ(-1, voe_apm_->GetEcDelayMetrics(dummy, dummy)); + EXPECT_EQ(-1, voe_apm_->GetEcDelayMetrics(dummy, dummy, dummy_f)); EXPECT_EQ(VE_APM_ERROR, voe_base_->LastError()); } @@ -76,8 +80,11 @@ TEST_F(EcMetricsTest, ManualVerifyEcDelayMetrics) { for (int i = 0; i < 5; i++) { int delay, delay_std; - EXPECT_EQ(0, voe_apm_->GetEcDelayMetrics(delay, delay_std)); - TEST_LOG("Delay = %d, Delay Std = %d\n", delay, delay_std); + float fraction_poor_delays; + EXPECT_EQ(0, voe_apm_->GetEcDelayMetrics(delay, delay_std, + fraction_poor_delays)); + TEST_LOG("Delay = %d, Delay Std = %d, Fraction poor delays = %3.1f\n", + delay, delay_std, fraction_poor_delays * 100); Sleep(1000); } } diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fakes/fake_external_transport.cc b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fakes/fake_external_transport.cc index 164e547ab1..c825ea5861 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fakes/fake_external_transport.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fakes/fake_external_transport.cc @@ -18,7 +18,6 @@ FakeExternalTransport::FakeExternalTransport(webrtc::VoENetwork* ptr) : my_network_(ptr), - thread_(NULL), lock_(NULL), event_(NULL), length_(0), @@ -28,26 +27,21 @@ FakeExternalTransport::FakeExternalTransport(webrtc::VoENetwork* ptr) const char* thread_name = "external_thread"; lock_ = webrtc::CriticalSectionWrapper::CreateCriticalSection(); event_ = webrtc::EventWrapper::Create(); - thread_ = webrtc::ThreadWrapper::CreateThread( - Run, this, webrtc::kHighPriority, thread_name); + thread_ = webrtc::ThreadWrapper::CreateThread(Run, this, thread_name); if (thread_) { - unsigned int id; - thread_->Start(id); + thread_->Start(); + thread_->SetPriority(webrtc::kHighPriority); } } FakeExternalTransport::~FakeExternalTransport() { if (thread_) { - thread_->SetNotAlive(); event_->Set(); - if (thread_->Stop()) { - delete thread_; - thread_ = NULL; - delete event_; - event_ = NULL; - delete lock_; - lock_ = NULL; - } + thread_->Stop(); + delete event_; + event_ = NULL; + delete lock_; + lock_ = NULL; } } @@ -71,7 +65,9 @@ bool FakeExternalTransport::Process() { return true; } -int FakeExternalTransport::SendPacket(int channel, const void *data, int len) { +int FakeExternalTransport::SendPacket(int channel, + const void *data, + size_t len) { lock_->Enter(); if (len < 1612) { memcpy(packet_buffer_, (const unsigned char*) data, len); @@ -80,17 +76,17 @@ int FakeExternalTransport::SendPacket(int channel, const void *data, int len) { } lock_->Leave(); event_->Set(); // Triggers ReceivedRTPPacket() from worker thread. - return len; + return static_cast(len); } int FakeExternalTransport::SendRTCPPacket(int channel, const void *data, - int len) { + size_t len) { if (delay_is_enabled_) { webrtc::SleepMs(delay_time_in_ms_); } my_network_->ReceivedRTCPPacket(channel, data, len); - return len; + return static_cast(len); } void FakeExternalTransport::SetDelayStatus(bool enable, diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fakes/fake_external_transport.h b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fakes/fake_external_transport.h index 318afdaf68..aecc58264a 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fakes/fake_external_transport.h +++ b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fakes/fake_external_transport.h @@ -23,10 +23,8 @@ class FakeExternalTransport : public webrtc::Transport { public: explicit FakeExternalTransport(webrtc::VoENetwork* ptr); virtual ~FakeExternalTransport(); - - virtual int SendPacket(int channel, const void *data, int len) OVERRIDE; - virtual int SendRTCPPacket(int channel, const void *data, int len) OVERRIDE; - + int SendPacket(int channel, const void* data, size_t len) override; + int SendRTCPPacket(int channel, const void* data, size_t len) override; void SetDelayStatus(bool enabled, unsigned int delayInMs = 100); webrtc::VoENetwork* my_network_; @@ -34,12 +32,12 @@ class FakeExternalTransport : public webrtc::Transport { static bool Run(void* ptr); bool Process(); private: - webrtc::ThreadWrapper* thread_; + rtc::scoped_ptr thread_; webrtc::CriticalSectionWrapper* lock_; webrtc::EventWrapper* event_; private: unsigned char packet_buffer_[1612]; - int length_; + size_t length_; int channel_; bool delay_is_enabled_; int delay_time_in_ms_; diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fixtures/after_initialization_fixture.h b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fixtures/after_initialization_fixture.h index 3b3878a777..cee5a58f8e 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fixtures/after_initialization_fixture.h +++ b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fixtures/after_initialization_fixture.h @@ -13,10 +13,12 @@ #include +#include "webrtc/base/scoped_ptr.h" #include "webrtc/common_types.h" +#include "webrtc/system_wrappers/interface/atomic32.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/event_wrapper.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/system_wrappers/interface/sleep.h" #include "webrtc/system_wrappers/interface/thread_wrapper.h" #include "webrtc/voice_engine/test/auto_test/fixtures/before_initialization_fixture.h" @@ -27,22 +29,32 @@ class LoopBackTransport : public webrtc::Transport { LoopBackTransport(webrtc::VoENetwork* voe_network) : crit_(webrtc::CriticalSectionWrapper::CreateCriticalSection()), packet_event_(webrtc::EventWrapper::Create()), - thread_(webrtc::ThreadWrapper::CreateThread(NetworkProcess, this)), - voe_network_(voe_network) { - unsigned int id; - thread_->Start(id); + thread_(webrtc::ThreadWrapper::CreateThread( + NetworkProcess, this, "LoopBackTransport")), + voe_network_(voe_network), transmitted_packets_(0) { + thread_->Start(); } ~LoopBackTransport() { thread_->Stop(); } - virtual int SendPacket(int channel, const void* data, int len) OVERRIDE { + int SendPacket(int channel, const void* data, size_t len) override { StorePacket(Packet::Rtp, channel, data, len); - return len; + return static_cast(len); } - virtual int SendRTCPPacket(int channel, const void* data, int len) OVERRIDE { + int SendRTCPPacket(int channel, const void* data, size_t len) override { StorePacket(Packet::Rtcp, channel, data, len); - return len; + return static_cast(len); + } + + void WaitForTransmittedPackets(int32_t packet_count) { + enum { + kSleepIntervalMs = 10 + }; + int32_t limit = transmitted_packets_.Value() + packet_count; + while (transmitted_packets_.Value() < limit) { + webrtc::SleepMs(kSleepIntervalMs); + } } private: @@ -50,20 +62,24 @@ class LoopBackTransport : public webrtc::Transport { enum Type { Rtp, Rtcp, } type; Packet() : len(0) {} - Packet(Type type, int channel, const void* data, int len) + Packet(Type type, int channel, const void* data, size_t len) : type(type), channel(channel), len(len) { assert(len <= 1500); - memcpy(this->data, data, static_cast(len)); + memcpy(this->data, data, len); } int channel; uint8_t data[1500]; - int len; + size_t len; }; - void StorePacket(Packet::Type type, int channel, const void* data, int len) { - webrtc::CriticalSectionScoped lock(crit_.get()); - packet_queue_.push_back(Packet(type, channel, data, len)); + void StorePacket(Packet::Type type, int channel, + const void* data, + size_t len) { + { + webrtc::CriticalSectionScoped lock(crit_.get()); + packet_queue_.push_back(Packet(type, channel, data, len)); + } packet_event_->Set(); } @@ -74,7 +90,6 @@ class LoopBackTransport : public webrtc::Transport { bool SendPackets() { switch (packet_event_->Wait(10)) { case webrtc::kEventSignaled: - packet_event_->Reset(); break; case webrtc::kEventTimeout: break; @@ -102,15 +117,17 @@ class LoopBackTransport : public webrtc::Transport { voe_network_->ReceivedRTCPPacket(p.channel, p.data, p.len); break; } + ++transmitted_packets_; } return true; } - webrtc::scoped_ptr crit_; - webrtc::scoped_ptr packet_event_; - webrtc::scoped_ptr thread_; + const rtc::scoped_ptr crit_; + const rtc::scoped_ptr packet_event_; + const rtc::scoped_ptr thread_; std::deque packet_queue_ GUARDED_BY(crit_.get()); webrtc::VoENetwork* const voe_network_; + webrtc::Atomic32 transmitted_packets_; }; // This fixture initializes the voice engine in addition to the work @@ -124,7 +141,7 @@ class AfterInitializationFixture : public BeforeInitializationFixture { virtual ~AfterInitializationFixture(); protected: - webrtc::scoped_ptr error_observer_; + rtc::scoped_ptr error_observer_; }; #endif // SRC_VOICE_ENGINE_MAIN_TEST_AUTO_TEST_STANDARD_TEST_BASE_AFTER_INIT_H_ diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fixtures/before_streaming_fixture.cc b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fixtures/before_streaming_fixture.cc index 8a7c4c3b4d..488f4489bf 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fixtures/before_streaming_fixture.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fixtures/before_streaming_fixture.cc @@ -56,6 +56,10 @@ void BeforeStreamingFixture::ResumePlaying() { EXPECT_EQ(0, voe_base_->StartSend(channel_)); } +void BeforeStreamingFixture::WaitForTransmittedPackets(int32_t packet_count) { + transport_->WaitForTransmittedPackets(packet_count); +} + void BeforeStreamingFixture::SetUpLocalPlayback() { transport_ = new LoopBackTransport(voe_network_); EXPECT_EQ(0, voe_network_->RegisterExternalTransport(channel_, *transport_)); diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fixtures/before_streaming_fixture.h b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fixtures/before_streaming_fixture.h index 6de583c7e7..1348e481a8 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fixtures/before_streaming_fixture.h +++ b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/fixtures/before_streaming_fixture.h @@ -41,6 +41,9 @@ class BeforeStreamingFixture : public AfterInitializationFixture { // Resumes all sending and playout. void ResumePlaying(); + // Waits until packet_count packetes have been processed by recipient. + void WaitForTransmittedPackets(int32_t packet_count); + private: void SetUpLocalPlayback(); diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/codec_before_streaming_test.cc b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/codec_before_streaming_test.cc index 66c00d459a..a733b12705 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/codec_before_streaming_test.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/codec_before_streaming_test.cc @@ -47,6 +47,7 @@ TEST_F(CodecBeforeStreamingTest, GetRecPayloadTypeRecognizesISAC) { TEST_F(CodecBeforeStreamingTest, SetRecPayloadTypeCanChangeISACPayloadType) { strcpy(codec_instance_.plname, "ISAC"); + codec_instance_.rate = 32000; codec_instance_.pltype = 123; EXPECT_EQ(0, voe_codec_->SetRecPayloadType(channel_, codec_instance_)); diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/codec_test.cc b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/codec_test.cc index 3b56bae54c..bfc2a30c5f 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/codec_test.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/codec_test.cc @@ -97,16 +97,17 @@ TEST_F(CodecTest, VoiceActivityDetectionTypeSettingsCanBeChanged) { EXPECT_EQ(vad_mode, webrtc::kVadAggressiveMid); EXPECT_FALSE(dtx_disabled); - // The fourth argument is the DTX disable flag. - EXPECT_EQ(0, voe_codec_->SetVADStatus( - channel_, true, webrtc::kVadAggressiveHigh, true)); + // The fourth argument is the DTX disable flag, which is always supposed to + // be false. + EXPECT_EQ(0, voe_codec_->SetVADStatus(channel_, true, + webrtc::kVadAggressiveHigh, false)); EXPECT_EQ(0, voe_codec_->GetVADStatus( channel_, vad_enabled, vad_mode, dtx_disabled)); EXPECT_EQ(vad_mode, webrtc::kVadAggressiveHigh); - EXPECT_TRUE(dtx_disabled); + EXPECT_FALSE(dtx_disabled); - EXPECT_EQ(0, voe_codec_->SetVADStatus( - channel_, true, webrtc::kVadConventional, true)); + EXPECT_EQ(0, voe_codec_->SetVADStatus(channel_, true, + webrtc::kVadConventional, false)); EXPECT_EQ(0, voe_codec_->GetVADStatus( channel_, vad_enabled, vad_mode, dtx_disabled)); EXPECT_EQ(vad_mode, webrtc::kVadConventional); @@ -157,6 +158,30 @@ TEST_F(CodecTest, OpusMaxPlaybackRateCannotBeSetForNonOpus) { } } +TEST_F(CodecTest, OpusDtxCanBeSetForOpus) { + for (int i = 0; i < voe_codec_->NumOfCodecs(); ++i) { + voe_codec_->GetCodec(i, codec_instance_); + if (_stricmp("opus", codec_instance_.plname)) { + continue; + } + voe_codec_->SetSendCodec(channel_, codec_instance_); + EXPECT_EQ(0, voe_codec_->SetOpusDtx(channel_, false)); + EXPECT_EQ(0, voe_codec_->SetOpusDtx(channel_, true)); + } +} + +TEST_F(CodecTest, OpusDtxCannotBeSetForNonOpus) { + for (int i = 0; i < voe_codec_->NumOfCodecs(); ++i) { + voe_codec_->GetCodec(i, codec_instance_); + if (!_stricmp("opus", codec_instance_.plname)) { + continue; + } + voe_codec_->SetSendCodec(channel_, codec_instance_); + EXPECT_EQ(-1, voe_codec_->SetOpusDtx(channel_, false)); + EXPECT_EQ(-1, voe_codec_->SetOpusDtx(channel_, true)); + } +} + // TODO(xians, phoglund): Re-enable when issue 372 is resolved. TEST_F(CodecTest, DISABLED_ManualVerifySendCodecsForAllPacketSizes) { for (int i = 0; i < voe_codec_->NumOfCodecs(); ++i) { diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/neteq_stats_test.cc b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/neteq_stats_test.cc index c9a913510b..f3be6355ba 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/neteq_stats_test.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/neteq_stats_test.cc @@ -23,31 +23,35 @@ TEST_F(NetEQStatsTest, ManualPrintStatisticsAfterRunningAWhile) { TEST_LOG("Inspect these statistics and ensure they make sense.\n"); - TEST_LOG(" currentAccelerateRate = %hu \n", + TEST_LOG(" currentAccelerateRate = %hu \n", network_statistics.currentAccelerateRate); - TEST_LOG(" currentBufferSize = %hu \n", + TEST_LOG(" currentBufferSize = %hu \n", network_statistics.currentBufferSize); - TEST_LOG(" currentDiscardRate = %hu \n", + TEST_LOG(" currentSecondaryDecodedRate = %hu \n", + network_statistics.currentSecondaryDecodedRate); + TEST_LOG(" currentDiscardRate = %hu \n", network_statistics.currentDiscardRate); - TEST_LOG(" currentExpandRate = %hu \n", + TEST_LOG(" currentExpandRate = %hu \n", network_statistics.currentExpandRate); - TEST_LOG(" currentPacketLossRate = %hu \n", + TEST_LOG(" currentPacketLossRate = %hu \n", network_statistics.currentPacketLossRate); - TEST_LOG(" currentPreemptiveRate = %hu \n", + TEST_LOG(" currentPreemptiveRate = %hu \n", network_statistics.currentPreemptiveRate); - TEST_LOG(" preferredBufferSize = %hu \n", + TEST_LOG(" currentSpeechExpandRate = %hu \n", + network_statistics.currentSpeechExpandRate); + TEST_LOG(" preferredBufferSize = %hu \n", network_statistics.preferredBufferSize); - TEST_LOG(" jitterPeaksFound = %i \n", + TEST_LOG(" jitterPeaksFound = %i \n", network_statistics.jitterPeaksFound); - TEST_LOG(" clockDriftPPM = %i \n", + TEST_LOG(" clockDriftPPM = %i \n", network_statistics.clockDriftPPM); - TEST_LOG(" meanWaitingTimeMs = %i \n", + TEST_LOG(" meanWaitingTimeMs = %i \n", network_statistics.meanWaitingTimeMs); - TEST_LOG(" medianWaitingTimeMs = %i \n", + TEST_LOG(" medianWaitingTimeMs = %i \n", network_statistics.medianWaitingTimeMs); - TEST_LOG(" minWaitingTimeMs = %i \n", + TEST_LOG(" minWaitingTimeMs = %i \n", network_statistics.minWaitingTimeMs); - TEST_LOG(" maxWaitingTimeMs = %i \n", + TEST_LOG(" maxWaitingTimeMs = %i \n", network_statistics.maxWaitingTimeMs); // This is only set to a non-zero value in off-mode. diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/rtp_rtcp_extensions.cc b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/rtp_rtcp_extensions.cc index 2fc117b673..18f064eb77 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/rtp_rtcp_extensions.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/rtp_rtcp_extensions.cc @@ -29,11 +29,9 @@ class ExtensionVerifyTransport : public webrtc::Transport { audio_level_id_(-1), absolute_sender_time_id_(-1) {} - virtual int SendPacket(int channel, const void* data, int len) OVERRIDE { + int SendPacket(int channel, const void* data, size_t len) override { webrtc::RTPHeader header; - if (parser_->Parse(reinterpret_cast(data), - static_cast(len), - &header)) { + if (parser_->Parse(reinterpret_cast(data), len, &header)) { bool ok = true; if (audio_level_id_ >= 0 && !header.extension.hasAudioLevel) { @@ -51,11 +49,11 @@ class ExtensionVerifyTransport : public webrtc::Transport { } // received_packets_ count all packets we receive. ++received_packets_; - return len; + return static_cast(len); } - virtual int SendRTCPPacket(int channel, const void* data, int len) OVERRIDE { - return len; + int SendRTCPPacket(int channel, const void* data, size_t len) override { + return static_cast(len); } void SetAudioLevelId(int id) { @@ -74,7 +72,7 @@ class ExtensionVerifyTransport : public webrtc::Transport { while (received_packets_.Value() < kPacketsExpected) { webrtc::SleepMs(kSleepIntervalMs); } - // Check whether any where 'bad' (didn't contain an extension when they + // Check whether any were 'bad' (didn't contain an extension when they // where supposed to). return bad_packets_.Value() == 0; } @@ -84,7 +82,7 @@ class ExtensionVerifyTransport : public webrtc::Transport { kPacketsExpected = 10, kSleepIntervalMs = 10 }; - webrtc::scoped_ptr parser_; + rtc::scoped_ptr parser_; webrtc::Atomic32 received_packets_; webrtc::Atomic32 bad_packets_; int audio_level_id_; @@ -93,14 +91,12 @@ class ExtensionVerifyTransport : public webrtc::Transport { class SendRtpRtcpHeaderExtensionsTest : public BeforeStreamingFixture { protected: - virtual void SetUp() OVERRIDE { + void SetUp() override { EXPECT_EQ(0, voe_network_->DeRegisterExternalTransport(channel_)); EXPECT_EQ(0, voe_network_->RegisterExternalTransport(channel_, verifying_transport_)); } - virtual void TearDown() OVERRIDE { - PausePlaying(); - } + void TearDown() override { PausePlaying(); } ExtensionVerifyTransport verifying_transport_; }; @@ -163,27 +159,33 @@ class MockViENetwork : public webrtc::ViENetwork { virtual ~MockViENetwork() {} MOCK_METHOD0(Release, int()); + MOCK_METHOD4(SetBitrateConfig, void(int, int, int, int)); MOCK_METHOD2(SetNetworkTransmissionState, void(const int, const bool)); MOCK_METHOD2(RegisterSendTransport, int(const int, webrtc::Transport&)); MOCK_METHOD1(DeregisterSendTransport, int(const int)); - MOCK_METHOD4(ReceivedRTPPacket, int(const int, const void*, const int, + MOCK_METHOD4(ReceivedRTPPacket, int(const int, const void*, const size_t, const webrtc::PacketTime&)); - MOCK_METHOD3(ReceivedRTCPPacket, int(const int, const void*, const int)); + MOCK_METHOD3(ReceivedRTCPPacket, int(const int, const void*, const size_t)); MOCK_METHOD2(SetMTU, int(int, unsigned int)); - MOCK_METHOD4(ReceivedBWEPacket, int(const int, int64_t, int, + MOCK_METHOD4(ReceivedBWEPacket, int(const int, int64_t, size_t, const webrtc::RTPHeader&)); }; class ReceiveRtpRtcpHeaderExtensionsTest : public BeforeStreamingFixture { protected: - virtual void SetUp() OVERRIDE { + void SetUp() override { EXPECT_EQ(0, voe_rtp_rtcp_->SetSendAbsoluteSenderTimeStatus(channel_, true, 11)); EXPECT_EQ(0, voe_rtp_rtcp_->SetReceiveAbsoluteSenderTimeStatus(channel_, true, 11)); } + void Wait() { + WaitForTransmittedPackets(kPacketsExpected); + } + enum { + kPacketsExpected = 5, kVideoChannelId1 = 667, kVideoChannelId2 = 668 }; @@ -191,8 +193,9 @@ class ReceiveRtpRtcpHeaderExtensionsTest : public BeforeStreamingFixture { }; TEST_F(ReceiveRtpRtcpHeaderExtensionsTest, ReceiveASTDisabled) { + EXPECT_CALL(mock_network_, ReceivedBWEPacket(_, _, _, _)).Times(0); ResumePlaying(); - Sleep(500); + Wait(); } TEST_F(ReceiveRtpRtcpHeaderExtensionsTest, ReceiveASTFailSetTarget) { @@ -200,6 +203,7 @@ TEST_F(ReceiveRtpRtcpHeaderExtensionsTest, ReceiveASTFailSetTarget) { EXPECT_EQ(-1, voe_rtp_rtcp_->SetVideoEngineBWETarget(-1, &mock_network_, kVideoChannelId1)); ResumePlaying(); + Wait(); } TEST_F(ReceiveRtpRtcpHeaderExtensionsTest, ReceiveASTEnabled) { @@ -211,7 +215,7 @@ TEST_F(ReceiveRtpRtcpHeaderExtensionsTest, ReceiveASTEnabled) { EXPECT_EQ(0, voe_rtp_rtcp_->SetVideoEngineBWETarget(channel_, &mock_network_, kVideoChannelId1)); ResumePlaying(); - Sleep(500); + Wait(); EXPECT_EQ(0, voe_rtp_rtcp_->SetVideoEngineBWETarget(channel_, NULL, -1)); } @@ -226,7 +230,7 @@ TEST_F(ReceiveRtpRtcpHeaderExtensionsTest, ReceiveASTEnabledBadExtensionId) { EXPECT_EQ(0, voe_rtp_rtcp_->SetVideoEngineBWETarget(channel_, &mock_network_, kVideoChannelId1)); ResumePlaying(); - Sleep(500); + Wait(); EXPECT_EQ(0, voe_rtp_rtcp_->SetVideoEngineBWETarget(channel_, NULL, -1)); } @@ -241,7 +245,7 @@ TEST_F(ReceiveRtpRtcpHeaderExtensionsTest, ReceiveASTEnabledNotSending) { EXPECT_EQ(0, voe_rtp_rtcp_->SetVideoEngineBWETarget(channel_, &mock_network_, kVideoChannelId1)); ResumePlaying(); - Sleep(500); + Wait(); EXPECT_EQ(0, voe_rtp_rtcp_->SetVideoEngineBWETarget(channel_, NULL, -1)); } @@ -256,7 +260,7 @@ TEST_F(ReceiveRtpRtcpHeaderExtensionsTest, ReceiveASTEnabledNotReceiving) { EXPECT_EQ(0, voe_rtp_rtcp_->SetVideoEngineBWETarget(channel_, &mock_network_, kVideoChannelId1)); ResumePlaying(); - Sleep(500); + Wait(); EXPECT_EQ(0, voe_rtp_rtcp_->SetVideoEngineBWETarget(channel_, NULL, -1)); } @@ -275,10 +279,10 @@ TEST_F(ReceiveRtpRtcpHeaderExtensionsTest, ReceiveASTSwitchViENetwork) { EXPECT_EQ(0, voe_rtp_rtcp_->SetVideoEngineBWETarget(channel_, &mock_network_2, kVideoChannelId1)); ResumePlaying(); - Sleep(500); + Wait(); EXPECT_EQ(0, voe_rtp_rtcp_->SetVideoEngineBWETarget(channel_, &mock_network_, kVideoChannelId1)); - Sleep(500); + Wait(); EXPECT_EQ(0, voe_rtp_rtcp_->SetVideoEngineBWETarget(channel_, NULL, -1)); } @@ -295,9 +299,9 @@ TEST_F(ReceiveRtpRtcpHeaderExtensionsTest, ReceiveASTSwitchVideoChannel) { EXPECT_EQ(0, voe_rtp_rtcp_->SetVideoEngineBWETarget(channel_, &mock_network_, kVideoChannelId1)); ResumePlaying(); - Sleep(500); + Wait(); EXPECT_EQ(0, voe_rtp_rtcp_->SetVideoEngineBWETarget(channel_, &mock_network_, kVideoChannelId2)); - Sleep(500); + Wait(); EXPECT_EQ(0, voe_rtp_rtcp_->SetVideoEngineBWETarget(channel_, NULL, -1)); } diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/rtp_rtcp_test.cc b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/rtp_rtcp_test.cc index 9a732c0e2b..e5b2f307de 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/rtp_rtcp_test.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/standard/rtp_rtcp_test.cc @@ -29,16 +29,15 @@ class TestRtpObserver : public webrtc::VoERTPObserver { void WaitForChangedSsrc() { // 10 seconds should be enough. EXPECT_EQ(voetest::kEventSignaled, changed_ssrc_event_->Wait(10*1000)); - changed_ssrc_event_->Reset(); } void SetIncomingSsrc(unsigned int ssrc) { voetest::CriticalSectionScoped lock(crit_.get()); incoming_ssrc_ = ssrc; } public: - voetest::scoped_ptr crit_; + rtc::scoped_ptr crit_; unsigned int incoming_ssrc_; - voetest::scoped_ptr changed_ssrc_event_; + rtc::scoped_ptr changed_ssrc_event_; }; void TestRtpObserver::OnIncomingSSRCChanged(int channel, @@ -55,23 +54,6 @@ void TestRtpObserver::OnIncomingSSRCChanged(int channel, } } -class RtcpAppHandler : public webrtc::VoERTCPObserver { - public: - RtcpAppHandler() : length_in_bytes_(0), sub_type_(0), name_(0) {} - void OnApplicationDataReceived(int channel, - unsigned char sub_type, - unsigned int name, - const unsigned char* data, - unsigned short length_in_bytes); - void Reset(); - ~RtcpAppHandler() {} - unsigned short length_in_bytes_; - unsigned char data_[256]; - unsigned char sub_type_; - unsigned int name_; -}; - - static const char* const RTCP_CNAME = "Whatever"; class RtpRtcpTest : public AfterStreamingFixture { @@ -104,23 +86,6 @@ class RtpRtcpTest : public AfterStreamingFixture { LoopBackTransport* transport_; }; -void RtcpAppHandler::OnApplicationDataReceived( - const int /*channel*/, unsigned char sub_type, - unsigned int name, const unsigned char* data, - unsigned short length_in_bytes) { - length_in_bytes_ = length_in_bytes; - memcpy(data_, &data[0], length_in_bytes); - sub_type_ = sub_type; - name_ = name; -} - -void RtcpAppHandler::Reset() { - length_in_bytes_ = 0; - memset(data_, 0, sizeof(data_)); - sub_type_ = 0; - name_ = 0; -} - TEST_F(RtpRtcpTest, RemoteRtcpCnameHasPropagatedToRemoteSide) { if (!FLAGS_include_timing_dependent_tests) { TEST_LOG("Skipping test - running in slow execution environment...\n"); diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/voe_cpu_test.cc b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/voe_cpu_test.cc index dddbb2cde9..ad6116dcdd 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/voe_cpu_test.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/voe_cpu_test.cc @@ -17,7 +17,7 @@ #include #endif -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/test/channel_transport/include/channel_transport.h" #include "webrtc/voice_engine/test/auto_test/voe_test_defines.h" @@ -64,7 +64,7 @@ int VoECpuTest::DoTest() { CHECK(base->Init()); channel = base->CreateChannel(); - scoped_ptr voice_socket_transport( + rtc::scoped_ptr voice_socket_transport( new VoiceChannelTransport(voe_network, channel)); CHECK(voice_socket_transport->SetSendDestination("127.0.0.1", 5566)); diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/voe_stress_test.cc b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/voe_stress_test.cc index d2c19175c9..ab8fffe832 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/voe_stress_test.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/voe_stress_test.cc @@ -24,9 +24,8 @@ #include "webrtc/voice_engine/test/auto_test/voe_stress_test.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/system_wrappers/interface/sleep.h" -#include "webrtc/system_wrappers/interface/thread_wrapper.h" #include "webrtc/test/channel_transport/include/channel_transport.h" #include "webrtc/voice_engine/test/auto_test/voe_standard_test.h" #include "webrtc/voice_engine/test/auto_test/voe_test_defines.h" @@ -145,7 +144,7 @@ int VoEStressTest::StartStopTest() { printf("Test will take approximately %d minutes. \n", numberOfLoops * loopSleep / 1000 / 60 + 1); - scoped_ptr voice_channel_transport( + rtc::scoped_ptr voice_channel_transport( new VoiceChannelTransport(voe_network, 0)); for (i = 0; i < numberOfLoops; ++i) { @@ -335,11 +334,9 @@ int VoEStressTest::MultipleThreadsTest() { int rnd(0); // Start extra thread - const char* threadName = "StressTest Extra API Thread"; _ptrExtraApiThread = ThreadWrapper::CreateThread(RunExtraApi, this, - kNormalPriority, threadName); - unsigned int id(0); - VALIDATE_STRESS(!_ptrExtraApiThread->Start(id)); + "StressTestExtraApiThread"); + VALIDATE_STRESS(!_ptrExtraApiThread->Start()); // Some possible extensions include: // Add more API calls to randomize @@ -369,7 +366,6 @@ int VoEStressTest::MultipleThreadsTest() { // Stop extra thread VALIDATE_STRESS(!_ptrExtraApiThread->Stop()); - delete _ptrExtraApiThread; ///////////// End test ///////////// diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/voe_stress_test.h b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/voe_stress_test.h index 15653bc55e..7128b238ff 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/voe_stress_test.h +++ b/media/webrtc/trunk/webrtc/voice_engine/test/auto_test/voe_stress_test.h @@ -11,9 +11,7 @@ #ifndef WEBRTC_VOICE_ENGINE_VOE_STRESS_TEST_H #define WEBRTC_VOICE_ENGINE_VOE_STRESS_TEST_H -namespace webrtc { -class ThreadWrapper; -} +#include "webrtc/system_wrappers/interface/thread_wrapper.h" namespace voetest { // TODO(andrew): using directives are not permitted. @@ -23,8 +21,7 @@ class VoETestManager; class VoEStressTest { public: - VoEStressTest(VoETestManager& mgr) : - _mgr(mgr), _ptrExtraApiThread(NULL) { + VoEStressTest(VoETestManager& mgr) : _mgr(mgr) { } ~VoEStressTest() { } @@ -41,7 +38,7 @@ class VoEStressTest { VoETestManager& _mgr; - ThreadWrapper* _ptrExtraApiThread; + rtc::scoped_ptr _ptrExtraApiThread; }; } // namespace voetest diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/cmd_test/voe_cmd_test.cc b/media/webrtc/trunk/webrtc/voice_engine/test/cmd_test/voe_cmd_test.cc index 09a70a9d82..419ba55d78 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/cmd_test/voe_cmd_test.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/test/cmd_test/voe_cmd_test.cc @@ -19,9 +19,9 @@ #include "gflags/gflags.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/engine_configurations.h" #include "webrtc/modules/audio_processing/include/audio_processing.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/test/channel_transport/include/channel_transport.h" #include "webrtc/test/testsupport/fileutils.h" #include "webrtc/test/testsupport/trace_to_stderr.h" @@ -140,7 +140,7 @@ int main(int argc, char** argv) { MyObserver my_observer; - scoped_ptr trace_to_stderr; + rtc::scoped_ptr trace_to_stderr; if (!FLAGS_use_log_file) { trace_to_stderr.reset(new test::TraceToStderr); } else { @@ -232,7 +232,9 @@ void RunTest(std::string out_path) { bool typing_detection = false; bool muted = false; bool opus_stereo = false; + bool opus_dtx = false; bool experimental_ns_enabled = false; + bool debug_recording_started = false; #if defined(WEBRTC_ANDROID) std::string resource_path = "/sdcard/"; @@ -258,7 +260,7 @@ void RunTest(std::string out_path) { fflush(NULL); } - scoped_ptr voice_channel_transport( + rtc::scoped_ptr voice_channel_transport( new VoiceChannelTransport(netw, chan)); char ip[64]; @@ -446,8 +448,10 @@ void RunTest(std::string out_path) { printf("%i. Toggle Opus stereo (Opus must be selected again to apply " "the setting) \n", option_index++); printf("%i. Set Opus maximum playback rate \n", option_index++); + printf("%i. Toggle Opus DTX \n", option_index++); printf("%i. Set bit rate (only take effect on codecs that allow the " "change) \n", option_index++); + printf("%i. Toggle debug recording \n", option_index++); printf("Select action or %i to stop the call: ", option_index); int option_selection; @@ -457,9 +461,14 @@ void RunTest(std::string out_path) { if (option_selection < option_index) { res = codec->GetCodec(option_selection, cinst); VALIDATE; - SetStereoIfOpus(opus_stereo, &cinst); - printf("Set primary codec\n"); - res = codec->SetSendCodec(chan, cinst); + if (strcmp(cinst.plname, "red") == 0) { + printf("Enabling RED\n"); + res = rtp_rtcp->SetREDStatus(chan, true, cinst.pltype); + } else { + SetStereoIfOpus(opus_stereo, &cinst); + printf("Set primary codec\n"); + res = codec->SetSendCodec(chan, cinst); + } VALIDATE; } else if (option_selection == option_index++) { enable_cng = !enable_cng; @@ -766,6 +775,11 @@ void RunTest(std::string out_path) { ASSERT_EQ(1, scanf("%i", &max_playback_rate)); res = codec->SetOpusMaxPlaybackRate(chan, max_playback_rate); VALIDATE; + } else if (option_selection == option_index++) { + opus_dtx = !opus_dtx; + res = codec->SetOpusDtx(chan, opus_dtx); + VALIDATE; + printf("Opus DTX %s.\n", opus_dtx ? "enabled" : "disabled"); } else if (option_selection == option_index++) { res = codec->GetSendCodec(chan, cinst); VALIDATE; @@ -773,11 +787,25 @@ void RunTest(std::string out_path) { ASSERT_EQ(1, scanf("%i", &cinst.rate)); res = codec->SetSendCodec(chan, cinst); VALIDATE; + } else if (option_selection == option_index++) { + const char* kDebugFileName = "audio.aecdump"; + if (debug_recording_started) { + apm->StopDebugRecording(); + printf("Debug recording named %s stopped\n", kDebugFileName); + } else { + apm->StartDebugRecording(kDebugFileName); + printf("Debug recording named %s started\n", kDebugFileName); + } + debug_recording_started = !debug_recording_started; } else { break; } } + if (debug_recording_started) { + apm->StopDebugRecording(); + } + if (send) { printf("Stop Send \n"); res = base1->StopSend(chan); diff --git a/media/webrtc/trunk/webrtc/voice_engine/test/win_test/WinTestDlg.cc b/media/webrtc/trunk/webrtc/voice_engine/test/win_test/WinTestDlg.cc index 4929ae4af6..4436a86d86 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/test/win_test/WinTestDlg.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/test/win_test/WinTestDlg.cc @@ -129,8 +129,9 @@ class MyTransport : public Transport { public: MyTransport(VoENetwork* veNetwork); - virtual int SendPacket(int channel, const void *data, int len) OVERRIDE; - virtual int SendRTCPPacket(int channel, const void *data, int len) OVERRIDE; + int SendPacket(int channel, const void* data, size_t len) override; + int SendRTCPPacket(int channel, const void* data, size_t len) override; + private: VoENetwork* _veNetworkPtr; }; @@ -141,14 +142,14 @@ MyTransport::MyTransport(VoENetwork* veNetwork) : } int -MyTransport::SendPacket(int channel, const void *data, int len) +MyTransport::SendPacket(int channel, const void *data, size_t len) { _veNetworkPtr->ReceivedRTPPacket(channel, data, len); return len; } int -MyTransport::SendRTCPPacket(int channel, const void *data, int len) +MyTransport::SendRTCPPacket(int channel, const void *data, size_t len) { _veNetworkPtr->ReceivedRTCPPacket(channel, data, len); return len; @@ -923,23 +924,27 @@ void CTelephonyEvent::OnBnClickedButtonSetRxTelephonePt() { BOOL ret; int pt = GetDlgItemInt(IDC_EDIT_EVENT_RX_PT, &ret); - if (ret == FALSE) + if (ret == FALSE || pt < 0 || pt > 127) return; CodecInst codec; strcpy_s(codec.plname, 32, "telephone-event"); - codec.pltype = pt; codec.channels = 1; codec.plfreq = 8000; + codec.pltype = pt; + codec.channels = 1; + codec.plfreq = 8000; TEST2(_veCodecPtr->SetRecPayloadType(_channel, codec) == 0, - _T("SetSendTelephoneEventPayloadType(channel=%d, codec.pltype=%u)"), _channel, codec.pltype); + _T("SetRecPayloadType(channel=%d, codec.pltype=%d)"), _channel, + codec.pltype); } void CTelephonyEvent::OnBnClickedButtonSetTxTelephonePt() { BOOL ret; int pt = GetDlgItemInt(IDC_EDIT_EVENT_TX_PT, &ret); - if (ret == FALSE) + if (ret == FALSE || pt < 0 || pt > 127) return; TEST2(_veDTMFPtr->SetSendTelephoneEventPayloadType(_channel, pt) == 0, - _T("SetSendTelephoneEventPayloadType(channel=%d, type=%u)"), _channel, pt); + _T("SetSendTelephoneEventPayloadType(channel=%d, type=%d)"), _channel, + pt); } void CTelephonyEvent::OnBnClickedCheckDetectInband() diff --git a/media/webrtc/trunk/webrtc/voice_engine/transmit_mixer.cc b/media/webrtc/trunk/webrtc/voice_engine/transmit_mixer.cc index fa8697e2e9..ac9247f062 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/transmit_mixer.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/transmit_mixer.cc @@ -259,15 +259,8 @@ TransmitMixer::SetEngineInformation(ProcessThread& processThread, _engineStatisticsPtr = &engineStatistics; _channelManagerPtr = &channelManager; - if (_processThreadPtr->RegisterModule(&_monitorModule) == -1) - { - WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1), - "TransmitMixer::SetEngineInformation() failed to" - "register the monitor module"); - } else - { - _monitorModule.RegisterObserver(*this); - } + _processThreadPtr->RegisterModule(&_monitorModule); + _monitorModule.RegisterObserver(*this); return 0; } @@ -1196,7 +1189,7 @@ int32_t TransmitMixer::RecordAudioToFile( int32_t TransmitMixer::MixOrReplaceAudioWithFile( int mixingFrequency) { - scoped_ptr fileBuffer(new int16_t[640]); + rtc::scoped_ptr fileBuffer(new int16_t[640]); int fileSamples(0); { diff --git a/media/webrtc/trunk/webrtc/voice_engine/transmit_mixer.h b/media/webrtc/trunk/webrtc/voice_engine/transmit_mixer.h index afeec3ac88..919de13123 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/transmit_mixer.h +++ b/media/webrtc/trunk/webrtc/voice_engine/transmit_mixer.h @@ -11,13 +11,13 @@ #ifndef WEBRTC_VOICE_ENGINE_TRANSMIT_MIXER_H #define WEBRTC_VOICE_ENGINE_TRANSMIT_MIXER_H +#include "webrtc/base/scoped_ptr.h" #include "webrtc/common_audio/resampler/include/push_resampler.h" #include "webrtc/common_types.h" #include "webrtc/modules/audio_processing/typing_detection.h" #include "webrtc/modules/interface/module_common_types.h" #include "webrtc/modules/utility/interface/file_player.h" #include "webrtc/modules/utility/interface/file_recorder.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/voice_engine/include/voe_base.h" #include "webrtc/voice_engine/level_indicator.h" #include "webrtc/voice_engine/monitor_module.h" @@ -229,7 +229,7 @@ private: int32_t _remainingMuteMicTimeMs; bool stereo_codec_; bool swap_stereo_channels_; - scoped_ptr mono_buffer_; + rtc::scoped_ptr mono_buffer_; }; } // namespace voe diff --git a/media/webrtc/trunk/webrtc/voice_engine/voe_audio_processing_impl.cc b/media/webrtc/trunk/webrtc/voice_engine/voe_audio_processing_impl.cc index 63a4ed768a..a310628eec 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voe_audio_processing_impl.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/voe_audio_processing_impl.cc @@ -921,9 +921,10 @@ int VoEAudioProcessingImpl::GetEchoMetrics(int& ERL, } int VoEAudioProcessingImpl::GetEcDelayMetrics(int& delay_median, - int& delay_std) { + int& delay_std, + float& fraction_poor_delays) { WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), - "GetEcDelayMetrics(median=?, std=?)"); + "GetEcDelayMetrics(median=?, std=?, fraction_poor_delays=?)"); #ifdef WEBRTC_VOICE_ENGINE_ECHO if (!_shared->statistics().Initialized()) { _shared->SetLastError(VE_NOT_INITED, kTraceError); @@ -937,9 +938,10 @@ int VoEAudioProcessingImpl::GetEcDelayMetrics(int& delay_median, int median = 0; int std = 0; + float poor_fraction = 0; // Get delay-logging values from Audio Processing Module. if (_shared->audio_processing()->echo_cancellation()->GetDelayMetrics( - &median, &std)) { + &median, &std, &poor_fraction)) { WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_shared->instance_id(), -1), "GetEcDelayMetrics(), AudioProcessingModule delay-logging " "error"); @@ -949,10 +951,12 @@ int VoEAudioProcessingImpl::GetEcDelayMetrics(int& delay_median, // EC delay-logging metrics delay_median = median; delay_std = std; + fraction_poor_delays = poor_fraction; WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_shared->instance_id(), -1), - "GetEcDelayMetrics() => delay_median=%d, delay_std=%d", - delay_median, delay_std); + "GetEcDelayMetrics() => delay_median=%d, delay_std=%d, " + "fraction_poor_delays=%f", delay_median, delay_std, + fraction_poor_delays); return 0; #else _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError, diff --git a/media/webrtc/trunk/webrtc/voice_engine/voe_audio_processing_impl.h b/media/webrtc/trunk/webrtc/voice_engine/voe_audio_processing_impl.h index 524439d5c1..26f7eec745 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voe_audio_processing_impl.h +++ b/media/webrtc/trunk/webrtc/voice_engine/voe_audio_processing_impl.h @@ -76,7 +76,8 @@ class VoEAudioProcessingImpl : public VoEAudioProcessing { virtual int GetEchoMetrics(int& ERL, int& ERLE, int& RERL, int& A_NLP); - virtual int GetEcDelayMetrics(int& delay_median, int& delay_std); + virtual int GetEcDelayMetrics(int& delay_median, int& delay_std, + float& fraction_poor_delays); virtual int StartDebugRecording(const char* fileNameUTF8); virtual int StartDebugRecording(FILE* file_handle); diff --git a/media/webrtc/trunk/webrtc/voice_engine/voe_auto_test.isolate b/media/webrtc/trunk/webrtc/voice_engine/voe_auto_test.isolate index c13110e718..e89620dde0 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voe_auto_test.isolate +++ b/media/webrtc/trunk/webrtc/voice_engine/voe_auto_test.isolate @@ -7,14 +7,6 @@ # be found in the AUTHORS file in the root of the source tree. { 'conditions': [ - ['OS=="android"', { - 'variables': { - 'files': [ - '<(DEPTH)/data/', - '<(DEPTH)/resources/', - ], - }, - }], ['OS=="linux" or OS=="mac" or OS=="win"', { 'variables': { 'command': [ diff --git a/media/webrtc/trunk/webrtc/voice_engine/voe_base_impl.cc b/media/webrtc/trunk/webrtc/voice_engine/voe_base_impl.cc index 0cf787acf1..430ee40c67 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voe_base_impl.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/voe_base_impl.cc @@ -314,12 +314,7 @@ int VoEBaseImpl::Init(AudioDeviceModule* external_adm, if (_shared->process_thread()) { - if (_shared->process_thread()->Start() != 0) - { - _shared->SetLastError(VE_THREAD_ERROR, kTraceError, - "Init() failed to start module process thread"); - return -1; - } + _shared->process_thread()->Start(); } // Create an internal ADM if the user has not added an external @@ -347,12 +342,9 @@ int VoEBaseImpl::Init(AudioDeviceModule* external_adm, // Register the ADM to the process thread, which will drive the error // callback mechanism - if (_shared->process_thread() && - _shared->process_thread()->RegisterModule(_shared->audio_device()) != 0) + if (_shared->process_thread()) { - _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError, - "Init() failed to register the ADM"); - return -1; + _shared->process_thread()->RegisterModule(_shared->audio_device()); } bool available(false); @@ -432,7 +424,7 @@ int VoEBaseImpl::Init(AudioDeviceModule* external_adm, } if (!audioproc) { - audioproc = AudioProcessing::Create(VoEId(_shared->instance_id(), -1)); + audioproc = AudioProcessing::Create(_shared->channel_manager().config_); if (!audioproc) { LOG(LS_ERROR) << "Failed to create AudioProcessing."; _shared->SetLastError(VE_NO_MEMORY); @@ -962,18 +954,10 @@ int32_t VoEBaseImpl::TerminateInternal() { if (_shared->audio_device()) { - if (_shared->process_thread()-> - DeRegisterModule(_shared->audio_device()) != 0) - { - _shared->SetLastError(VE_THREAD_ERROR, kTraceError, - "TerminateInternal() failed to deregister ADM"); - } - } - if (_shared->process_thread()->Stop() != 0) - { - _shared->SetLastError(VE_THREAD_ERROR, kTraceError, - "TerminateInternal() failed to stop module process thread"); + _shared->process_thread()->DeRegisterModule( + _shared->audio_device()); } + _shared->process_thread()->Stop(); } if (_shared->audio_device()) diff --git a/media/webrtc/trunk/webrtc/voice_engine/voe_base_unittest.cc b/media/webrtc/trunk/webrtc/voice_engine/voe_base_unittest.cc index 6057534d04..69aba712ef 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voe_base_unittest.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/voe_base_unittest.cc @@ -11,9 +11,9 @@ #include "webrtc/voice_engine/include/voe_base.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/audio_device/include/fake_audio_device.h" #include "webrtc/modules/audio_processing/include/audio_processing.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" namespace webrtc { @@ -32,11 +32,11 @@ class VoEBaseTest : public ::testing::Test { VoiceEngine* voe_; VoEBase* base_; - scoped_ptr adm_; + rtc::scoped_ptr adm_; }; TEST_F(VoEBaseTest, AcceptsAudioProcessingPtr) { - AudioProcessing* audioproc = AudioProcessing::Create(0); + AudioProcessing* audioproc = AudioProcessing::Create(); EXPECT_EQ(0, base_->Init(adm_.get(), audioproc)); EXPECT_EQ(audioproc, base_->audio_processing()); } diff --git a/media/webrtc/trunk/webrtc/voice_engine/voe_codec_impl.cc b/media/webrtc/trunk/webrtc/voice_engine/voe_codec_impl.cc index 6f470be106..2b0141fa81 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voe_codec_impl.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/voe_codec_impl.cc @@ -436,6 +436,23 @@ int VoECodecImpl::SetOpusMaxPlaybackRate(int channel, int frequency_hz) { return channelPtr->SetOpusMaxPlaybackRate(frequency_hz); } +int VoECodecImpl::SetOpusDtx(int channel, bool enable_dtx) { + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "SetOpusDtx(channel=%d, enable_dtx=%d)", channel, enable_dtx); + if (!_shared->statistics().Initialized()) { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel); + voe::Channel* channelPtr = ch.channel(); + if (channelPtr == NULL) { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SetOpusDtx failed to locate channel"); + return -1; + } + return channelPtr->SetOpusDtx(enable_dtx); +} + void VoECodecImpl::ACMToExternalCodecRepresentation(CodecInst& toInst, const CodecInst& fromInst) { @@ -514,111 +531,6 @@ void VoECodecImpl::ExternalToACMCodecRepresentation(CodecInst& toInst, } } -int VoECodecImpl::SetSecondarySendCodec(int channel, const CodecInst& codec, - int red_payload_type) { - CodecInst copy_codec; - ExternalToACMCodecRepresentation(copy_codec, codec); - - WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), - "SetSecondarySendCodec(channel=%d, codec)", channel); - WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1), - "codec: plname=%s, pacsize=%d, plfreq=%d, pltype=%d, " - "channels=%d, rate=%d", codec.plname, codec.pacsize, - codec.plfreq, codec.pltype, codec.channels, codec.rate); - if (!_shared->statistics().Initialized()) { - _shared->SetLastError(VE_NOT_INITED, kTraceError); - return -1; - } - - // External sanity checks performed outside the ACM - if ((STR_CASE_CMP(copy_codec.plname, "L16") == 0) && - (copy_codec.pacsize >= 960)) { - _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, - "SetSecondarySendCodec() invalid L16 packet size"); - return -1; - } - - // None of the following codecs can be registered as the secondary encoder. - if (!STR_CASE_CMP(copy_codec.plname, "CN") || - !STR_CASE_CMP(copy_codec.plname, "TELEPHONE-EVENT") || - !STR_CASE_CMP(copy_codec.plname, "RED")) { - _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, - "SetSecondarySendCodec() invalid codec name"); - return -1; - } - - // Only mono and stereo are supported. - if ((copy_codec.channels != 1) && (copy_codec.channels != 2)) { - _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, - "SetSecondarySendCodec() invalid number of channels"); - return -1; - } - voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel); - voe::Channel* channelPtr = ch.channel(); - if (channelPtr == NULL) { - _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, - "SetSecondarySendCodec() failed to locate channel"); - return -1; - } - if (!AudioCodingModule::IsCodecValid(copy_codec)) { - _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, - "SetSecondarySendCodec() invalid codec"); - return -1; - } - if (channelPtr->SetSecondarySendCodec(copy_codec, red_payload_type) != 0) { - _shared->SetLastError(VE_CANNOT_SET_SECONDARY_SEND_CODEC, kTraceError, - "SetSecondarySendCodec() failed to set secondary " - "send codec"); - return -1; - } - return 0; -} - -int VoECodecImpl::GetSecondarySendCodec(int channel, CodecInst& codec) { - WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), - "GetSecondarySendCodec(channel=%d, codec=?)", channel); - if (!_shared->statistics().Initialized()) { - _shared->SetLastError(VE_NOT_INITED, kTraceError); - return -1; - } - voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel); - voe::Channel* channelPtr = ch.channel(); - if (channelPtr == NULL) { - _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, - "GetSecondarySendCodec() failed to locate channel"); - return -1; - } - CodecInst acm_codec; - if (channelPtr->GetSecondarySendCodec(&acm_codec) != 0) { - _shared->SetLastError(VE_CANNOT_GET_SECONDARY_SEND_CODEC, kTraceError, - "GetSecondarySendCodec() failed to get secondary " - "send codec"); - return -1; - } - ACMToExternalCodecRepresentation(codec, acm_codec); - WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, - VoEId(_shared->instance_id(), -1), - "GetSecondarySendCodec() => plname=%s, pacsize=%d, plfreq=%d, " - "channels=%d, rate=%d", codec.plname, codec.pacsize, - codec.plfreq, codec.channels, codec.rate); - return 0; -} - -int VoECodecImpl::RemoveSecondarySendCodec(int channel) { - WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), - "RemoveSecondarySendCodec(channel=%d)", channel); - voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel); - voe::Channel* channelPtr = ch.channel(); - if (channelPtr == NULL) { - _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, - "RemoveSecondarySendCodec() failed to locate " - "channel"); - return -1; - } - channelPtr->RemoveSecondarySendCodec(); - return 0; -} - #endif // WEBRTC_VOICE_ENGINE_CODEC_API } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/voice_engine/voe_codec_impl.h b/media/webrtc/trunk/webrtc/voice_engine/voe_codec_impl.h index f001df8660..dad808dbbf 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voe_codec_impl.h +++ b/media/webrtc/trunk/webrtc/voice_engine/voe_codec_impl.h @@ -56,13 +56,7 @@ public: virtual int SetOpusMaxPlaybackRate(int channel, int frequency_hz); - // Dual-streaming - virtual int SetSecondarySendCodec(int channel, const CodecInst& codec, - int red_payload_type); - - virtual int RemoveSecondarySendCodec(int channel); - - virtual int GetSecondarySendCodec(int channel, CodecInst& codec); + virtual int SetOpusDtx(int channel, bool enable_dtx); protected: VoECodecImpl(voe::SharedData* shared); diff --git a/media/webrtc/trunk/webrtc/voice_engine/voe_codec_unittest.cc b/media/webrtc/trunk/webrtc/voice_engine/voe_codec_unittest.cc index 7e440b2ada..6eb5a5145c 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voe_codec_unittest.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/voe_codec_unittest.cc @@ -11,8 +11,8 @@ #include "webrtc/voice_engine/include/voe_codec.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/audio_device/include/fake_audio_device.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/test/testsupport/gtest_disable.h" #include "webrtc/voice_engine/include/voe_base.h" #include "webrtc/voice_engine/include/voe_hardware.h" @@ -94,81 +94,13 @@ class VoECodecTest : public ::testing::Test { int channel_; CodecInst primary_; CodecInst valid_secondary_; - scoped_ptr adm_; + rtc::scoped_ptr adm_; // A codec which is not valid to be registered as secondary codec. CodecInst invalid_secondary_; int red_payload_type_; }; - -TEST_F(VoECodecTest, - DISABLED_ON_ANDROID(DualStreamSetSecondaryBeforePrimaryFails)) { - // Setting secondary before a primary is registered should fail. - EXPECT_EQ(-1, voe_codec_->SetSecondarySendCodec(channel_, valid_secondary_, - red_payload_type_)); - red_payload_type_ = 1; -} - -TEST_F(VoECodecTest, - DISABLED_ON_ANDROID(DualStreamRegisterWithWrongInputsFails)) { - // Register primary codec. - EXPECT_EQ(0, voe_codec_->SetSendCodec(channel_, primary_)); - - // Wrong secondary. - EXPECT_EQ(-1, voe_codec_->SetSecondarySendCodec(channel_, invalid_secondary_, - red_payload_type_)); - - // Wrong payload. - EXPECT_EQ(-1, voe_codec_->SetSecondarySendCodec(channel_, valid_secondary_, - -1)); - // Wrong channel. - EXPECT_EQ(-1, voe_codec_->SetSecondarySendCodec(channel_ + 1, - valid_secondary_, - red_payload_type_)); -} - -TEST_F(VoECodecTest, DISABLED_ON_ANDROID(DualStreamGetSecodaryEncoder)) { - // Register primary codec. - EXPECT_EQ(0, voe_codec_->SetSendCodec(channel_, primary_)); - - // Register a valid codec. - EXPECT_EQ(0, voe_codec_->SetSecondarySendCodec(channel_, valid_secondary_, - red_payload_type_)); - CodecInst my_codec; - - // Get secondary codec from wrong channel. - EXPECT_EQ(-1, voe_codec_->GetSecondarySendCodec(channel_ + 1, my_codec)); - - // Get secondary and compare. - memset(&my_codec, 0, sizeof(my_codec)); - EXPECT_EQ(0, voe_codec_->GetSecondarySendCodec(channel_, my_codec)); - - EXPECT_EQ(valid_secondary_.plfreq, my_codec.plfreq); - EXPECT_EQ(valid_secondary_.channels, my_codec.channels); - EXPECT_EQ(valid_secondary_.pacsize, my_codec.pacsize); - EXPECT_EQ(valid_secondary_.rate, my_codec.rate); - EXPECT_EQ(valid_secondary_.pltype, my_codec.pltype); - EXPECT_EQ(0, STR_CASE_CMP(valid_secondary_.plname, my_codec.plname)); -} - -TEST_F(VoECodecTest, DISABLED_ON_ANDROID(DualStreamRemoveSecondaryCodec)) { - // Register primary codec. - EXPECT_EQ(0, voe_codec_->SetSendCodec(channel_, primary_)); - - // Register a valid codec. - EXPECT_EQ(0, voe_codec_->SetSecondarySendCodec(channel_, valid_secondary_, - red_payload_type_)); - // Remove from wrong channel. - EXPECT_EQ(-1, voe_codec_->RemoveSecondarySendCodec(channel_ + 1)); - EXPECT_EQ(0, voe_codec_->RemoveSecondarySendCodec(channel_)); - - CodecInst my_codec; - - // Get should fail, if secondary is removed. - EXPECT_EQ(-1, voe_codec_->GetSecondarySendCodec(channel_, my_codec)); -} - TEST(VoECodecInst, TestCompareCodecInstances) { CodecInst codec1, codec2; memset(&codec1, 0, sizeof(CodecInst)); diff --git a/media/webrtc/trunk/webrtc/voice_engine/voe_hardware_impl.cc b/media/webrtc/trunk/webrtc/voice_engine/voe_hardware_impl.cc index 921701b21f..4505f9ee86 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voe_hardware_impl.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/voe_hardware_impl.cc @@ -787,6 +787,14 @@ int VoEHardwareImpl::PlayoutSampleRate(unsigned int* samples_per_sec) const { return _shared->audio_device()->PlayoutSampleRate(samples_per_sec); } +bool VoEHardwareImpl::BuiltInAECIsAvailable() const { +if (!_shared->statistics().Initialized()) { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return false; + } + return _shared->audio_device()->BuiltInAECIsAvailable(); +} + #endif // WEBRTC_VOICE_ENGINE_HARDWARE_API } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/voice_engine/voe_hardware_impl.h b/media/webrtc/trunk/webrtc/voice_engine/voe_hardware_impl.h index 4e06f978d9..e23e4e5df4 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voe_hardware_impl.h +++ b/media/webrtc/trunk/webrtc/voice_engine/voe_hardware_impl.h @@ -28,15 +28,15 @@ public: virtual int GetRecordingDeviceName(int index, char strNameUTF8[128], char strGuidUTF8[128]); + + virtual int GetRecordingDeviceStatus(bool& isAvailable); + + virtual int GetPlayoutDeviceStatus(bool& isAvailable); virtual int GetPlayoutDeviceName(int index, char strNameUTF8[128], char strGuidUTF8[128]); - virtual int GetRecordingDeviceStatus(bool& isAvailable); - - virtual int GetPlayoutDeviceStatus(bool& isAvailable); - virtual int SetRecordingDevice( int index, StereoChannel recordingChannel = kStereoBoth); @@ -44,9 +44,7 @@ public: virtual int SetPlayoutDevice(int index); virtual int SetAudioDeviceLayer(AudioLayers audioLayer); - - virtual int GetAudioDeviceLayer(AudioLayers& audioLayer); - + virtual int GetCPULoad(int& loadPercent); virtual int ResetAudioDevice(); @@ -62,11 +60,15 @@ public: virtual int EnableBuiltInAEC(bool enable); virtual bool BuiltInAECIsEnabled() const; + virtual int GetAudioDeviceLayer(AudioLayers& audioLayer); + virtual int SetRecordingSampleRate(unsigned int samples_per_sec); virtual int RecordingSampleRate(unsigned int* samples_per_sec) const; virtual int SetPlayoutSampleRate(unsigned int samples_per_sec); virtual int PlayoutSampleRate(unsigned int* samples_per_sec) const; + virtual bool BuiltInAECIsAvailable() const; + protected: VoEHardwareImpl(voe::SharedData* shared); virtual ~VoEHardwareImpl(); diff --git a/media/webrtc/trunk/webrtc/voice_engine/voe_network_impl.cc b/media/webrtc/trunk/webrtc/voice_engine/voe_network_impl.cc index 70c548857b..89d1b04f48 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voe_network_impl.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/voe_network_impl.cc @@ -10,6 +10,7 @@ #include "webrtc/voice_engine/voe_network_impl.h" +#include "webrtc/base/format_macros.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/logging.h" #include "webrtc/system_wrappers/interface/trace.h" @@ -88,17 +89,18 @@ int VoENetworkImpl::DeRegisterExternalTransport(int channel) int VoENetworkImpl::ReceivedRTPPacket(int channel, const void* data, - unsigned int length) { + size_t length) { return ReceivedRTPPacket(channel, data, length, webrtc::PacketTime()); } int VoENetworkImpl::ReceivedRTPPacket(int channel, const void* data, - unsigned int length, + size_t length, const PacketTime& packet_time) { WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_shared->instance_id(), -1), - "ReceivedRTPPacket(channel=%d, length=%u)", channel, length); + "ReceivedRTPPacket(channel=%d, length=%" PRIuS ")", channel, + length); if (!_shared->statistics().Initialized()) { _shared->SetLastError(VE_NOT_INITED, kTraceError); @@ -137,10 +139,11 @@ int VoENetworkImpl::ReceivedRTPPacket(int channel, } int VoENetworkImpl::ReceivedRTCPPacket(int channel, const void* data, - unsigned int length) + size_t length) { WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_shared->instance_id(), -1), - "ReceivedRTCPPacket(channel=%d, length=%u)", channel, length); + "ReceivedRTCPPacket(channel=%d, length=%" PRIuS ")", channel, + length); if (!_shared->statistics().Initialized()) { _shared->SetLastError(VE_NOT_INITED, kTraceError); diff --git a/media/webrtc/trunk/webrtc/voice_engine/voe_network_impl.h b/media/webrtc/trunk/webrtc/voice_engine/voe_network_impl.h index 0cf07ad1fd..ee9b92ec3b 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voe_network_impl.h +++ b/media/webrtc/trunk/webrtc/voice_engine/voe_network_impl.h @@ -22,22 +22,17 @@ namespace webrtc class VoENetworkImpl: public VoENetwork { public: - virtual int RegisterExternalTransport(int channel, - Transport& transport) OVERRIDE; + int RegisterExternalTransport(int channel, Transport& transport) override; - virtual int DeRegisterExternalTransport(int channel) OVERRIDE; + int DeRegisterExternalTransport(int channel) override; - virtual int ReceivedRTPPacket(int channel, - const void* data, - unsigned int length) OVERRIDE; - virtual int ReceivedRTPPacket(int channel, - const void* data, - unsigned int length, - const PacketTime& packet_time) OVERRIDE; + int ReceivedRTPPacket(int channel, const void* data, size_t length) override; + int ReceivedRTPPacket(int channel, + const void* data, + size_t length, + const PacketTime& packet_time) override; - virtual int ReceivedRTCPPacket(int channel, - const void* data, - unsigned int length) OVERRIDE; + int ReceivedRTCPPacket(int channel, const void* data, size_t length) override; protected: VoENetworkImpl(voe::SharedData* shared); diff --git a/media/webrtc/trunk/webrtc/voice_engine/voe_rtp_rtcp_impl.cc b/media/webrtc/trunk/webrtc/voice_engine/voe_rtp_rtcp_impl.cc index 47a6a219de..422cd27f0e 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voe_rtp_rtcp_impl.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/voe_rtp_rtcp_impl.cc @@ -249,7 +249,8 @@ int VoERTP_RTCPImpl::SetRTCPStatus(int channel, bool enable) "SetRTCPStatus() failed to locate channel"); return -1; } - return channelPtr->SetRTCPStatus(enable); + channelPtr->SetRTCPStatus(enable); + return 0; } int VoERTP_RTCPImpl::GetRTCPStatus(int channel, bool& enabled) diff --git a/media/webrtc/trunk/webrtc/voice_engine/voice_engine.gyp b/media/webrtc/trunk/webrtc/voice_engine/voice_engine.gyp index 36e9b6af74..232dff127e 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voice_engine.gyp +++ b/media/webrtc/trunk/webrtc/voice_engine/voice_engine.gyp @@ -15,6 +15,7 @@ 'target_name': 'voice_engine', 'type': 'static_library', 'dependencies': [ + '<(webrtc_root)/common.gyp:webrtc_common', '<(webrtc_root)/common_audio/common_audio.gyp:common_audio', '<(webrtc_root)/modules/modules.gyp:audio_coding_module', '<(webrtc_root)/modules/modules.gyp:audio_conference_mixer', @@ -24,15 +25,12 @@ '<(webrtc_root)/modules/modules.gyp:media_file', '<(webrtc_root)/modules/modules.gyp:rtp_rtcp', '<(webrtc_root)/modules/modules.gyp:webrtc_utility', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', ], 'defines': [ 'WEBRTC_EXTERNAL_TRANSPORT', ], 'sources': [ - '../common_types.h', - '../engine_configurations.h', - '../typedefs.h', 'include/voe_audio_processing.h', 'include/voe_base.h', 'include/voe_codec.h', @@ -122,7 +120,7 @@ '<(webrtc_root)/modules/modules.gyp:media_file', '<(webrtc_root)/modules/modules.gyp:rtp_rtcp', '<(webrtc_root)/modules/modules.gyp:webrtc_utility', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', '<(webrtc_root)/test/test.gyp:test_support_main', ], 'sources': [ @@ -150,8 +148,8 @@ '<(DEPTH)/testing/gmock.gyp:gmock', '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers_default', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers_default', '<(webrtc_root)/test/test.gyp:channel_transport', '<(webrtc_root)/test/test.gyp:test_support', ], @@ -218,8 +216,8 @@ 'voice_engine', '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers_default', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers_default', '<(webrtc_root)/test/test.gyp:channel_transport', '<(webrtc_root)/test/test.gyp:test_support', ], @@ -239,7 +237,7 @@ 'type': 'executable', 'dependencies': [ 'voice_engine', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', '<(webrtc_root)/test/test.gyp:test_support', ], 'sources': [ diff --git a/media/webrtc/trunk/webrtc/voice_engine/voice_engine_impl.cc b/media/webrtc/trunk/webrtc/voice_engine/voice_engine_impl.cc index d77ffdaec5..8fa9489d35 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voice_engine_impl.cc +++ b/media/webrtc/trunk/webrtc/voice_engine/voice_engine_impl.cc @@ -154,7 +154,7 @@ bool VoiceEngine::Delete(VoiceEngine*& voiceEngine) } #if !defined(WEBRTC_CHROMIUM_BUILD) -int VoiceEngine::SetAndroidObjects(void* javaVM, void* env, void* context) +int VoiceEngine::SetAndroidObjects(void* javaVM, void* context) { #ifdef WEBRTC_ANDROID #ifdef WEBRTC_ANDROID_OPENSLES @@ -165,16 +165,20 @@ int VoiceEngine::SetAndroidObjects(void* javaVM, void* env, void* context) typedef AudioDeviceTemplate AudioDeviceInstanceJni; #endif - if (javaVM && env && context) { + if (javaVM && context) { #if !defined(WEBRTC_GONK) && defined(ANDROID) - AudioDeviceInstanceJni::SetAndroidAudioDeviceObjects(javaVM, env, context); + AudioDeviceInstanceJni::SetAndroidAudioDeviceObjects(javaVM, context); +#endif +#ifdef WEBRTC_ANDROID_OPENSLES + AudioDeviceInstance::SetAndroidAudioDeviceObjects(javaVM, context); #endif - AudioDeviceInstance::SetAndroidAudioDeviceObjects(javaVM, env, context); } else { #if !defined(WEBRTC_GONK) && defined(ANDROID) AudioDeviceInstanceJni::ClearAndroidAudioDeviceObjects(); #endif +#ifdef WEBRTC_ANDROID_OPENSLES AudioDeviceInstance::ClearAndroidAudioDeviceObjects(); +#endif } return 0; #else diff --git a/media/webrtc/trunk/webrtc/voice_engine/voice_engine_impl.h b/media/webrtc/trunk/webrtc/voice_engine/voice_engine_impl.h index 1d2b9c5efd..992bc2d83e 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voice_engine_impl.h +++ b/media/webrtc/trunk/webrtc/voice_engine/voice_engine_impl.h @@ -136,7 +136,7 @@ public: private: Atomic32 _ref_count; - scoped_ptr own_config_; + rtc::scoped_ptr own_config_; }; } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/voice_engine/voice_engine_unittests.isolate b/media/webrtc/trunk/webrtc/voice_engine/voice_engine_unittests.isolate index 4cd1f907e3..0d55515f99 100644 --- a/media/webrtc/trunk/webrtc/voice_engine/voice_engine_unittests.isolate +++ b/media/webrtc/trunk/webrtc/voice_engine/voice_engine_unittests.isolate @@ -7,14 +7,6 @@ # be found in the AUTHORS file in the root of the source tree. { 'conditions': [ - ['OS=="android"', { - 'variables': { - 'files': [ - '<(DEPTH)/data/', - '<(DEPTH)/resources/', - ], - }, - }], ['OS=="linux" or OS=="mac" or OS=="win"', { 'variables': { 'command': [ diff --git a/media/webrtc/trunk/webrtc/webrtc.gyp b/media/webrtc/trunk/webrtc/webrtc.gyp index f9ed8838f0..1ecc0cd708 100644 --- a/media/webrtc/trunk/webrtc/webrtc.gyp +++ b/media/webrtc/trunk/webrtc/webrtc.gyp @@ -28,11 +28,10 @@ 'common.gyp:*', 'common_audio/common_audio.gyp:*', 'common_video/common_video.gyp:*', - 'libjingle/xmllite/xmllite.gyp:*', - 'libjingle/xmpp/xmpp.gyp:*', 'modules/modules.gyp:*', 'p2p/p2p.gyp:*', - 'system_wrappers/source/system_wrappers.gyp:*', + 'system_wrappers/system_wrappers.gyp:*', + 'tools/tools.gyp:*', 'video_engine/video_engine.gyp:*', 'voice_engine/voice_engine.gyp:*', '<(webrtc_vp8_dir)/vp8.gyp:*', @@ -51,11 +50,10 @@ ['include_tests==1', { 'dependencies': [ 'common_video/common_video_unittests.gyp:*', - 'system_wrappers/source/system_wrappers_tests.gyp:*', + 'system_wrappers/system_wrappers_tests.gyp:*', 'test/metrics.gyp:*', 'test/test.gyp:*', 'test/webrtc_test_common.gyp:webrtc_test_common_unittests', - 'tools/tools.gyp:*', 'webrtc_tests', 'rtc_unittests', ], @@ -85,13 +83,13 @@ ], 'conditions': [ # TODO(andresp): Chromium libpeerconnection should link directly with - # this and no if conditions should be needed on webrtc build files. + # this and no if conditions should be needed on webrtc build files. ['build_with_chromium==1', { - 'dependencies': [ - '<(webrtc_root)/modules/modules.gyp:video_capture_module_impl', - '<(webrtc_root)/modules/modules.gyp:video_render_module_impl', - ], - }], + 'dependencies': [ + '<(webrtc_root)/modules/modules.gyp:video_capture', + '<(webrtc_root)/modules/modules.gyp:video_render', + ], + }], ], }, ], diff --git a/media/webrtc/trunk/webrtc/webrtc_examples.gyp b/media/webrtc/trunk/webrtc/webrtc_examples.gyp index 4d63110021..5d18aa64bf 100644 --- a/media/webrtc/trunk/webrtc/webrtc_examples.gyp +++ b/media/webrtc/trunk/webrtc/webrtc_examples.gyp @@ -16,20 +16,22 @@ 'type': 'loadable_module', 'dependencies': [ '<(DEPTH)/third_party/icu/icu.gyp:icuuc', - '<(webrtc_root)/modules/modules.gyp:video_capture_module_internal_impl', - '<(webrtc_root)/modules/modules.gyp:video_render_module_internal_impl', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers_default', + '<(webrtc_root)/common.gyp:webrtc_common', + '<(webrtc_root)/modules/modules.gyp:video_render_module_internal_impl', + '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers_default', '<(webrtc_root)/test/test.gyp:channel_transport', - '<(webrtc_root)/video_engine/video_engine.gyp:video_engine_core', '<(webrtc_root)/voice_engine/voice_engine.gyp:voice_engine', ], 'sources': [ 'examples/android/media_demo/jni/jni_helpers.cc', 'examples/android/media_demo/jni/on_load.cc', - 'examples/android/media_demo/jni/video_engine_jni.cc', 'examples/android/media_demo/jni/voice_engine_jni.cc', - 'examples/android/media_demo/jni/media_codec_video_decoder.cc', ], + 'variables': { + # This library uses native JNI exports; tell GYP so that the + # required symbols will be kept. + 'use_native_jni_exports': 1, + }, 'link_settings': { 'libraries': [ '-llog', @@ -57,8 +59,6 @@ }, 'inputs' : [ '<(PRODUCT_DIR)/lib.java/audio_device_module_java.jar', - '<(PRODUCT_DIR)/lib.java/video_capture_module_java.jar', - '<(PRODUCT_DIR)/lib.java/video_render_module_java.jar', '<(PRODUCT_DIR)/libwebrtcdemo-jni.so', ' { sendAsyncMessage("BackgroundPageThumbs:didCapture", { id: capture.id, diff --git a/toolkit/devtools/server/actors/device.js b/toolkit/devtools/server/actors/device.js index 3e50af6017..f194466124 100644 --- a/toolkit/devtools/server/actors/device.js +++ b/toolkit/devtools/server/actors/device.js @@ -10,6 +10,7 @@ const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {}); const {LongStringActor} = require("devtools/server/actors/string"); const {DebuggerServer} = require("devtools/server/main"); +Cu.importGlobalProperties(["FileReader"]); Cu.import("resource://gre/modules/PermissionsTable.jsm") const APP_MAP = { @@ -145,7 +146,6 @@ let DeviceActor = exports.DeviceActor = protocol.ActorClass({ getWallpaper: method(function() { let deferred = promise.defer(); this._getSetting("wallpaper.image").then((blob) => { - let FileReader = CC("@mozilla.org/files/filereader;1"); let reader = new FileReader(); let conn = this.conn; reader.addEventListener("load", function() { diff --git a/toolkit/devtools/server/actors/webapps.js b/toolkit/devtools/server/actors/webapps.js index c00ecb2510..44ddf976d6 100644 --- a/toolkit/devtools/server/actors/webapps.js +++ b/toolkit/devtools/server/actors/webapps.js @@ -11,6 +11,8 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/FileUtils.jsm"); +Cu.importGlobalProperties(["FileReader"]); + let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {}); let DevToolsUtils = require("devtools/toolkit/DevToolsUtils"); @@ -822,8 +824,7 @@ WebappsActor.prototype = { } // Convert the blog to a base64 encoded data URI - let reader = Cc["@mozilla.org/files/filereader;1"] - .createInstance(Ci.nsIDOMFileReader); + let reader = new FileReader(); reader.onload = function () { deferred.resolve({ url: reader.result diff --git a/toolkit/devtools/webconsole/test/common.js b/toolkit/devtools/webconsole/test/common.js index 666cedf1ce..ca349a6419 100644 --- a/toolkit/devtools/webconsole/test/common.js +++ b/toolkit/devtools/webconsole/test/common.js @@ -3,7 +3,7 @@ "use strict"; -const {classes: Cc, interfaces: Ci, utils: Cu} = Components; +var {classes: Cc, interfaces: Ci, utils: Cu} = Components; const XHTML_NS = "http://www.w3.org/1999/xhtml"; diff --git a/toolkit/modules/CharsetMenu.jsm b/toolkit/modules/CharsetMenu.jsm index 0a409cafba..e95de0cb22 100644 --- a/toolkit/modules/CharsetMenu.jsm +++ b/toolkit/modules/CharsetMenu.jsm @@ -186,12 +186,12 @@ let CharsetMenu = { }, getCharsetInfo: function(charsets, sort=true) { - let list = [{ + let list = Array.from(charsets, charset => ({ label: this._getCharsetLabel(charset), accesskey: this._getCharsetAccessKey(charset), name: "charset", value: charset - } for (charset of charsets)]; + })); if (sort) { list.sort(CharsetComparator); diff --git a/toolkit/modules/DeferredTask.jsm b/toolkit/modules/DeferredTask.jsm index 81b796da9f..9ca6508284 100644 --- a/toolkit/modules/DeferredTask.jsm +++ b/toolkit/modules/DeferredTask.jsm @@ -277,7 +277,7 @@ this.DeferredTask.prototype = { this._armed = false; this._runningPromise = runningDeferred.promise; - runningDeferred.resolve(Task.spawn(function () { + runningDeferred.resolve(Task.spawn(function* () { // Execute the provided function asynchronously. yield Task.spawn(this._taskFn).then(null, Cu.reportError); diff --git a/toolkit/modules/FileUtils.jsm b/toolkit/modules/FileUtils.jsm index b4409cb99a..df17d60a2b 100644 --- a/toolkit/modules/FileUtils.jsm +++ b/toolkit/modules/FileUtils.jsm @@ -68,7 +68,10 @@ this.FileUtils = { if (shouldCreate) { try { dir.create(Ci.nsIFile.DIRECTORY_TYPE, this.PERMS_DIRECTORY); - } catch (ex if ex.result == Cr.NS_ERROR_FILE_ALREADY_EXISTS) { + } catch (ex) { + if (ex.result != Cr.NS_ERROR_FILE_ALREADY_EXISTS) { + throw ex; + } // Ignore the exception due to a directory that already exists. } } diff --git a/toolkit/modules/Log.jsm b/toolkit/modules/Log.jsm index 80f2dac099..41059836c7 100644 --- a/toolkit/modules/Log.jsm +++ b/toolkit/modules/Log.jsm @@ -867,7 +867,7 @@ FileAppender.prototype = { __proto__: Appender.prototype, _openFile: function () { - return Task.spawn(function _openFile() { + return Task.spawn(function* _openFile() { try { this._file = yield OS.File.open(this._path, {truncate: true}); diff --git a/toolkit/modules/Promise-backend.js b/toolkit/modules/Promise-backend.js index 3d56dad2cd..41653a92af 100644 --- a/toolkit/modules/Promise-backend.js +++ b/toolkit/modules/Promise-backend.js @@ -236,8 +236,7 @@ var PendingErrors = { flush: function() { // Since we are going to modify the map while walking it, // let's copying the keys first. - let keys = [key for (key of this._map.keys())]; - for (let key of keys) { + for (let key of Array.from(this._map.keys())) { this.report(key); } }, diff --git a/toolkit/modules/PromiseUtils.jsm b/toolkit/modules/PromiseUtils.jsm index e0a09ec6f8..8ceebced32 100644 --- a/toolkit/modules/PromiseUtils.jsm +++ b/toolkit/modules/PromiseUtils.jsm @@ -50,4 +50,4 @@ function Deferred() { this.resolve = resolve; this.reject = reject; }); -} \ No newline at end of file +} diff --git a/toolkit/modules/PropertyListUtils.jsm b/toolkit/modules/PropertyListUtils.jsm index e0fade1694..4b29988137 100644 --- a/toolkit/modules/PropertyListUtils.jsm +++ b/toolkit/modules/PropertyListUtils.jsm @@ -61,7 +61,7 @@ const Cc = Components.classes; const Ci = Components.interfaces; const Cu = Components.utils; -Cu.importGlobalProperties(['File']); +Cu.importGlobalProperties(['File', 'FileReader']); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Dict", @@ -102,8 +102,7 @@ this.PropertyListUtils = Object.freeze({ file = new File(file); } - let fileReader = Cc["@mozilla.org/files/filereader;1"]. - createInstance(Ci.nsIDOMFileReader); + let fileReader = new FileReader(); let onLoadEnd = function() { let root = null; try { @@ -694,7 +693,7 @@ XMLPropertyListReader.prototype = { // Strip spaces and new lines. let base64str = aDOMElt.textContent.replace(/\s*/g, ""); let decoded = atob(base64str); - return new Uint8Array([decoded.charCodeAt(i) for (i in decoded)]); + return new Uint8Array(Array.from(decoded, c => c.charCodeAt(0))); case "dict": return this._wrapDictionary(aDOMElt); case "array": diff --git a/toolkit/modules/RemotePageManager.jsm b/toolkit/modules/RemotePageManager.jsm index 354350c23e..93a1ab78cf 100644 --- a/toolkit/modules/RemotePageManager.jsm +++ b/toolkit/modules/RemotePageManager.jsm @@ -461,7 +461,7 @@ var RemotePageManagerInternal = { // A listener is requesting the list of currently registered urls initListener: function({ target: messageManager }) { - messageManager.sendAsyncMessage("RemotePage:Register", { urls: [u for (u of this.pages.keys())] }) + messageManager.sendAsyncMessage("RemotePage:Register", { urls: Array.from(this.pages.keys()) }) }, // A remote page has been created and a port is ready in the content side diff --git a/toolkit/modules/Services.jsm b/toolkit/modules/Services.jsm index 1788b15b6e..5ed07fb2f7 100644 --- a/toolkit/modules/Services.jsm +++ b/toolkit/modules/Services.jsm @@ -23,9 +23,11 @@ XPCOMUtils.defineLazyGetter(Services, "appinfo", function () { .getService(Ci.nsIXULRuntime); try { appinfo.QueryInterface(Ci.nsIXULAppInfo); - } catch (ex if ex instanceof Components.Exception && - ex.result == Cr.NS_NOINTERFACE) { + } catch (ex) { // Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't). + if (!(ex instanceof Components.Exception) || ex.result != Cr.NS_NOINTERFACE) { + throw ex; + } } return appinfo; }); diff --git a/toolkit/modules/Sqlite.jsm b/toolkit/modules/Sqlite.jsm index 3c02acb6b4..3840c32a05 100644 --- a/toolkit/modules/Sqlite.jsm +++ b/toolkit/modules/Sqlite.jsm @@ -769,13 +769,15 @@ ConnectionData.prototype = Object.freeze({ try { onRow(row); - } catch (e if e instanceof StopIteration) { - userCancelled = true; - pending.cancel(); - break; - } catch (ex) { + } catch (e) { + if (e instanceof StopIteration) { + userCancelled = true; + pending.cancel(); + break; + } + self._log.warn("Exception when calling onRow callback: " + - CommonUtils.exceptionStr(ex)); + CommonUtils.exceptionStr(e)); } } }, @@ -811,7 +813,7 @@ ConnectionData.prototype = Object.freeze({ break; case Ci.mozIStorageStatementCallback.REASON_ERROR: - let error = new Error("Error(s) encountered during statement execution: " + [error.message for (error of errors)].join(", ")); + let error = new Error("Error(s) encountered during statement execution: " + errors.map(e => e.message).join(", ")); error.errors = errors; deferred.reject(error); break; diff --git a/toolkit/modules/Task.jsm b/toolkit/modules/Task.jsm index 1bd82a949c..98e0601b45 100644 --- a/toolkit/modules/Task.jsm +++ b/toolkit/modules/Task.jsm @@ -237,9 +237,10 @@ function createAsyncFunction(aTask) { try { // Let's call into the function ourselves. result = aTask.apply(this, arguments); - } catch (ex if ex instanceof Task.Result) { - return Promise.resolve(ex.value); } catch (ex) { + if (ex instanceof Task.Result) { + return Promise.resolve(ex.value); + } return Promise.reject(ex); } } @@ -330,16 +331,18 @@ TaskImpl.prototype = { let yielded = aSendResolved ? this._iterator.send(aSendValue) : this._iterator.throw(aSendValue); this._handleResultValue(yielded); - } catch (ex if ex instanceof Task.Result) { - // The generator function threw the special exception that allows it to - // return a specific value on resolution. - this.deferred.resolve(ex.value); - } catch (ex if ex instanceof StopIteration) { - // The generator function terminated with no specific result. - this.deferred.resolve(undefined); } catch (ex) { - // The generator function failed with an uncaught exception. - this._handleException(ex); + if (ex instanceof Task.Result) { + // The generator function threw the special exception that allows it to + // return a specific value on resolution. + this.deferred.resolve(ex.value); + } else if (ex instanceof StopIteration) { + // The generator function terminated with no specific result. + this.deferred.resolve(undefined); + } else { + // The generator function failed with an uncaught exception. + this._handleException(ex); + } } } } finally { diff --git a/toolkit/modules/ZipUtils.jsm b/toolkit/modules/ZipUtils.jsm index 4f735f89dd..decb3bc7bd 100644 --- a/toolkit/modules/ZipUtils.jsm +++ b/toolkit/modules/ZipUtils.jsm @@ -79,11 +79,11 @@ function saveStreamAsync(aPath, aStream, aFile) { input.asyncWait(readData, 0, 0, Services.tm.currentThread); }, readFailed); } - catch (e if e.result == Cr.NS_BASE_STREAM_CLOSED) { - deferred.resolve(aFile.close()); - } catch (e) { - readFailed(e); + if (e.result == Cr.NS_BASE_STREAM_CLOSED) + deferred.resolve(aFile.close()); + else + readFailed(e); } } @@ -115,7 +115,7 @@ this.ZipUtils = { return Promise.reject(e); } - return Task.spawn(function() { + return Task.spawn(function* () { // Get all of the entries in the zip and sort them so we create directories // before files let entries = zipReader.findEntries(null); diff --git a/toolkit/modules/addons/MatchPattern.jsm b/toolkit/modules/addons/MatchPattern.jsm index 91d4bf6b30..dda7fb52df 100644 --- a/toolkit/modules/addons/MatchPattern.jsm +++ b/toolkit/modules/addons/MatchPattern.jsm @@ -99,7 +99,7 @@ function MatchPattern(pat) } else if (pat instanceof String || typeof(pat) == "string") { this.matchers = [new SingleMatchPattern(pat)]; } else { - this.matchers = [for (p of pat) new SingleMatchPattern(p)]; + this.matchers = pat.map(p => new SingleMatchPattern(p)); } } diff --git a/toolkit/modules/addons/WebRequestContent.js b/toolkit/modules/addons/WebRequestContent.js index 2cd019a3bd..75221b2ede 100644 --- a/toolkit/modules/addons/WebRequestContent.js +++ b/toolkit/modules/addons/WebRequestContent.js @@ -140,7 +140,11 @@ let ContentPolicy = { try { // If e10s is disabled, this throws NS_NOINTERFACE for closed tabs. mm = ir.getInterface(Ci.nsIContentFrameMessageManager); - } catch (e if e.result == Cr.NS_NOINTERFACE) {} + } catch (e) { + if (e.result != Cr.NS_NOINTERFACE) { + throw e; + } + } } let data = {ids, diff --git a/toolkit/modules/tests/xpcshell/test_DeferredTask.js b/toolkit/modules/tests/xpcshell/test_DeferredTask.js index 606d9cbe19..41dbcefb0c 100644 --- a/toolkit/modules/tests/xpcshell/test_DeferredTask.js +++ b/toolkit/modules/tests/xpcshell/test_DeferredTask.js @@ -156,7 +156,7 @@ add_test(function test_arm_async() let finishedExecutionAgain = false; // Create a task that will run later. - let deferredTask = new DeferredTask(function () { + let deferredTask = new DeferredTask(function* () { yield promiseTimeout(4*T); if (!finishedExecution) { finishedExecution = true; @@ -247,7 +247,7 @@ add_test(function test_disarm_async() { let finishedExecution = false; - let deferredTask = new DeferredTask(function () { + let deferredTask = new DeferredTask(function* () { deferredTask.arm(); yield promiseTimeout(2*T); finishedExecution = true; @@ -277,7 +277,7 @@ add_test(function test_disarm_immediate_async() { let executed = false; - let deferredTask = new DeferredTask(function () { + let deferredTask = new DeferredTask(function* () { do_check_false(executed); executed = true; yield promiseTimeout(2*T); @@ -353,7 +353,7 @@ add_test(function test_finalize_executes_entirely() let executedAgain = false; let timePassed = false; - let deferredTask = new DeferredTask(function () { + let deferredTask = new DeferredTask(function* () { // The first time, we arm the timer again and set up the finalization. if (!executed) { deferredTask.arm(); diff --git a/toolkit/modules/tests/xpcshell/test_Log.js b/toolkit/modules/tests/xpcshell/test_Log.js index 0fcfe40520..a0fb975997 100644 --- a/toolkit/modules/tests/xpcshell/test_Log.js +++ b/toolkit/modules/tests/xpcshell/test_Log.js @@ -233,7 +233,7 @@ function fileContents(path) { }); } -add_task(function test_FileAppender() { +add_task(function* test_FileAppender() { // This directory does not exist yet let dir = OS.Path.join(do_get_profile().path, "test_Log"); do_check_false(yield OS.File.exists(dir)); @@ -287,7 +287,7 @@ add_task(function test_FileAppender() { "test.FileAppender\tINFO\t5\n"); }); -add_task(function test_BoundedFileAppender() { +add_task(function* test_BoundedFileAppender() { let dir = OS.Path.join(do_get_profile().path, "test_Log"); if (!(yield OS.File.exists(dir))) { @@ -338,7 +338,7 @@ add_task(function test_BoundedFileAppender() { /* * Test parameter formatting. */ -add_task(function log_message_with_params() { +add_task(function* log_message_with_params() { let formatter = new Log.BasicFormatter(); function formatMessage(text, params) { @@ -487,7 +487,7 @@ add_task(function log_message_with_params() { * with the object argument as parameters. This makes the log useful when the * caller does "catch(err) {logger.error(err)}" */ -add_task(function test_log_err_only() { +add_task(function* test_log_err_only() { let log = Log.repository.getLogger("error.only"); let testFormatter = { format: msg => msg }; let appender = new MockAppender(testFormatter); @@ -513,7 +513,7 @@ add_task(function test_log_err_only() { /* * Test logStructured() messages through basic formatter. */ -add_task(function test_structured_basic() { +add_task(function* test_structured_basic() { let log = Log.repository.getLogger("test.logger"); let appender = new MockAppender(new Log.BasicFormatter()); @@ -538,7 +538,7 @@ add_task(function test_structured_basic() { /* * Test that all the basic logger methods pass the message and params through to the appender. */ -add_task(function log_message_with_params() { +add_task(function* log_message_with_params() { let log = Log.repository.getLogger("error.logger"); let testFormatter = { format: msg => msg }; let appender = new MockAppender(testFormatter); @@ -562,7 +562,7 @@ add_task(function log_message_with_params() { /* * Check that we format JS Errors reasonably. */ -add_task(function format_errors() { +add_task(function* format_errors() { let pFormat = new Log.ParameterFormatter(); // Test that subclasses of Error are recognized as errors. diff --git a/toolkit/modules/tests/xpcshell/test_NewTabUtils.js b/toolkit/modules/tests/xpcshell/test_NewTabUtils.js index e9bed568ac..f6a383a415 100644 --- a/toolkit/modules/tests/xpcshell/test_NewTabUtils.js +++ b/toolkit/modules/tests/xpcshell/test_NewTabUtils.js @@ -11,7 +11,7 @@ function run_test() { run_next_test(); } -add_task(function isTopSiteGivenProvider() { +add_task(function* isTopSiteGivenProvider() { let expectedLinks = makeLinks(0, 10, 2); // The lowest 2 frecencies have the same base domain. @@ -50,7 +50,7 @@ add_task(function isTopSiteGivenProvider() { NewTabUtils.links.removeProvider(provider); }); -add_task(function multipleProviders() { +add_task(function* multipleProviders() { // Make each provider generate NewTabUtils.links.maxNumLinks links to check // that no more than maxNumLinks are actually returned in the merged list. let evenLinks = makeLinks(0, 2 * NewTabUtils.links.maxNumLinks, 2); @@ -76,7 +76,7 @@ add_task(function multipleProviders() { NewTabUtils.links.removeProvider(oddProvider); }); -add_task(function changeLinks() { +add_task(function* changeLinks() { let expectedLinks = makeLinks(0, 20, 2); let provider = new TestProvider(done => done(expectedLinks)); @@ -131,7 +131,7 @@ add_task(function changeLinks() { NewTabUtils.links.removeProvider(provider); }); -add_task(function oneProviderAlreadyCached() { +add_task(function* oneProviderAlreadyCached() { let links1 = makeLinks(0, 10, 1); let provider1 = new TestProvider(done => done(links1)); @@ -153,7 +153,7 @@ add_task(function oneProviderAlreadyCached() { NewTabUtils.links.removeProvider(provider2); }); -add_task(function newLowRankedLink() { +add_task(function* newLowRankedLink() { // Init a provider with 10 links and make its maximum number also 10. let links = makeLinks(0, 10, 1); let provider = new TestProvider(done => done(links)); @@ -181,7 +181,7 @@ add_task(function newLowRankedLink() { NewTabUtils.links.removeProvider(provider); }); -add_task(function extractSite() { +add_task(function* extractSite() { // All these should extract to the same site [ "mozilla.org", "m.mozilla.org", diff --git a/toolkit/modules/tests/xpcshell/test_PromiseUtils.js b/toolkit/modules/tests/xpcshell/test_PromiseUtils.js index 8953d2d501..ff9ba3688b 100644 --- a/toolkit/modules/tests/xpcshell/test_PromiseUtils.js +++ b/toolkit/modules/tests/xpcshell/test_PromiseUtils.js @@ -102,4 +102,4 @@ add_task(function* test_reject_resolved_promise() { let p = new Promise((resolve, reject) => reject(new Error("This on rejects"))); def.reject(p); yield Assert.rejects(def.promise, Promise, "Rejection with a rejected promise uses the passed promise itself as the reason of rejection"); -}); \ No newline at end of file +}); diff --git a/toolkit/modules/tests/xpcshell/test_ZipUtils.js b/toolkit/modules/tests/xpcshell/test_ZipUtils.js index 35f882a643..dbd938b1dc 100644 --- a/toolkit/modules/tests/xpcshell/test_ZipUtils.js +++ b/toolkit/modules/tests/xpcshell/test_ZipUtils.js @@ -45,7 +45,7 @@ add_task(function test_extractFiles() { ensureExtracted(target); }); -add_task(function test_extractFilesAsync() { +add_task(function* test_extractFilesAsync() { let target = dir.clone(); target.append("test_extractFilesAsync"); target.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, diff --git a/toolkit/modules/tests/xpcshell/test_sqlite.js b/toolkit/modules/tests/xpcshell/test_sqlite.js index dff42f5cf1..9c5f3c15ca 100644 --- a/toolkit/modules/tests/xpcshell/test_sqlite.js +++ b/toolkit/modules/tests/xpcshell/test_sqlite.js @@ -126,7 +126,9 @@ add_task(function* test_schema_version() { yield db.setSchemaVersion(v); do_print("Schema version " + v + " should have been rejected"); success = false; - } catch (ex if ex.message.startsWith("Schema version must be an integer.")) { + } catch (ex) { + if (!ex.message.startsWith("Schema version must be an integer.")) + throw ex; success = true; } do_check_true(success); @@ -918,7 +920,11 @@ add_task(function* test_cloneStorageConnection() { try { let clone = yield Sqlite.cloneStorageConnection({ connection: null }); do_throw(new Error("Should throw on invalid connection")); - } catch (ex if ex.name == "TypeError") {} + } catch (ex) { + if (ex.name != "TypeError") { + throw ex; + } + } }); // Test clone() method. diff --git a/toolkit/modules/tests/xpcshell/test_sqlite_shutdown.js b/toolkit/modules/tests/xpcshell/test_sqlite_shutdown.js index 3c6634eb2d..2c3a0cf5bb 100644 --- a/toolkit/modules/tests/xpcshell/test_sqlite_shutdown.js +++ b/toolkit/modules/tests/xpcshell/test_sqlite_shutdown.js @@ -25,7 +25,7 @@ function getConnection(dbName, extraOptions={}) { return Sqlite.openConnection(options); } -function getDummyDatabase(name, extraOptions={}) { +function* getDummyDatabase(name, extraOptions={}) { const TABLES = { dirs: "id INTEGER PRIMARY KEY AUTOINCREMENT, path TEXT", files: "id INTEGER PRIMARY KEY AUTOINCREMENT, dir_id INTEGER, path TEXT", @@ -39,7 +39,7 @@ function getDummyDatabase(name, extraOptions={}) { c._initialStatementCount++; } - throw new Task.Result(c); + return c; } function sleep(ms) { diff --git a/toolkit/mozapps/extensions/content/selectAddons.js b/toolkit/mozapps/extensions/content/selectAddons.js index 33ab8a84e0..82edbc419b 100644 --- a/toolkit/mozapps/extensions/content/selectAddons.js +++ b/toolkit/mozapps/extensions/content/selectAddons.js @@ -123,7 +123,7 @@ var gChecking = { if (this._completeCount < this._addonCount) return; - var addons = [gAddons[id] for (id in gAddons)]; + let addons = Object.values(gAddons); addons.sort(function sortAddons(a, b) { let orderA = orderForScope(a.addon.scope); diff --git a/toolkit/mozapps/extensions/content/update.js b/toolkit/mozapps/extensions/content/update.js index 4e44b4f5ed..72530cfdf2 100644 --- a/toolkit/mozapps/extensions/content/update.js +++ b/toolkit/mozapps/extensions/content/update.js @@ -131,7 +131,8 @@ var gUpdateWizard = { if (gMismatchPage.waiting) { logger.info("Dialog closed in mismatch page"); if (gUpdateWizard.addonInstalls.size > 0) { - gInstallingPage.startInstalls([i for ([, i] of gUpdateWizard.addonInstalls)]); + gInstallingPage.startInstalls( + Array.from(gUpdateWizard.addonInstalls.values())); } return true; } @@ -195,8 +196,10 @@ var gVersionInfoPage = { logger.debug("repopulateCache completed after dialog closed"); } } - // Fetch the add-ons that are still affected by this update. - let idlist = [id for (id of gUpdateWizard.affectedAddonIDs)]; + // Fetch the add-ons that are still affected by this update, + // excluding the hotfix add-on. + let idlist = Array.from(gUpdateWizard.affectedAddonIDs).filter( + a => a.id != AddonManager.hotfixID); if (idlist.length < 1) { gVersionInfoPage.onAllUpdatesFinished(); return; @@ -206,7 +209,7 @@ var gVersionInfoPage = { let fetchedAddons = yield new Promise((resolve, reject) => AddonManager.getAddonsByIDs(idlist, resolve)); // We shouldn't get nulls here, but let's be paranoid... - gUpdateWizard.addons = [a for (a of fetchedAddons) if (a)]; + gUpdateWizard.addons = fetchedAddons.filter(a => a); if (gUpdateWizard.addons.length < 1) { gVersionInfoPage.onAllUpdatesFinished(); return; @@ -234,8 +237,8 @@ var gVersionInfoPage = { AddonManagerPrivate.recordSimpleMeasure("appUpdate_upgradeFailed", 0); AddonManagerPrivate.recordSimpleMeasure("appUpdate_upgradeDeclined", 0); // Filter out any add-ons that are now enabled. - logger.debug("VersionInfo updates finished: found " + - [addon.id + ":" + addon.appDisabled for (addon of gUpdateWizard.addons)].toSource()); + let addonList = gUpdateWizard.addons.map(a => a.id + ":" + a.appDisabled); + logger.debug("VersionInfo updates finished: found " + addonList.toSource()); let filteredAddons = []; for (let a of gUpdateWizard.addons) { if (a.appDisabled) { @@ -252,7 +255,8 @@ var gVersionInfoPage = { if (gUpdateWizard.shuttingDown) { // jump directly to updating auto-update add-ons in the background if (gUpdateWizard.addonInstalls.size > 0) { - gInstallingPage.startInstalls([i for ([, i] of gUpdateWizard.addonInstalls)]); + let installs = Array.from(gUpdateWizard.addonInstalls.values()); + gInstallingPage.startInstalls(installs); } return; } @@ -478,8 +482,8 @@ var gInstallingPage = { return; } - logger.debug("Start installs for " - + [i.existingAddon.id for (i of aInstallList)].toSource()); + let installs = Array.from(aInstallList).map(a => a.existingAddon.id); + logger.debug("Start installs for " + installs.toSource()); this._errors = []; this._installs = aInstallList; this._installing = true; diff --git a/toolkit/mozapps/extensions/internal/AddonRepository.jsm b/toolkit/mozapps/extensions/internal/AddonRepository.jsm index 14e8d04cc1..1d12b4b80d 100644 --- a/toolkit/mozapps/extensions/internal/AddonRepository.jsm +++ b/toolkit/mozapps/extensions/internal/AddonRepository.jsm @@ -631,7 +631,7 @@ this.AddonRepository = { return this._clearCache(); } - let ids = [a.id for (a of allAddons)]; + let ids = allAddons.map(a => a.id); logger.debug("Repopulate add-on cache with " + ids.toSource()); let self = this; @@ -1618,34 +1618,34 @@ var AddonDatabase = { schema < DB_MIN_JSON_SCHEMA) { throw new Error("Invalid schema value."); } - } catch (e if e instanceof OS.File.Error && e.becauseNoSuchFile) { - logger.debug("No " + FILE_DATABASE + " found."); + } catch (e) { + if (e instanceof OS.File.Error && e.becauseNoSuchFile) { + logger.debug("No " + FILE_DATABASE + " found."); - // Create a blank addons.json file - this._saveDBToDisk(); + // Create a blank addons.json file + this._saveDBToDisk(); - let dbSchema = 0; - try { - dbSchema = Services.prefs.getIntPref(PREF_GETADDONS_DB_SCHEMA); - } catch (e) {} + let dbSchema = 0; + try { + dbSchema = Services.prefs.getIntPref(PREF_GETADDONS_DB_SCHEMA); + } catch (e) {} - if (dbSchema < DB_MIN_JSON_SCHEMA) { - let results = yield new Promise((resolve, reject) => { - AddonRepository_SQLiteMigrator.migrate(resolve); - }); + if (dbSchema < DB_MIN_JSON_SCHEMA) { + let results = yield new Promise((resolve, reject) => { + AddonRepository_SQLiteMigrator.migrate(resolve); + }); + + if (results.length) { + yield this._insertAddons(results); + } - if (results.length) { - yield this._insertAddons(results); } Services.prefs.setIntPref(PREF_GETADDONS_DB_SCHEMA, DB_SCHEMA); + } else { + logger.error("Malformed " + FILE_DATABASE + ": " + e); + this.databaseOk = false; } - - return this.DB; - } catch (e) { - logger.error("Malformed " + FILE_DATABASE + ": " + e); - this.databaseOk = false; - return this.DB; } diff --git a/toolkit/mozapps/extensions/internal/AddonRepository_SQLiteMigrator.jsm b/toolkit/mozapps/extensions/internal/AddonRepository_SQLiteMigrator.jsm index b98963033f..59035223a0 100644 --- a/toolkit/mozapps/extensions/internal/AddonRepository_SQLiteMigrator.jsm +++ b/toolkit/mozapps/extensions/internal/AddonRepository_SQLiteMigrator.jsm @@ -60,7 +60,7 @@ this.AddonRepository_SQLiteMigrator = { this._retrieveStoredData((results) => { this._closeConnection(); - let resultArray = [addon for ([,addon] of Iterator(results))]; + let resultArray = Object.values(results); logger.debug(resultArray.length + " addons imported.") aCallback(resultArray); }); diff --git a/toolkit/mozapps/extensions/internal/AddonUpdateChecker.jsm b/toolkit/mozapps/extensions/internal/AddonUpdateChecker.jsm index 6bae768eec..74d9231925 100644 --- a/toolkit/mozapps/extensions/internal/AddonUpdateChecker.jsm +++ b/toolkit/mozapps/extensions/internal/AddonUpdateChecker.jsm @@ -651,7 +651,9 @@ UpdateParser.prototype = { let json = JSON.parse(request.responseText); parser = () => parseJSONManifest(this.id, this.updateKey, request, json); - } catch (e if e instanceof SyntaxError) { + } catch (e) { + if (!(e instanceof SyntaxError)) + throw e; let domParser = Cc["@mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser); let xml = domParser.parseFromString(request.responseText, "text/xml"); diff --git a/toolkit/mozapps/extensions/internal/GMPProvider.jsm b/toolkit/mozapps/extensions/internal/GMPProvider.jsm index d20ca7977f..bc17d514c9 100644 --- a/toolkit/mozapps/extensions/internal/GMPProvider.jsm +++ b/toolkit/mozapps/extensions/internal/GMPProvider.jsm @@ -555,7 +555,9 @@ var GMPProvider = { this._log.info("startup - adding gmp directory " + gmpPath); try { gmpService.addPluginDirectory(gmpPath); - } catch (e if e.name == 'NS_ERROR_NOT_AVAILABLE') { + } catch (e) { + if (e.name != 'NS_ERROR_NOT_AVAILABLE') + throw e; this._log.warn("startup - adding gmp directory failed with " + e.name + " - sandboxing not available?", e); } @@ -636,8 +638,10 @@ var GMPProvider = { return; } - let results = [p.wrapper for ([id, p] of this._plugins) - if (!GMPUtils.isPluginHidden(p))]; + let results = Array.from(this._plugins.values()) + .filter(p => !GMPUtils.isPluginHidden(p)) + .map(p => p.wrapper); + aCallback(results); }, diff --git a/toolkit/mozapps/extensions/internal/PluginProvider.jsm b/toolkit/mozapps/extensions/internal/PluginProvider.jsm index 7f58ceb136..86d74fda2f 100644 --- a/toolkit/mozapps/extensions/internal/PluginProvider.jsm +++ b/toolkit/mozapps/extensions/internal/PluginProvider.jsm @@ -39,7 +39,8 @@ function getIDHashForString(aStr) { // convert the binary hash data to a hex string. let binary = hasher.finish(false); - let hash = [toHexString(binary.charCodeAt(i)) for (i in binary)].join("").toLowerCase(); + let hash = Array.from(binary, c => toHexString(c.charCodeAt(0))); + hash = hash.join("").toLowerCase(); return "{" + hash.substr(0, 8) + "-" + hash.substr(8, 4) + "-" + hash.substr(12, 4) + "-" + @@ -464,7 +465,9 @@ function PluginWrapper(aId, aName, aDescription, aTags) { dir = Services.dirsvc.get("Home", Ci.nsIFile); if (path.startsWith(dir.path)) return AddonManager.SCOPE_USER; - } catch (e if (e.result && e.result == Components.results.NS_ERROR_FAILURE)) { + } catch (e) { + if (!e.result || e.result != Components.results.NS_ERROR_FAILURE) + throw e; // Do nothing: missing "Home". } diff --git a/toolkit/mozapps/extensions/internal/XPIProvider.jsm b/toolkit/mozapps/extensions/internal/XPIProvider.jsm index 90ef847c86..3d5541c083 100644 --- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm +++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm @@ -1323,7 +1323,7 @@ function escapeAddonURI(aAddon, aUri, aUpdateType, aAppVersion) } function removeAsync(aFile) { - return Task.spawn(function () { + return Task.spawn(function*() { let info = null; try { info = yield OS.File.stat(aFile.path); @@ -1332,7 +1332,9 @@ function removeAsync(aFile) { else yield OS.File.remove(aFile.path); } - catch (e if e instanceof OS.File.Error && e.becauseNoSuchFile) { + catch (e) { + if (!(e instanceof OS.File.Error) || ! e.becauseNoSuchFile) + throw e; // The file has already gone away return; } @@ -2559,7 +2561,9 @@ this.XPIProvider = { try { isDir = stageDirEntry.isDirectory(); } - catch (e if e.result == Cr.NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) { + catch (e) { + if (e.result != Cr.NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) + throw e; // If the file has already gone away then don't worry about it, this // can happen on OSX where the resource fork is automatically moved // with the data fork for the file. See bug 733436. @@ -3608,8 +3612,8 @@ this.XPIProvider = { // XXX This will go away when we fold bootstrappedAddons into XPIStates. if (updateReasons.length == 0) { - let bootstrapDescriptors = new Set([for (b of Object.keys(this.bootstrappedAddons)) - this.bootstrappedAddons[b].descriptor]); + let bootstrapDescriptors = new Set(Object.keys(this.bootstrappedAddons) + .map(b => this.bootstrappedAddons[b].descriptor)); for (let location of XPIStates.db.values()) { for (let state of location.values()) { @@ -3619,7 +3623,7 @@ this.XPIProvider = { if (bootstrapDescriptors.size > 0) { logger.warn("Bootstrap state is invalid (missing add-ons: " - + [for (b of bootstrapDescriptors) b] + ")"); + + Array.from(bootstrapDescriptors).join(", ") + ")"); updateReasons.push("missingBootstrapAddon"); } } @@ -4818,7 +4822,8 @@ function getHashStringForCrypto(aCrypto) { // convert the binary hash data to a hex string. let binary = aCrypto.finish(false); - return [toHexString(binary.charCodeAt(i)) for (i in binary)].join("").toLowerCase() + let hash = Array.from(binary, c => toHexString(c.charCodeAt(0))) + return hash.join("").toLowerCase(); } /** @@ -5779,7 +5784,7 @@ AddonInstall.prototype = { let stagingDir = this.installLocation.getStagingDir(); let stagedAddon = stagingDir.clone(); - Task.spawn((function() { + Task.spawn((function*() { let installedUnpacked = 0; yield this.installLocation.requestStagingDir(); diff --git a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js index d4798b726c..2e0f9275bc 100644 --- a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js +++ b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js @@ -200,7 +200,7 @@ function asyncMap(aObjects, aMethod, aCallback) { * @param aStatement * The statement to execute */ -function resultRows(aStatement) { +function* resultRows(aStatement) { try { while (stepStatement(aStatement)) yield aStatement.row; @@ -390,7 +390,7 @@ function _findAddon(addonDB, aFilter) { * Internal interface to get a filtered list of addons from a loaded addonDB */ function _filterDB(addonDB, aFilter) { - return [for (addon of addonDB.values()) if (aFilter(addon)) addon]; + return Array.from(addonDB.values()).filter(aFilter); } this.XPIDatabase = { @@ -918,7 +918,7 @@ this.XPIDatabase = { let reqCount = 0; let props = []; - for (let row in resultRows(stmt)) { + for (let row of resultRows(stmt)) { if (REQUIRED.indexOf(row.name) != -1) { reqCount++; props.push(row.name); @@ -938,7 +938,7 @@ this.XPIDatabase = { stmt.finalize(); stmt = aConnection.createStatement("SELECT " + props.join(",") + " FROM addon"); - for (let row in resultRows(stmt)) { + for (let row of resultRows(stmt)) { if (!(row.location in migrateData)) migrateData[row.location] = {}; let addonData = { @@ -965,7 +965,7 @@ this.XPIDatabase = { for (let id in migrateData[location]) { taStmt.params.internal_id = migrateData[location][id].internal_id; delete migrateData[location][id].internal_id; - for (let row in resultRows(taStmt)) { + for (let row of resultRows(taStmt)) { migrateData[location][id].targetApplications.push({ id: row.id, minVersion: row.minVersion, diff --git a/toolkit/mozapps/extensions/nsBlocklistService.js b/toolkit/mozapps/extensions/nsBlocklistService.js index b05e1d59d8..7863bbdcbd 100644 --- a/toolkit/mozapps/extensions/nsBlocklistService.js +++ b/toolkit/mozapps/extensions/nsBlocklistService.js @@ -95,9 +95,11 @@ XPCOMUtils.defineLazyGetter(this, "gApp", function bls_gApp() { .getService(Ci.nsIXULRuntime); try { appinfo.QueryInterface(Ci.nsIXULAppInfo); - } catch (ex if ex instanceof Components.Exception && - ex.result == Cr.NS_NOINTERFACE) { + } catch (ex) { // Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't). + if (!(ex instanceof Components.Exception) || + ex.result != Cr.NS_NOINTERFACE) + throw ex; } return appinfo; }); diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug580298.js b/toolkit/mozapps/extensions/test/browser/browser_bug580298.js index 77b386c28a..2242460d86 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug580298.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug580298.js @@ -9,7 +9,7 @@ var gManagerWindow; var gCategoryUtilities; var gProvider; -add_task(function test() { +add_task(function* test() { gProvider = new MockProvider(); gProvider.createAddons([{ diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug596336.js b/toolkit/mozapps/extensions/test/browser/browser_bug596336.js index 00b7e6619b..6c9e5bb81b 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug596336.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug596336.js @@ -41,7 +41,7 @@ function install_addon(aXpi) { }); } -let check_addon = Task.async(function*(aAddon, aVersion) { +var check_addon = Task.async(function*(aAddon, aVersion) { is(get_list_item_count(), 1, "Should be one item in the list"); is(aAddon.version, aVersion, "Add-on should have the right version"); @@ -51,98 +51,82 @@ let check_addon = Task.async(function*(aAddon, aVersion) { // Force XBL to apply item.clientTop; - is(get_node(item, "version").value, version, "Version should be correct"); + let { version } = yield get_tooltip_info(item); + is(version, aVersion, "Version should be correct"); if (aAddon.userDisabled) is_element_visible(get_class_node(item, "disabled-postfix"), "Disabled postfix should be hidden"); else is_element_hidden(get_class_node(item, "disabled-postfix"), "Disabled postfix should be hidden"); -} +}); // Install version 1 then upgrade to version 2 with the manager open -add_test(function() { - install_addon("browser_bug596336_1", function() { - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { - check_addon(aAddon, "1.0"); - ok(!aAddon.userDisabled, "Add-on should not be disabled"); +add_task(function*() { + yield install_addon("browser_bug596336_1"); + let [aAddon] = yield promiseAddonsByIDs(["addon1@tests.mozilla.org"]); + yield check_addon(aAddon, "1.0"); + ok(!aAddon.userDisabled, "Add-on should not be disabled"); - install_addon("browser_bug596336_2", function() { - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { - check_addon(aAddon, "2.0"); - ok(!aAddon.userDisabled, "Add-on should not be disabled"); + yield install_addon("browser_bug596336_2"); + [aAddon] = yield promiseAddonsByIDs(["addon1@tests.mozilla.org"]); + yield check_addon(aAddon, "2.0"); + ok(!aAddon.userDisabled, "Add-on should not be disabled"); - aAddon.uninstall(); + aAddon.uninstall(); - is(get_list_item_count(), 0, "Should be no items in the list"); - - run_next_test(); - }); - }); - }); - }); + is(get_list_item_count(), 0, "Should be no items in the list"); }); // Install version 1 mark it as disabled then upgrade to version 2 with the // manager open -add_test(function() { - install_addon("browser_bug596336_1", function() { - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { - aAddon.userDisabled = true; - check_addon(aAddon, "1.0"); - ok(aAddon.userDisabled, "Add-on should be disabled"); +add_task(function*() { + yield install_addon("browser_bug596336_1"); + let [aAddon] = yield promiseAddonsByIDs(["addon1@tests.mozilla.org"]); + aAddon.userDisabled = true; + yield check_addon(aAddon, "1.0"); + ok(aAddon.userDisabled, "Add-on should be disabled"); - install_addon("browser_bug596336_2", function() { - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { - check_addon(aAddon, "2.0"); - ok(aAddon.userDisabled, "Add-on should be disabled"); + yield install_addon("browser_bug596336_2"); + [aAddon] = yield promiseAddonsByIDs(["addon1@tests.mozilla.org"]); + yield check_addon(aAddon, "2.0"); + ok(aAddon.userDisabled, "Add-on should be disabled"); - aAddon.uninstall(); + aAddon.uninstall(); - is(get_list_item_count(), 0, "Should be no items in the list"); - - run_next_test(); - }); - }); - }); - }); + is(get_list_item_count(), 0, "Should be no items in the list"); }); // Install version 1 click the remove button and then upgrade to version 2 with // the manager open -add_test(function() { - install_addon("browser_bug596336_1", function() { - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { - check_addon(aAddon, "1.0"); - ok(!aAddon.userDisabled, "Add-on should not be disabled"); +add_task(function*() { + yield install_addon("browser_bug596336_1"); + let [aAddon] = yield promiseAddonsByIDs(["addon1@tests.mozilla.org"]); + yield check_addon(aAddon, "1.0"); + ok(!aAddon.userDisabled, "Add-on should not be disabled"); - let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); - EventUtils.synthesizeMouseAtCenter(get_node(item, "remove-btn"), { }, gManagerWindow); + let item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org"); + EventUtils.synthesizeMouseAtCenter(get_node(item, "remove-btn"), { }, gManagerWindow); - // Force XBL to apply - item.clientTop; + // Force XBL to apply + item.clientTop; - ok(!!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should be pending uninstall"); - is_element_visible(get_class_node(item, "pending"), "Pending message should be visible"); + ok(aAddon.userDisabled, "Add-on should be disabled"); + ok(!aAddon.pendingUninstall, "Add-on should not be pending uninstall"); + is_element_visible(get_class_node(item, "pending"), "Pending message should be visible"); - install_addon("browser_bug596336_2", function() { - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) { - check_addon(aAddon, "2.0"); - ok(!aAddon.userDisabled, "Add-on should not be disabled"); + yield install_addon("browser_bug596336_2"); + [aAddon] = yield promiseAddonsByIDs(["addon1@tests.mozilla.org"]); + yield check_addon(aAddon, "2.0"); + ok(!aAddon.userDisabled, "Add-on should not be disabled"); - aAddon.uninstall(); + aAddon.uninstall(); - is(get_list_item_count(), 0, "Should be no items in the list"); - - run_next_test(); - }); - }); - }); - }); + is(get_list_item_count(), 0, "Should be no items in the list"); }); // Install version 1, disable it, click the remove button and then upgrade to // version 2 with the manager open -add_task(function() { +add_task(function*() { yield install_addon("browser_bug596336_1"); let [aAddon] = yield promiseAddonsByIDs(["addon1@tests.mozilla.org"]); aAddon.userDisabled = true; diff --git a/toolkit/mozapps/extensions/test/browser/browser_cancelCompatCheck.js b/toolkit/mozapps/extensions/test/browser/browser_cancelCompatCheck.js index 1799adcdda..f4ea898945 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_cancelCompatCheck.js +++ b/toolkit/mozapps/extensions/test/browser/browser_cancelCompatCheck.js @@ -220,7 +220,7 @@ let inactiveAddonIds = [ // Make sure the addons in the list are not installed function* check_addons_uninstalled(aAddonList) { - let foundList = yield promise_addons_by_ids([addon.id for (addon of aAddonList)]); + let foundList = yield promise_addons_by_ids(aAddonList.map(a => a.id)); for (let i = 0; i < aAddonList.length; i++) { ok(!foundList[i], "Addon " + aAddonList[i].id + " is not installed"); } @@ -232,7 +232,7 @@ function* check_addons_uninstalled(aAddonList) { // Add-ons that have updates available should not update if they were disabled before // For this test, addon8 became disabled during update and addon9 was previously disabled, // so addon8 should update and addon9 should not -add_task(function cancel_during_repopulate() { +add_task(function* cancel_during_repopulate() { let a5, a8, a9, a10; Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); @@ -297,7 +297,7 @@ add_task(function cancel_during_repopulate() { // calls in gVersionInfoPage_onPageShow() to complete // For this test, both addon8 and addon9 were disabled by this update, but addon8 // is set to not auto-update, so only addon9 should update in the background -add_task(function cancel_during_findUpdates() { +add_task(function* cancel_during_findUpdates() { let a5, a8, a9; Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); @@ -357,7 +357,7 @@ add_task(function cancel_during_findUpdates() { // to continue updating in the background and cancels any other updates // Same conditions as the previous test - addon8 and addon9 have updates available, // addon8 is set to not auto-update so only addon9 should become compatible -add_task(function cancel_mismatch() { +add_task(function* cancel_mismatch() { let a3, a5, a7, a8, a9; Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); @@ -416,7 +416,7 @@ add_task(function cancel_mismatch() { // Cancelling during the 'mismatch' screen with only add-ons that have // no updates available -add_task(function cancel_mismatch_no_updates() { +add_task(function* cancel_mismatch_no_updates() { let a3, a5, a6 Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true); diff --git a/toolkit/mozapps/extensions/test/browser/browser_experiments.js b/toolkit/mozapps/extensions/test/browser/browser_experiments.js index 3da5fd423f..b973f0b12a 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_experiments.js +++ b/toolkit/mozapps/extensions/test/browser/browser_experiments.js @@ -331,7 +331,7 @@ add_task(function* testActivateExperiment() { is_element_visible(el, "Experiment info is visible on experiment tab."); }); -add_task(function testDeactivateExperiment() { +add_task(function* testDeactivateExperiment() { if (!gExperiments) { return; } @@ -379,7 +379,7 @@ add_task(function testDeactivateExperiment() { is_element_hidden(el, "Preferences button is not visible."); }); -add_task(function testActivateRealExperiments() { +add_task(function* testActivateRealExperiments() { if (!gExperiments) { info("Skipping experiments test because that feature isn't available."); return; @@ -532,7 +532,7 @@ add_task(function testActivateRealExperiments() { } }); -add_task(function testDetailView() { +add_task(function* testDetailView() { if (!gExperiments) { info("Skipping experiments test because that feature isn't available."); return; diff --git a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js index 0ea7b1cd5a..0329a0dcc2 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js +++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js @@ -194,7 +194,8 @@ function do_get_file_hash(aFile, aAlgorithm) { let toHexString = charCode => ("0" + charCode.toString(16)).slice(-2); let binary = crypto.finish(false); - return aAlgorithm + ":" + [toHexString(binary.charCodeAt(i)) for (i in binary)].join("") + let hash = Array.from(binary, c => toHexString(c.charCodeAt(0))); + return aAlgorithm + ":" + hash.join(""); } /** @@ -876,7 +877,9 @@ function promiseSetExtensionModifiedTime(aPath, aTime) { try { let iterator = new OS.File.DirectoryIterator(aPath); entries = yield iterator.nextBatch(); - } catch (ex if ex instanceof OS.File.Error) { + } catch (ex) { + if (!(ex instanceof OS.File.Error)) + throw ex; return; } finally { if (iterator) { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_DeferredSave.js b/toolkit/mozapps/extensions/test/xpcshell/test_DeferredSave.js index 7599c8b808..ed92afc3b3 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_DeferredSave.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_DeferredSave.js @@ -147,7 +147,7 @@ function run_test() { } // Modify set data once, ask for save, make sure it saves cleanly -add_task(function test_basic_save_succeeds() { +add_task(function* test_basic_save_succeeds() { setQuickMockTimer(); let tester = DeferredSaveTester(); let data = "Test 1 Data"; @@ -159,7 +159,7 @@ add_task(function test_basic_save_succeeds() { // Two saves called during the same event loop, both with callbacks // Make sure we save only the second version of the data -add_task(function test_two_saves() { +add_task(function* test_two_saves() { setQuickMockTimer(); let tester = DeferredSaveTester(); let firstCallback_happened = false; @@ -182,7 +182,7 @@ add_task(function test_two_saves() { // Two saves called with a delay in between, both with callbacks // Make sure we save the second version of the data -add_task(function test_two_saves_delay() { +add_task(function* test_two_saves_delay() { let timerPromise = setPromiseMockTimer(); let tester = DeferredSaveTester(); let firstCallback_happened = false; @@ -219,7 +219,7 @@ add_task(function test_two_saves_delay() { // Test case where OS.File immediately reports an error when the write begins // Also check that the "error" getter correctly returns the error // Then do a write that succeeds, and make sure the error is cleared -add_task(function test_error_immediate() { +add_task(function* test_error_immediate() { let tester = DeferredSaveTester(); let testError = new Error("Forced failure"); function writeFail(aTester) { @@ -243,7 +243,7 @@ add_task(function test_error_immediate() { // Save one set of changes, then while the write is in progress, modify the // data two more times. Test that we re-write the dirty data exactly once // after the first write succeeds -add_task(function dirty_while_writing() { +add_task(function* dirty_while_writing() { let tester = DeferredSaveTester(); let firstData = "First data"; let secondData = "Second data"; @@ -317,7 +317,7 @@ function write_then_disable(aTester) { // Flush tests. First, do an ordinary clean save and then call flush; // there should not be another save -add_task(function flush_after_save() { +add_task(function* flush_after_save() { setQuickMockTimer(); let tester = DeferredSaveTester(); let dataToSave = "Flush after save"; @@ -328,7 +328,7 @@ add_task(function flush_after_save() { }); // Flush while a write is in progress, but the in-memory data is clean -add_task(function flush_during_write() { +add_task(function* flush_during_write() { let tester = DeferredSaveTester(); let dataToSave = "Flush during write"; let firstCallback_happened = false; @@ -361,7 +361,7 @@ add_task(function flush_during_write() { // Flush while dirty but write not in progress // The data written should be the value at the time // flush() is called, even if it is changed later -add_task(function flush_while_dirty() { +add_task(function* flush_while_dirty() { let timerPromise = setPromiseMockTimer(); let tester = DeferredSaveTester(); let firstData = "Flush while dirty, valid data"; @@ -397,7 +397,7 @@ add_task(function flush_while_dirty() { // then flush, then modify the data again // Data for the second write should be taken at the time // flush() is called, even if it is modified later -add_task(function flush_writing_dirty() { +add_task(function* flush_writing_dirty() { let timerPromise = setPromiseMockTimer(); let tester = DeferredSaveTester(); let firstData = "Flush first pass data"; @@ -463,7 +463,7 @@ function badDataProvider() { // Handle cases where data provider throws // First, throws during a normal save -add_task(function data_throw() { +add_task(function* data_throw() { setQuickMockTimer(); badDataError = expectedDataError; let tester = DeferredSaveTester(badDataProvider); @@ -473,7 +473,7 @@ add_task(function data_throw() { }); // Now, throws during flush -add_task(function data_throw_during_flush() { +add_task(function* data_throw_during_flush() { badDataError = expectedDataError; let tester = DeferredSaveTester(badDataProvider); let firstCallback_happened = false; @@ -508,7 +508,7 @@ add_task(function data_throw_during_flush() { // actually restart timer for delayed write // write completes // delayed timer goes off, throws error because DeferredSave has been torn down -add_task(function delay_flush_race() { +add_task(function* delay_flush_race() { let timerPromise = setPromiseMockTimer(); let tester = DeferredSaveTester(); let firstData = "First save"; diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_asyncBlocklistLoad.js b/toolkit/mozapps/extensions/test/xpcshell/test_asyncBlocklistLoad.js index 11d9f2943e..38e563979b 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_asyncBlocklistLoad.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_asyncBlocklistLoad.js @@ -6,7 +6,7 @@ function run_test() { run_next_test(); } -add_task(function () { +add_task(function* () { let blocklist = AM_Cc["@mozilla.org/extensions/blocklist;1"]. getService().wrappedJSObject; let scope = Components.utils.import("resource://gre/modules/osfile.jsm"); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_locked2.js b/toolkit/mozapps/extensions/test/xpcshell/test_locked2.js index 10b13c9f65..b5766ce4b7 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_locked2.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked2.js @@ -71,7 +71,7 @@ var addon5 = { const profileDir = gProfD.clone(); profileDir.append("extensions"); -add_task(function() { +add_task(function*() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js b/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js index a6f9c80523..7d8f1eed64 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js @@ -279,11 +279,12 @@ function run_test_invalidarg() { AddonManager.mapURIToAddonID(test); throw new Error("Shouldn't be able to map the URI in question"); } - catch (ex if ex.result) { - do_check_eq(ex.result, Components.results.NS_ERROR_INVALID_ARG); - } catch (ex) { - do_throw(ex); + if (ex.result) { + do_check_eq(ex.result, Components.results.NS_ERROR_INVALID_ARG); + } else { + do_throw(ex); + } } } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_no_addons.js b/toolkit/mozapps/extensions/test/xpcshell/test_no_addons.js index ae75fbb438..ae321ccc3a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_no_addons.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_no_addons.js @@ -56,14 +56,14 @@ function check_empty_state() { // bootstrap add-ons preference is not found // add-on directory state preference is an empty array // no pending operations -add_task(function first_run() { +add_task(function* first_run() { startupManager(); check_empty_state(); yield true; }); // Now do something that causes a DB load, and re-check -function trigger_db_load() { +function* trigger_db_load() { let addonDefer = Promise.defer(); AddonManager.getAddonsByTypes(['extension'], addonDefer.resolve); let addonList = yield addonDefer.promise; @@ -76,7 +76,7 @@ function trigger_db_load() { add_task(trigger_db_load); // Now restart the manager and check again -add_task(function restart_and_recheck() { +add_task(function* restart_and_recheck() { restartManager(); check_empty_state(); yield true; diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_updateCancel.js b/toolkit/mozapps/extensions/test/xpcshell/test_updateCancel.js index d513f4adfd..8ed536ae08 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_updateCancel.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_updateCancel.js @@ -75,7 +75,7 @@ writeInstallRDFForExtension({ name: "Test Addon 1", }, profileDir); -add_task(function cancel_during_check() { +add_task(function* cancel_during_check() { startupManager(); let a1 = yield promiseAddonByID("addon1@tests.mozilla.org"); @@ -109,7 +109,7 @@ add_task(function cancel_during_check() { // Test that update check is cancelled if the XPI provider shuts down while // the update check is in progress -add_task(function shutdown_during_check() { +add_task(function* shutdown_during_check() { // Reset our HTTP listener httpReceived = Promise.defer(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js index 3fc16a0f7e..61e0e6b00b 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js @@ -1023,7 +1023,7 @@ for (let test of testParams) { }); }); - add_task(function cleanup() { + add_task(function* cleanup() { let addons = yield new Promise(resolve => { AddonManager.getAddonsByTypes(["extension"], resolve); }); diff --git a/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp b/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp index 8ea43d73f1..a93d5b0b2e 100644 --- a/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp +++ b/xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp @@ -44,7 +44,6 @@ #include "nsIDOMEvent.h" #include "nsIDOMEventTarget.h" #include "nsIDOMFileList.h" -#include "nsIDOMFileReader.h" #include "nsIDOMFocusEvent.h" #include "nsIDOMFormData.h" #include "nsIDOMGeoPositionError.h" @@ -179,7 +178,6 @@ #include "mozilla/dom/EventBinding.h" #include "mozilla/dom/EventTargetBinding.h" #include "mozilla/dom/FileListBinding.h" -#include "mozilla/dom/FileReaderBinding.h" #include "mozilla/dom/FocusEventBinding.h" #include "mozilla/dom/FormDataBinding.h" #include "mozilla/dom/HistoryBinding.h" @@ -363,7 +361,6 @@ const ComponentsInterfaceShimEntry kComponentsInterfaceShimMap[] = DEFINE_SHIM(Element), DEFINE_SHIM(Event), DEFINE_SHIM(EventTarget), - DEFINE_SHIM(FileReader), DEFINE_SHIM(FileList), DEFINE_SHIM(FocusEvent), DEFINE_SHIM(FormData),