Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
savoirfairelinux
jami-daemon
Commits
2f521d2e
Commit
2f521d2e
authored
Jul 26, 2012
by
Tristan Matthews
Browse files
* #13814: video: parse encoder profile-level-id properly
parent
1d3ebe19
Changes
7
Hide whitespace changes
Inline
Side-by-side
daemon/src/account.cpp
View file @
2f521d2e
...
...
@@ -46,6 +46,7 @@ const char * const Account::AUDIO_CODECS_KEY = "audioCodecs"; // 0/9/110/1
const
char
*
const
Account
::
VIDEO_CODECS_KEY
=
"videoCodecs"
;
const
char
*
const
Account
::
VIDEO_CODEC_ENABLED
=
"enabled"
;
const
char
*
const
Account
::
VIDEO_CODEC_NAME
=
"name"
;
const
char
*
const
Account
::
VIDEO_CODEC_PARAMETERS
=
"parameters"
;
const
char
*
const
Account
::
VIDEO_CODEC_BITRATE
=
"bitrate"
;
const
char
*
const
Account
::
RINGTONE_PATH_KEY
=
"ringtonePath"
;
const
char
*
const
Account
::
RINGTONE_ENABLED_KEY
=
"ringtoneEnabled"
;
...
...
@@ -146,7 +147,7 @@ namespace {
bool
isCodecValid
(
const
map
<
string
,
string
>
&
codec
,
const
vector
<
map
<
string
,
string
>
>
&
defaults
)
{
map
<
string
,
string
>::
const_iterator
name
(
codec
.
find
(
Account
::
VIDEO_CODEC_NAME
));
const
map
<
string
,
string
>::
const_iterator
name
(
codec
.
find
(
Account
::
VIDEO_CODEC_NAME
));
if
(
name
==
codec
.
end
())
{
ERROR
(
"Field
\"
name
\"
missing in codec specification"
);
return
false
;
...
...
@@ -154,7 +155,7 @@ namespace {
// check that it's in the list of valid codecs and that it has all the required fields
for
(
vector
<
map
<
string
,
string
>
>::
const_iterator
i
=
defaults
.
begin
();
i
!=
defaults
.
end
();
++
i
)
{
map
<
string
,
string
>::
const_iterator
defaultName
=
i
->
find
(
Account
::
VIDEO_CODEC_NAME
);
const
map
<
string
,
string
>::
const_iterator
defaultName
=
i
->
find
(
Account
::
VIDEO_CODEC_NAME
);
if
(
defaultName
->
second
==
name
->
second
)
{
return
isFieldValid
(
codec
,
Account
::
VIDEO_CODEC_BITRATE
,
isPositiveInteger
)
and
isFieldValid
(
codec
,
Account
::
VIDEO_CODEC_ENABLED
,
isBoolean
);
...
...
daemon/src/account.h
View file @
2f521d2e
...
...
@@ -185,6 +185,7 @@ class Account : public Serializable {
static
const
char
*
const
VIDEO_CODEC_ENABLED
;
static
const
char
*
const
VIDEO_CODEC_NAME
;
static
const
char
*
const
VIDEO_CODEC_PARAMETERS
;
static
const
char
*
const
VIDEO_CODEC_BITRATE
;
private:
NON_COPYABLE
(
Account
);
...
...
daemon/src/sip/sdp.cpp
View file @
2f521d2e
...
...
@@ -220,13 +220,15 @@ pjmedia_sdp_media *Sdp::setMediaDescriptorLine(bool audio)
pjmedia_sdp_rtpmap_to_attr
(
memPool_
,
&
rtpmap
,
&
attr
);
med
->
attr
[
med
->
attr_count
++
]
=
attr
;
#ifdef SFL_VIDEO
if
(
enc_name
==
"H264"
)
{
std
::
ostringstream
os
;
// FIXME: this should not be hardcoded, it will determine what profile and level
// our peer will send us
os
<<
"fmtp:"
<<
dynamic_payload
<<
"
profile-level-id=428014"
;
os
<<
"fmtp:"
<<
dynamic_payload
<<
"
"
<<
libav_utils
::
DEFAULT_H264_PROFILE_LEVEL_ID
;
med
->
attr
[
med
->
attr_count
++
]
=
pjmedia_sdp_attr_create
(
memPool_
,
os
.
str
().
c_str
(),
NULL
);
}
#endif
if
(
not
audio
)
dynamic_payload
++
;
}
...
...
daemon/src/sip/sipaccount.cpp
View file @
2f521d2e
...
...
@@ -160,6 +160,7 @@ void SIPAccount::serialize(Conf::YamlEmitter &emitter)
mapNode
->
setKeyValue
(
VIDEO_CODEC_NAME
,
new
ScalarNode
(
codec
[
VIDEO_CODEC_NAME
]));
mapNode
->
setKeyValue
(
VIDEO_CODEC_BITRATE
,
new
ScalarNode
(
codec
[
VIDEO_CODEC_BITRATE
]));
mapNode
->
setKeyValue
(
VIDEO_CODEC_ENABLED
,
new
ScalarNode
(
codec
[
VIDEO_CODEC_ENABLED
]));
mapNode
->
setKeyValue
(
VIDEO_CODEC_PARAMETERS
,
new
ScalarNode
(
codec
[
VIDEO_CODEC_PARAMETERS
]));
videoCodecs
.
addNode
(
mapNode
);
}
#endif
...
...
@@ -287,6 +288,7 @@ void SIPAccount::serialize(Conf::YamlEmitter &emitter)
delete
node
->
getValue
(
VIDEO_CODEC_NAME
);
delete
node
->
getValue
(
VIDEO_CODEC_BITRATE
);
delete
node
->
getValue
(
VIDEO_CODEC_ENABLED
);
delete
node
->
getValue
(
VIDEO_CODEC_PARAMETERS
);
delete
node
;
}
#endif
...
...
@@ -326,6 +328,7 @@ void SIPAccount::unserialize(const Conf::MappingNode &mapNode)
codec
->
getValue
(
VIDEO_CODEC_NAME
,
&
codecMap
[
VIDEO_CODEC_NAME
]);
codec
->
getValue
(
VIDEO_CODEC_BITRATE
,
&
codecMap
[
VIDEO_CODEC_BITRATE
]);
codec
->
getValue
(
VIDEO_CODEC_ENABLED
,
&
codecMap
[
VIDEO_CODEC_ENABLED
]);
codec
->
getValue
(
VIDEO_CODEC_PARAMETERS
,
&
codecMap
[
VIDEO_CODEC_PARAMETERS
]);
videoCodecDetails
.
push_back
(
codecMap
);
}
// these must be validated
...
...
daemon/src/video/libav_utils.cpp
View file @
2f521d2e
...
...
@@ -52,7 +52,6 @@ vector<string> installed_video_codecs_;
/* application wide mutex to protect concurrent access to avcodec */
ost
::
Mutex
avcodec_lock_
;
void
findInstalledVideoCodecs
()
{
vector
<
string
>
libav_codecs
;
...
...
@@ -73,7 +72,6 @@ void findInstalledVideoCodecs()
namespace
libav_utils
{
vector
<
string
>
getVideoCodecList
()
{
if
(
installed_video_codecs_
.
empty
())
...
...
@@ -154,6 +152,9 @@ getDefaultCodecs()
codec
[
"name"
]
=
*
iter
;
codec
[
"bitrate"
]
=
DEFAULT_BITRATE
;
codec
[
"enabled"
]
=
"true"
;
// FIXME: make a nicer version of this
if
(
*
iter
==
"H264"
)
codec
[
"parameters"
]
=
DEFAULT_H264_PROFILE_LEVEL_ID
;
result
.
push_back
(
codec
);
}
return
result
;
...
...
daemon/src/video/libav_utils.h
View file @
2f521d2e
...
...
@@ -47,6 +47,7 @@ namespace libav_utils {
std
::
vector
<
std
::
map
<
std
::
string
,
std
::
string
>
>
getDefaultCodecs
();
const
char
*
const
DEFAULT_H264_PROFILE_LEVEL_ID
=
"profile-level-id=428014"
;
}
#endif // __LIBAV_UTILS_H__
daemon/src/video/video_send_thread.cpp
View file @
2f521d2e
...
...
@@ -121,6 +121,53 @@ void VideoSendThread::prepareEncoderContext(AVCodec *encoder)
// encoderCtx_->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
namespace
{
void
extractProfileLevelID
(
const
std
::
string
&
parameters
,
AVCodecContext
*
ctx
)
{
// From RFC3984:
// If no profile-level-id is present, the Baseline Profile without
// additional constraints at Level 1 MUST be implied.
ctx
->
profile
=
FF_PROFILE_H264_BASELINE
;
ctx
->
level
=
0x1
;
// ctx->level = 0x0d; // => 13 aka 1.3
if
(
parameters
.
empty
())
return
;
const
std
::
string
target
(
"profile-level-id="
);
size_t
needle
=
parameters
.
find
(
target
);
if
(
needle
==
std
::
string
::
npos
)
return
;
needle
+=
target
.
length
();
const
size_t
id_length
=
6
;
/* digits */
const
std
::
string
profileLevelID
(
parameters
.
substr
(
needle
,
id_length
));
if
(
profileLevelID
.
length
()
!=
id_length
)
return
;
int
result
;
std
::
stringstream
ss
;
ss
<<
profileLevelID
;
ss
>>
std
::
hex
>>
result
;
// profile-level id consists of three bytes
const
unsigned
char
profile_idc
=
result
>>
16
;
// 42xxxx -> 42
const
unsigned
char
profile_iop
=
((
result
>>
8
)
&
0xff
);
// xx80xx -> 80
ctx
->
level
=
result
&
0xff
;
// xxxx0d -> 0d
switch
(
profile_idc
)
{
case
FF_PROFILE_H264_BASELINE
:
// check constraint_set_1_flag
ctx
->
profile
|=
(
profile_iop
&
0x40
)
>>
6
?
FF_PROFILE_H264_CONSTRAINED
:
0
;
break
;
case
FF_PROFILE_H264_HIGH_10
:
case
FF_PROFILE_H264_HIGH_422
:
case
FF_PROFILE_H264_HIGH_444_PREDICTIVE
:
// check constraint_set_3_flag
ctx
->
profile
|=
(
profile_iop
&
0x10
)
>>
4
?
FF_PROFILE_H264_INTRA
:
0
;
break
;
}
DEBUG
(
"Using profile %x and level %d"
,
ctx
->
profile
,
ctx
->
level
);
}
}
void
VideoSendThread
::
setup
()
{
...
...
@@ -191,12 +238,11 @@ void VideoSendThread::setup()
/* let x264 preset override our encoder settings */
if
(
args_
[
"codec"
]
==
"libx264"
)
{
forcePresetX264
();
// FIXME: this should be parsed from the fmtp:profile-level-id
// attribute of our peer, it will determine what profile and
// level we are sending (i.e. that they can accept).
e
ncoderCtx_
->
profile
=
FF_PROFILE_H264_CONSTRAINED_BASELINE
;
encoderCtx_
->
level
=
0x0d
;
// => 13 aka 1.3
e
xtractProfileLevelID
(
args_
[
"parameters"
],
encoderCtx_
)
;
forcePresetX264
();
}
scaledPicture_
=
avcodec_alloc_frame
();
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment