Commit 4d10d214 authored by magjed's avatar magjed Committed by Commit Bot

Reland of RTCVideoEncoder: Report H264 profile information to WebRTC (patchset...

Reland of RTCVideoEncoder: Report H264 profile information to WebRTC (patchset #1 id:1 of https://codereview.chromium.org/2973253002/ )

Reason for revert:
Update test to still use HW version of H264.

Original issue's description:
> Revert of TCVideoEncoder: Report H264 profile information to WebRTC (patchset #1 id:190001 of https://codereview.chromium.org/2548443002/ )
>
> Reason for revert:
> Reverting this since it's causing multiple perf regression on mac, looks like HW encode/decode might get disabled.
>
> Original issue's description:
> > Reland of RTCVideoEncoder: Report H264 profile information to WebRTC (patchset #1 id:1 of https://codereview.chromium.org/2521923002/ )
> >
> > Reason for revert:
> > Try again.
> >
> > Original issue's description:
> > > Revert of RTCVideoEncoder: Report H264 profile information to WebRTC (patchset #3 id:60001 of https://codereview.chromium.org/2499973002/ )
> > >
> > > Reason for revert:
> > > Causes these tests to fail on chromium.webrtc bots for Win and Mac:
> > > WebRtcPerfBrowserTest.MANUAL_RunsAudioVideoCall60SecsAndLogsInternalMetricsH264
> > > WebRtcVideoQualityBrowserTests/WebRtcVideoQualityBrowserTest.MANUAL_TestVideoQualityH264
> > > https://build.chromium.org/p/chromium.webrtc/builders/Win8%20Tester/builds/30367
> > > https://build.chromium.org/p/chromium.webrtc/builders/Mac%20Tester/builds/62661
> > >
> > > Original issue's description:
> > > > RTCVideoEncoder: Report H264 profile information to WebRTC
> > > >
> > > > This CL updates RTCVideoEncoderFactory to report cricket::VideoCodecs
> > > > instead of WebRtcVideoEncoderFactory::VideoCodecs. The H264 profile
> > > > information is added to the cricket::VideoCodec so that WebRTC receives
> > > > this information. Also, the mapping between media::VideoCodecProfiles
> > > > and cricket::VideoCodecs is cached so that we can send the
> > > > media::VideoCodecProfile to RTCVideoEncoder instead of having to deal
> > > > with webrtc::VideoCodecType.
> > > >
> > > > BUG=webrtc:6337
> > > >
> > > > Committed: https://crrev.com/510eddede44cb4b67c8f17fdd68cefb780a668c5
> > > > Cr-Commit-Position: refs/heads/master@{#433508}
> > >
> > > TBR=emircan@chromium.org,posciak@chromium.org
> > > # Skipping CQ checks because original CL landed less than 1 days ago.
> > > NOPRESUBMIT=true
> > > NOTREECHECKS=true
> > > NOTRY=true
> > > BUG=webrtc:6337
> > >
> > > Committed: https://crrev.com/c2564bc627cb950b124ac8e41bc5fd3187f7ad9c
> > > Cr-Commit-Position: refs/heads/master@{#433828}
> >
> > TBR=emircan@chromium.org,posciak@chromium.org
> > # Not skipping CQ checks because original CL landed more than 1 days ago.
> > BUG=688541,735959
> >
> > Review-Url: https://codereview.chromium.org/2548443002
> > Cr-Commit-Position: refs/heads/master@{#484874}
> > Committed: https://chromium.googlesource.com/chromium/src/+/829b1d57525c3c6549d18a2c85a96527d59ea5e9
>
> TBR=emircan@chromium.org,magjed@chromium.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=688541,735959
>
> Review-Url: https://codereview.chromium.org/2973253002
> Cr-Commit-Position: refs/heads/master@{#484960}
> Committed: https://chromium.googlesource.com/chromium/src/+/df6e5a5c7e7c665603f9619930a1d7106b55160d

TBR=emircan@chromium.org,niklase@chromium.org,phoglund@chromium.org
# Not skipping CQ checks because original CL landed more than 1 days ago.
BUG=688541,735959

Review-Url: https://codereview.chromium.org/2985263002
Cr-Commit-Position: refs/heads/master@{#491338}
parent 507ddcc2
......@@ -52,6 +52,7 @@ class WebRtcBrowserTest : public WebRtcTestBase {
void RunsAudioVideoWebRTCCallInTwoTabs(
const std::string& video_codec = WebRtcTestBase::kUseDefaultVideoCodec,
bool prefer_hw_video_codec = false,
const std::string& offer_cert_keygen_alg =
WebRtcTestBase::kUseDefaultCertKeygen,
const std::string& answer_cert_keygen_alg =
......@@ -62,8 +63,8 @@ class WebRtcBrowserTest : public WebRtcTestBase {
SetupPeerconnectionWithLocalStream(right_tab_, answer_cert_keygen_alg);
if (!video_codec.empty()) {
SetDefaultVideoCodec(left_tab_, video_codec);
SetDefaultVideoCodec(right_tab_, video_codec);
SetDefaultVideoCodec(left_tab_, video_codec, prefer_hw_video_codec);
SetDefaultVideoCodec(right_tab_, video_codec, prefer_hw_video_codec);
}
NegotiateCall(left_tab_, right_tab_);
......@@ -137,7 +138,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcBrowserTest,
"(test \"OK\")";
return;
}
RunsAudioVideoWebRTCCallInTwoTabs("H264");
RunsAudioVideoWebRTCCallInTwoTabs("H264", true /* prefer_hw_video_codec */);
}
#endif // BUILDFLAG(RTC_USE_H264)
......@@ -160,15 +161,15 @@ IN_PROC_BROWSER_TEST_F(WebRtcBrowserTest, TestWebAudioMediaStream) {
IN_PROC_BROWSER_TEST_F(WebRtcBrowserTest,
RunsAudioVideoWebRTCCallInTwoTabsOfferRsaAnswerRsa) {
RunsAudioVideoWebRTCCallInTwoTabs(WebRtcTestBase::kUseDefaultVideoCodec,
kKeygenAlgorithmRsa,
kKeygenAlgorithmRsa);
false /* prefer_hw_video_codec */,
kKeygenAlgorithmRsa, kKeygenAlgorithmRsa);
}
IN_PROC_BROWSER_TEST_F(WebRtcBrowserTest,
RunsAudioVideoWebRTCCallInTwoTabsOfferEcdsaAnswerEcdsa) {
RunsAudioVideoWebRTCCallInTwoTabs(WebRtcTestBase::kUseDefaultVideoCodec,
kKeygenAlgorithmEcdsa,
kKeygenAlgorithmEcdsa);
RunsAudioVideoWebRTCCallInTwoTabs(
WebRtcTestBase::kUseDefaultVideoCodec, false /* prefer_hw_video_codec */,
kKeygenAlgorithmEcdsa, kKeygenAlgorithmEcdsa);
}
IN_PROC_BROWSER_TEST_F(
......@@ -186,15 +187,15 @@ IN_PROC_BROWSER_TEST_F(
IN_PROC_BROWSER_TEST_F(WebRtcBrowserTest,
RunsAudioVideoWebRTCCallInTwoTabsOfferRsaAnswerEcdsa) {
RunsAudioVideoWebRTCCallInTwoTabs(WebRtcTestBase::kUseDefaultVideoCodec,
kKeygenAlgorithmRsa,
kKeygenAlgorithmEcdsa);
false /* prefer_hw_video_codec */,
kKeygenAlgorithmRsa, kKeygenAlgorithmEcdsa);
}
IN_PROC_BROWSER_TEST_F(WebRtcBrowserTest,
RunsAudioVideoWebRTCCallInTwoTabsOfferEcdsaAnswerRsa) {
RunsAudioVideoWebRTCCallInTwoTabs(WebRtcTestBase::kUseDefaultVideoCodec,
kKeygenAlgorithmEcdsa,
kKeygenAlgorithmRsa);
false /* prefer_hw_video_codec */,
kKeygenAlgorithmEcdsa, kKeygenAlgorithmRsa);
}
IN_PROC_BROWSER_TEST_F(WebRtcBrowserTest,
......
......@@ -559,11 +559,13 @@ void WebRtcTestBase::SetDefaultAudioCodec(
"setDefaultAudioCodec('" + audio_codec + "')", tab));
}
void WebRtcTestBase::SetDefaultVideoCodec(
content::WebContents* tab,
const std::string& video_codec) const {
EXPECT_EQ("ok", ExecuteJavascript(
"setDefaultVideoCodec('" + video_codec + "')", tab));
void WebRtcTestBase::SetDefaultVideoCodec(content::WebContents* tab,
const std::string& video_codec,
bool prefer_hw_codec) const {
EXPECT_EQ("ok",
ExecuteJavascript("setDefaultVideoCodec('" + video_codec + "'," +
(prefer_hw_codec ? "true" : "false") + ")",
tab));
}
void WebRtcTestBase::EnableOpusDtx(content::WebContents* tab) const {
......
......@@ -193,8 +193,13 @@ class WebRtcTestBase : public InProcessBrowserTest {
// Change the default audio/video codec in the offer SDP.
void SetDefaultAudioCodec(content::WebContents* tab,
const std::string& audio_codec) const;
// |prefer_hw_codec| controls if the first or last codec with name
// |video_codec| should be selected. External video codecs are currently at
// the end of the SDP list. This parameter only matters if there are multiple
// codecs with the same name, which can be the case for H264.
void SetDefaultVideoCodec(content::WebContents* tab,
const std::string& video_codec) const;
const std::string& video_codec,
bool prefer_hw_codec = false) const;
// Add 'usedtx=1' to the offer SDP.
void EnableOpusDtx(content::WebContents* tab) const;
......
......@@ -114,7 +114,8 @@ class WebRtcInternalsPerfBrowserTest : public WebRtcTestBase {
}
void RunsAudioVideoCall60SecsAndLogsInternalMetrics(
const std::string& video_codec) {
const std::string& video_codec,
bool prefer_hw_video_codec) {
ASSERT_TRUE(test::HasReferenceFilesInCheckout());
ASSERT_TRUE(embedded_test_server()->Start());
......@@ -131,8 +132,8 @@ class WebRtcInternalsPerfBrowserTest : public WebRtcTestBase {
SetupPeerconnectionWithLocalStream(right_tab);
if (!video_codec.empty()) {
SetDefaultVideoCodec(left_tab, video_codec);
SetDefaultVideoCodec(right_tab, video_codec);
SetDefaultVideoCodec(left_tab, video_codec, prefer_hw_video_codec);
SetDefaultVideoCodec(right_tab, video_codec, prefer_hw_video_codec);
}
NegotiateCall(left_tab, right_tab);
......@@ -179,8 +180,8 @@ class WebRtcInternalsPerfBrowserTest : public WebRtcTestBase {
SetupPeerconnectionWithoutLocalStream(right_tab);
if (!video_codec.empty()) {
SetDefaultVideoCodec(left_tab, video_codec);
SetDefaultVideoCodec(right_tab, video_codec);
SetDefaultVideoCodec(left_tab, video_codec, false /* prefer_hw_codec */);
SetDefaultVideoCodec(right_tab, video_codec, false /* prefer_hw_codec */);
}
if (opus_dtx) {
EnableOpusDtx(left_tab);
......@@ -228,14 +229,16 @@ IN_PROC_BROWSER_TEST_F(
WebRtcInternalsPerfBrowserTest,
MANUAL_RunsAudioVideoCall60SecsAndLogsInternalMetricsVp8) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
RunsAudioVideoCall60SecsAndLogsInternalMetrics("VP8");
RunsAudioVideoCall60SecsAndLogsInternalMetrics(
"VP8", false /* prefer_hw_video_codec */);
}
IN_PROC_BROWSER_TEST_F(
WebRtcInternalsPerfBrowserTest,
MANUAL_RunsAudioVideoCall60SecsAndLogsInternalMetricsVp9) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
RunsAudioVideoCall60SecsAndLogsInternalMetrics("VP9");
RunsAudioVideoCall60SecsAndLogsInternalMetrics(
"VP9", false /* prefer_hw_video_codec */);
}
#if BUILDFLAG(RTC_USE_H264)
......@@ -252,7 +255,8 @@ IN_PROC_BROWSER_TEST_F(
"\"OK\")";
return;
}
RunsAudioVideoCall60SecsAndLogsInternalMetrics("H264");
RunsAudioVideoCall60SecsAndLogsInternalMetrics(
"H264", true /* prefer_hw_video_codec */);
}
#endif // BUILDFLAG(RTC_USE_H264)
......
......@@ -88,7 +88,8 @@ class WebRtcStatsPerfBrowserTest : public WebRtcTestBase {
}
void StartCall(const std::string& audio_codec,
const std::string& video_codec) {
const std::string& video_codec,
bool prefer_hw_video_codec) {
ASSERT_TRUE(test::HasReferenceFilesInCheckout());
ASSERT_TRUE(embedded_test_server()->Start());
......@@ -103,8 +104,8 @@ class WebRtcStatsPerfBrowserTest : public WebRtcTestBase {
SetupPeerconnectionWithLocalStream(right_tab_);
SetDefaultAudioCodec(left_tab_, audio_codec);
SetDefaultAudioCodec(right_tab_, audio_codec);
SetDefaultVideoCodec(left_tab_, video_codec);
SetDefaultVideoCodec(right_tab_, video_codec);
SetDefaultVideoCodec(left_tab_, video_codec, prefer_hw_video_codec);
SetDefaultVideoCodec(right_tab_, video_codec, prefer_hw_video_codec);
CreateDataChannel(left_tab_, "data");
CreateDataChannel(right_tab_, "data");
NegotiateCall(left_tab_, right_tab_);
......@@ -121,9 +122,23 @@ class WebRtcStatsPerfBrowserTest : public WebRtcTestBase {
HangUp(right_tab_);
}
void RunsAudioAndVideoCallCollectingMetrics(
const std::string& audio_codec, const std::string& video_codec) {
StartCall(audio_codec, video_codec);
void RunsAudioAndVideoCallCollectingMetricsWithAudioCodec(
const std::string& audio_codec) {
RunsAudioAndVideoCallCollectingMetrics(audio_codec, kUseDefaultVideoCodec,
false /* prefer_hw_video_codec */);
}
void RunsAudioAndVideoCallCollectingMetricsWithVideoCodec(
const std::string& video_codec,
bool prefer_hw_video_codec) {
RunsAudioAndVideoCallCollectingMetrics(kUseDefaultAudioCodec, video_codec,
prefer_hw_video_codec);
}
void RunsAudioAndVideoCallCollectingMetrics(const std::string& audio_codec,
const std::string& video_codec,
bool prefer_hw_video_codec) {
StartCall(audio_codec, video_codec, prefer_hw_video_codec);
// Call for 60 seconds so that values may stabilize, bandwidth ramp up, etc.
test::SleepInJavascript(left_tab_, 60000);
......@@ -199,7 +214,8 @@ class WebRtcStatsPerfBrowserTest : public WebRtcTestBase {
GetStatsVariation variation) {
EXPECT_TRUE(base::TimeTicks::IsHighResolution());
StartCall(kUseDefaultAudioCodec, kUseDefaultVideoCodec);
StartCall(kUseDefaultAudioCodec, kUseDefaultVideoCodec,
false /* prefer_hw_video_codec */);
double invocation_time = 0.0;
switch (variation) {
......@@ -234,49 +250,51 @@ IN_PROC_BROWSER_TEST_F(
WebRtcStatsPerfBrowserTest,
MANUAL_RunsAudioAndVideoCallCollectingMetrics_AudioCodec_opus) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
RunsAudioAndVideoCallCollectingMetrics("opus", kUseDefaultVideoCodec);
RunsAudioAndVideoCallCollectingMetricsWithAudioCodec("opus");
}
IN_PROC_BROWSER_TEST_F(
WebRtcStatsPerfBrowserTest,
MANUAL_RunsAudioAndVideoCallCollectingMetrics_AudioCodec_ISAC) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
RunsAudioAndVideoCallCollectingMetrics("ISAC", kUseDefaultVideoCodec);
RunsAudioAndVideoCallCollectingMetricsWithAudioCodec("ISAC");
}
IN_PROC_BROWSER_TEST_F(
WebRtcStatsPerfBrowserTest,
MANUAL_RunsAudioAndVideoCallCollectingMetrics_AudioCodec_G722) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
RunsAudioAndVideoCallCollectingMetrics("G722", kUseDefaultVideoCodec);
RunsAudioAndVideoCallCollectingMetricsWithAudioCodec("G722");
}
IN_PROC_BROWSER_TEST_F(
WebRtcStatsPerfBrowserTest,
MANUAL_RunsAudioAndVideoCallCollectingMetrics_AudioCodec_PCMU) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
RunsAudioAndVideoCallCollectingMetrics("PCMU", kUseDefaultVideoCodec);
RunsAudioAndVideoCallCollectingMetricsWithAudioCodec("PCMU");
}
IN_PROC_BROWSER_TEST_F(
WebRtcStatsPerfBrowserTest,
MANUAL_RunsAudioAndVideoCallCollectingMetrics_AudioCodec_PCMA) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
RunsAudioAndVideoCallCollectingMetrics("PCMA", kUseDefaultVideoCodec);
RunsAudioAndVideoCallCollectingMetricsWithAudioCodec("PCMA");
}
IN_PROC_BROWSER_TEST_F(
WebRtcStatsPerfBrowserTest,
MANUAL_RunsAudioAndVideoCallCollectingMetrics_VideoCodec_VP8) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
RunsAudioAndVideoCallCollectingMetrics(kUseDefaultAudioCodec, "VP8");
RunsAudioAndVideoCallCollectingMetricsWithVideoCodec(
"VP8", false /* prefer_hw_video_codec */);
}
IN_PROC_BROWSER_TEST_F(
WebRtcStatsPerfBrowserTest,
MANUAL_RunsAudioAndVideoCallCollectingMetrics_VideoCodec_VP9) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
RunsAudioAndVideoCallCollectingMetrics(kUseDefaultAudioCodec, "VP9");
RunsAudioAndVideoCallCollectingMetricsWithVideoCodec(
"VP9", false /* prefer_hw_video_codec */);
}
#if BUILDFLAG(RTC_USE_H264)
......@@ -293,7 +311,8 @@ IN_PROC_BROWSER_TEST_F(
"\"OK\")";
return;
}
RunsAudioAndVideoCallCollectingMetrics(kUseDefaultAudioCodec, "H264");
RunsAudioAndVideoCallCollectingMetricsWithVideoCodec(
"H264", true /* prefer_hw_video_codec */);
}
#endif // BUILDFLAG(RTC_USE_H264)
......
......@@ -259,7 +259,8 @@ class WebRtcVideoQualityBrowserTest : public WebRtcTestBase,
return true;
}
void TestVideoQuality(const std::string& video_codec) {
void TestVideoQuality(const std::string& video_codec,
bool prefer_hw_video_codec) {
ASSERT_GE(TestTimeouts::action_max_timeout().InSeconds(), 150)
<< "This is a long-running test; you must specify "
"--ui-test-action-max-timeout to have a value of at least 150000.";
......@@ -279,8 +280,8 @@ class WebRtcVideoQualityBrowserTest : public WebRtcTestBase,
SetupPeerconnectionWithLocalStream(right_tab);
if (!video_codec.empty()) {
SetDefaultVideoCodec(left_tab, video_codec);
SetDefaultVideoCodec(right_tab, video_codec);
SetDefaultVideoCodec(left_tab, video_codec, prefer_hw_video_codec);
SetDefaultVideoCodec(right_tab, video_codec, prefer_hw_video_codec);
}
NegotiateCall(left_tab, right_tab);
......@@ -346,13 +347,13 @@ INSTANTIATE_TEST_CASE_P(
IN_PROC_BROWSER_TEST_P(WebRtcVideoQualityBrowserTest,
MANUAL_TestVideoQualityVp8) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
TestVideoQuality("VP8");
TestVideoQuality("VP8", false /* prefer_hw_video_codec */);
}
IN_PROC_BROWSER_TEST_P(WebRtcVideoQualityBrowserTest,
MANUAL_TestVideoQualityVp9) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
TestVideoQuality("VP9");
TestVideoQuality("VP9", false /* prefer_hw_video_codec */);
}
#if BUILDFLAG(RTC_USE_H264)
......@@ -367,7 +368,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcVideoQualityBrowserTest,
"(test \"OK\")";
return;
}
TestVideoQuality("H264");
TestVideoQuality("H264", true /* prefer_hw_video_codec */);
}
#endif // BUILDFLAG(RTC_USE_H264)
......@@ -8,14 +8,14 @@
* See |setSdpDefaultCodec|.
*/
function setSdpDefaultAudioCodec(sdp, codec) {
return setSdpDefaultCodec(sdp, 'audio', codec);
return setSdpDefaultCodec(sdp, 'audio', codec, false /* preferHwCodec */);
}
/**
* See |setSdpDefaultCodec|.
*/
function setSdpDefaultVideoCodec(sdp, codec) {
return setSdpDefaultCodec(sdp, 'video', codec);
function setSdpDefaultVideoCodec(sdp, codec, preferHwCodec) {
return setSdpDefaultCodec(sdp, 'video', codec, preferHwCodec);
}
/**
......@@ -55,14 +55,17 @@ function setOpusDtxEnabled(sdp) {
/**
* Returns a modified version of |sdp| where the |codec| has been promoted to be
* the default codec, i.e. the codec whose ID is first in the list of codecs on
* the 'm=|type|' line, where |type| is 'audio' or 'video'.
* the 'm=|type|' line, where |type| is 'audio' or 'video'. If |preferHwCodec|
* is true, it will select the last codec with the given name, and if false, it
* will select the first codec with the given name, because HW codecs are listed
* after SW codecs in the SDP list.
* @private
*/
function setSdpDefaultCodec(sdp, type, codec) {
function setSdpDefaultCodec(sdp, type, codec, preferHwCodec) {
var sdpLines = splitSdpLines(sdp);
// Find codec ID, e.g. 100 for 'VP8' if 'a=rtpmap:100 VP8/9000'.
var codecId = findRtpmapId(sdpLines, codec);
var codecId = findRtpmapId(sdpLines, codec, preferHwCodec);
if (codecId === null) {
failure('setSdpDefaultCodec',
'Unknown ID for |codec| = \'' + codec + '\'.');
......@@ -129,13 +132,15 @@ function getSdpDefaultCodec(sdp, type) {
/**
* Searches through all |sdpLines| for the 'a=rtpmap:' line for the codec of
* the specified name, returning its ID as an int if found, or null otherwise.
* |codec| is the case-sensitive name of the codec.
* |codec| is the case-sensitive name of the codec. If |lastInstance|
* is true, it will return the last such ID, and if false, it will return the
* first such ID.
* For example, if |sdpLines| contains 'a=rtpmap:100 VP8/9000' and |codec| is
* 'VP8', this function returns 100.
* @private
*/
function findRtpmapId(sdpLines, codec) {
var lineNo = findRtpmapLine(sdpLines, codec);
function findRtpmapId(sdpLines, codec, lastInstance) {
var lineNo = findRtpmapLine(sdpLines, codec, lastInstance);
if (lineNo === null)
return null;
// Parse <id> from 'a=rtpmap:<id> <codec>/<rate>'.
......@@ -163,27 +168,45 @@ function findRtpmapCodec(sdpLines, id) {
}
/**
* Finds the first 'a=rtpmap:' line from |sdpLines| that contains |contains| and
* returns its line index, or null if no such line was found. |contains| may be
* the codec ID, codec name or bitrate. An 'a=rtpmap:' line looks like this:
* 'a=rtpmap:<id> <codec>/<rate>'.
* Finds a 'a=rtpmap:' line from |sdpLines| that contains |contains| and returns
* its line index, or null if no such line was found. |contains| may be the
* codec ID, codec name or bitrate. If |lastInstance| is true, it will return
* the last such line index, and if false, it will return the first such line
* index.
* An 'a=rtpmap:' line looks like this: 'a=rtpmap:<id> <codec>/<rate>'.
*/
function findRtpmapLine(sdpLines, contains) {
for (var i = 0; i < sdpLines.length; i++) {
// Is 'a=rtpmap:' line containing |contains| string?
if (sdpLines[i].startsWith('a=rtpmap:') &&
sdpLines[i].indexOf(contains) != -1) {
// Expecting pattern 'a=rtpmap:<id> <codec>/<rate>'.
var pattern = new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+');
if (!sdpLines[i].match(pattern))
failure('findRtpmapLine', 'Unexpected "a=rtpmap:" pattern.');
// Return line index.
return i;
function findRtpmapLine(sdpLines, contains, lastInstance) {
if (lastInstance === true) {
for (var i = sdpLines.length - 1; i >= 0 ; i--) {
if (isRtpmapLine(sdpLines[i], contains))
return i;
}
} else {
for (var i = 0; i < sdpLines.length; i++) {
if (isRtpmapLine(sdpLines[i], contains))
return i;
}
}
return null;
}
/**
* Returns true if |sdpLine| contains |contains| and is of pattern
* 'a=rtpmap:<id> <codec>/<rate>'.
*/
function isRtpmapLine(sdpLine, contains) {
// Is 'a=rtpmap:' line containing |contains| string?
if (sdpLine.startsWith('a=rtpmap:') &&
sdpLine.indexOf(contains) != -1) {
// Expecting pattern 'a=rtpmap:<id> <codec>/<rate>'.
var pattern = new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+');
if (!sdpLine.match(pattern))
failure('isRtpmapLine', 'Unexpected "a=rtpmap:" pattern.');
return true;
}
return false;
}
/**
* Finds the fmtp line in |sdpLines| for the given |codecId|, and returns its
* line number. The line starts with 'a=fmtp:<codecId>'.
......
......@@ -40,6 +40,12 @@ var gDefaultAudioCodec = null;
*/
var gDefaultVideoCodec = null;
/**
* Flag to indicate if HW or SW video codec is preferred.
* @private
*/
var gDefaultPreferHwVideoCodec = null;
/**
* Flag to indicate if Opus Dtx should be enabled.
* @private
......@@ -122,9 +128,14 @@ function setDefaultAudioCodec(audioCodec) {
* video codec, e.g. the first one in the list on the 'm=video' SDP offer
* line. |videoCodec| is the case-sensitive codec name, e.g. 'VP8' or
* 'H264'.
* @param {bool} preferHwVideoCodec specifies what codec to use from the
* 'm=video' line when there are multiple codecs with the name |videoCodec|.
* If true, it will return the last codec with that name, and if false, it
* will return the first codec with that name.
*/
function setDefaultVideoCodec(videoCodec) {
function setDefaultVideoCodec(videoCodec, preferHwVideoCodec) {
gDefaultVideoCodec = videoCodec;
gDefaultPreferHwVideoCodec = preferHwVideoCodec;
returnToTest('ok');
}
......@@ -156,7 +167,8 @@ function createLocalOffer(constraints) {
}
if (gDefaultVideoCodec !== null) {
localOffer.sdp = setSdpDefaultVideoCodec(localOffer.sdp,
gDefaultVideoCodec);
gDefaultVideoCodec,
gDefaultPreferHwVideoCodec);
}
if (gOpusDtx) {
localOffer.sdp = setOpusDtxEnabled(localOffer.sdp);
......
......@@ -775,6 +775,7 @@ target(link_target_type, "renderer") {
"//third_party/webrtc/api:video_frame_api",
"//third_party/webrtc/api/audio_codecs:builtin_audio_decoder_factory",
"//third_party/webrtc/api/audio_codecs:builtin_audio_encoder_factory",
"//third_party/webrtc/common_video:common_video",
"//third_party/webrtc/media:rtc_media",
"//third_party/webrtc/media:rtc_media_base",
"//third_party/webrtc/modules/audio_device",
......
......@@ -47,25 +47,16 @@ struct RTCTimestamps {
DISALLOW_IMPLICIT_CONSTRUCTORS(RTCTimestamps);
};
// Translate from webrtc::VideoCodecType and webrtc::VideoCodec to
// media::VideoCodecProfile.
media::VideoCodecProfile WebRTCVideoCodecToVideoCodecProfile(
webrtc::VideoCodecType type,
const webrtc::VideoCodec* codec_settings) {
DCHECK_EQ(type, codec_settings->codecType);
switch (type) {
case webrtc::kVideoCodecVP8:
return media::VP8PROFILE_ANY;
case webrtc::kVideoCodecVP9:
return media::VP9PROFILE_MIN;
case webrtc::kVideoCodecH264:
// TODO(magjed): WebRTC is only using Baseline profile for now. Update
// once http://crbug/webrtc/6337 is fixed.
return media::H264PROFILE_BASELINE;
default:
NOTREACHED() << "Unrecognized video codec type";
return media::VIDEO_CODEC_PROFILE_UNKNOWN;
webrtc::VideoCodecType ProfileToWebRtcVideoCodecType(
media::VideoCodecProfile profile) {
if (profile >= media::VP8PROFILE_MIN && profile <= media::VP8PROFILE_MAX) {
return webrtc::kVideoCodecVP8;
} else if (profile >= media::H264PROFILE_MIN &&
profile <= media::H264PROFILE_MAX) {
return webrtc::kVideoCodecH264;
}
NOTREACHED() << "Invalid profile " << GetProfileName(profile);
return webrtc::kVideoCodecUnknown;
}
// Populates struct webrtc::RTPFragmentationHeader for H264 codec.
......@@ -798,12 +789,12 @@ void RTCVideoEncoder::Impl::ReturnEncodedImage(
}
RTCVideoEncoder::RTCVideoEncoder(
webrtc::VideoCodecType type,
media::VideoCodecProfile profile,
media::GpuVideoAcceleratorFactories* gpu_factories)
: video_codec_type_(type),
: profile_(profile),
gpu_factories_(gpu_factories),
gpu_task_runner_(gpu_factories->GetTaskRunner()) {
DVLOG(1) << __func__ << " codec type=" << type;
DVLOG(1) << "RTCVideoEncoder(): profile=" << GetProfileName(profile);
}
RTCVideoEncoder::~RTCVideoEncoder() {
......@@ -822,9 +813,7 @@ int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
if (impl_)
Release();
impl_ = new Impl(gpu_factories_, video_codec_type_);
const media::VideoCodecProfile profile = WebRTCVideoCodecToVideoCodecProfile(
impl_->video_codec_type(), codec_settings);
impl_ = new Impl(gpu_factories_, ProfileToWebRtcVideoCodecType(profile_));
base::WaitableEvent initialization_waiter(
base::WaitableEvent::ResetPolicy::MANUAL,
......@@ -832,17 +821,14 @@ int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
int32_t initialization_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
gpu_task_runner_->PostTask(
FROM_HERE,
base::Bind(&RTCVideoEncoder::Impl::CreateAndInitializeVEA,
impl_,
base::Bind(&RTCVideoEncoder::Impl::CreateAndInitializeVEA, impl_,
gfx::Size(codec_settings->width, codec_settings->height),
codec_settings->startBitrate,
profile,
&initialization_waiter,
codec_settings->startBitrate, profile_, &initialization_waiter,
&initialization_retval));
// webrtc::VideoEncoder expects this call to be synchronous.
initialization_waiter.Wait();
RecordInitEncodeUMA(initialization_retval, profile);
RecordInitEncodeUMA(initialization_retval, profile_);
return initialization_retval;
}
......
......@@ -41,7 +41,7 @@ namespace content {
class CONTENT_EXPORT RTCVideoEncoder
: NON_EXPORTED_BASE(public webrtc::VideoEncoder) {
public:
RTCVideoEncoder(webrtc::VideoCodecType type,
RTCVideoEncoder(media::VideoCodecProfile profile,
media::GpuVideoAcceleratorFactories* gpu_factories);
~RTCVideoEncoder() override;
......@@ -65,8 +65,7 @@ class CONTENT_EXPORT RTCVideoEncoder
class Impl;
friend class RTCVideoEncoder::Impl;
// The video codec type, as reported to WebRTC.
const webrtc::VideoCodecType video_codec_type_;
const media::VideoCodecProfile profile_;
// Factory for creating VEAs, shared memory buffers, etc.
media::GpuVideoAcceleratorFactories* gpu_factories_;
......
......@@ -11,23 +11,23 @@
#include "content/renderer/media/gpu/rtc_video_encoder.h"
#include "media/gpu/ipc/client/gpu_video_encode_accelerator_host.h"
#include "media/renderers/gpu_video_accelerator_factories.h"
#include "media/video/video_encode_accelerator.h"
#include "third_party/webrtc/common_video/h264/profile_level_id.h"
namespace content {
namespace {
// Translate from media::VideoEncodeAccelerator::SupportedProfile to
// one or more instances of cricket::WebRtcVideoEncoderFactory::VideoCodec
void VEAToWebRTCCodecs(
std::vector<cricket::VideoCodec>* codecs,
// cricket::WebRtcVideoEncoderFactory::VideoCodec, or return nothing if the
// profile isn't supported.
base::Optional<cricket::VideoCodec> VEAToWebRTCCodec(
const media::VideoEncodeAccelerator::SupportedProfile& profile) {
DCHECK_EQ(profile.max_framerate_denominator, 1U);
if (profile.profile >= media::VP8PROFILE_MIN &&
profile.profile <= media::VP8PROFILE_MAX) {
if (base::FeatureList::IsEnabled(features::kWebRtcHWVP8Encoding)) {
codecs->push_back(cricket::VideoCodec("VP8"));
return base::Optional<cricket::VideoCodec>(cricket::VideoCodec("VP8"));
}
} else if (profile.profile >= media::H264PROFILE_MIN &&
profile.profile <= media::H264PROFILE_MAX) {
......@@ -41,10 +41,41 @@ void VEAToWebRTCCodecs(
#endif // BUILDFLAG(RTC_USE_H264) && !defined(MEDIA_DISABLE_FFMPEG)
if (webrtc_h264_sw_enabled ||
base::FeatureList::IsEnabled(features::kWebRtcHWH264Encoding)) {
// TODO(magjed): Propagate H264 profile information.
codecs->push_back(cricket::VideoCodec("H264"));
webrtc::H264::Profile h264_profile;
switch (profile.profile) {
case media::H264PROFILE_BASELINE:
h264_profile = webrtc::H264::kProfileBaseline;
break;
case media::H264PROFILE_MAIN:
h264_profile = webrtc::H264::kProfileMain;
break;
case media::H264PROFILE_HIGH:
h264_profile = webrtc::H264::kProfileHigh;
break;
default:
// Unsupported H264 profile in WebRTC.
return base::Optional<cricket::VideoCodec>();
}
const int width = profile.max_resolution.width();
const int height = profile.max_resolution.height();
const int fps = profile.max_framerate_numerator;
DCHECK_EQ(1u, profile.max_framerate_denominator);
const rtc::Optional<webrtc::H264::Level> h264_level =
webrtc::H264::SupportedLevel(width * height, fps);
const webrtc::H264::ProfileLevelId profile_level_id(
h264_profile, h264_level.value_or(webrtc::H264::kLevel1));
cricket::VideoCodec codec("H264");
codec.SetParam(cricket::kH264FmtpProfileLevelId,
*webrtc::H264::ProfileLevelIdToString(profile_level_id));
codec.SetParam(cricket::kH264FmtpLevelAsymmetryAllowed, "1");
codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
return base::Optional<cricket::VideoCodec>(codec);
}
}
return base::Optional<cricket::VideoCodec>();
}
} // anonymous namespace
......@@ -54,20 +85,36 @@ RTCVideoEncoderFactory::RTCVideoEncoderFactory(
: gpu_factories_(gpu_factories) {
const media::VideoEncodeAccelerator::SupportedProfiles& profiles =
gpu_factories_->GetVideoEncodeAcceleratorSupportedProfiles();
for (const auto& profile : profiles)
VEAToWebRTCCodecs(&supported_codecs_, profile);
for (const auto& profile : profiles) {
base::Optional<cricket::VideoCodec> codec = VEAToWebRTCCodec(profile);
if (codec) {
supported_codecs_.push_back(std::move(*codec));
profiles_.push_back(profile.profile);
}
}
// There should be a 1:1 mapping between media::VideoCodecProfile and
// cricket::VideoCodec.
CHECK_EQ(profiles_.size(), supported_codecs_.size());
}
RTCVideoEncoderFactory::~RTCVideoEncoderFactory() {}
webrtc::VideoEncoder* RTCVideoEncoderFactory::CreateVideoEncoder(
const cricket::VideoCodec& codec) {
for (const cricket::VideoCodec& supported_codec : supported_codecs_) {
if (cricket::CodecNamesEq(codec.name, supported_codec.name)) {
webrtc::VideoCodecType type = webrtc::PayloadNameToCodecType(codec.name)
.value_or(webrtc::kVideoCodecUnknown);
return new RTCVideoEncoder(type, gpu_factories_);
for (size_t i = 0; i < supported_codecs_.size(); ++i) {
if (!cricket::CodecNamesEq(codec.name, supported_codecs_[i].name))
continue;
// Check H264 profile.
using webrtc::H264::ParseSdpProfileLevelId;
if (cricket::CodecNamesEq(codec.name.c_str(), cricket::kH264CodecName) &&
ParseSdpProfileLevelId(codec.params)->profile !=
ParseSdpProfileLevelId(supported_codecs_[i].params)->profile) {
continue;
}
// There should be a 1:1 mapping between media::VideoCodecProfile and
// cricket::VideoCodec.
CHECK_EQ(profiles_.size(), supported_codecs_.size());
return new RTCVideoEncoder(profiles_[i], gpu_factories_);
}
return nullptr;
}
......
......@@ -39,6 +39,9 @@ class CONTENT_EXPORT RTCVideoEncoderFactory
media::GpuVideoAcceleratorFactories* gpu_factories_;
// List of supported cricket::WebRtcVideoEncoderFactory::VideoCodec.
// |profiles_| and |supported_codecs_| have the same length and the profile
// for |supported_codecs_[i]| is |profiles_[i]|.
std::vector<media::VideoCodecProfile> profiles_;
std::vector<cricket::VideoCodec> supported_codecs_;
DISALLOW_COPY_AND_ASSIGN(RTCVideoEncoderFactory);
......
......@@ -113,7 +113,19 @@ class RTCVideoEncoderTest
void CreateEncoder(webrtc::VideoCodecType codec_type) {
DVLOG(3) << __func__;
rtc_encoder_ = base::MakeUnique<RTCVideoEncoder>(codec_type,
media::VideoCodecProfile media_profile;
switch (codec_type) {
case webrtc::kVideoCodecVP8:
media_profile = media::VP8PROFILE_ANY;
break;
case webrtc::kVideoCodecH264:
media_profile = media::H264PROFILE_BASELINE;
break;
default:
ADD_FAILURE() << "Unexpected codec type: " << codec_type;
media_profile = media::VIDEO_CODEC_PROFILE_UNKNOWN;
}
rtc_encoder_ = base::MakeUnique<RTCVideoEncoder>(media_profile,
mock_gpu_factories_.get());
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment