ffmpeg plugin: improve encoding format negociation
The ffmpeg encoders are restricted on which raw formats they accept (each with different constraints). When asked to encode something, the ffmpeg encoder now checks the codec capabilities and if the suggested input format does not match, modifies it to something the codec can actually handle. Enable "experimental" codecs, as this is needed for AAC support in ffmpeg 0.10. This allows format negociation to work properly, and as a result we can enable several new audio formats: AAC (for MPEG family only), AC3, and raw audio. Declare MKV as B_ANY_FORMAT_FAMILY since it is designed to be a generic container (so it is possible to put AAC in MKV). Also remove duplicate entries for AC3.
This commit is contained in:
parent
ca747629f9
commit
5e0e16894d
@ -462,12 +462,12 @@ AVCodecEncoder::_Setup()
|
||||
if (fContext->codec_id == CODEC_ID_MPEG2VIDEO) {
|
||||
// Just for testing, we also add B frames */
|
||||
fContext->max_b_frames = 2;
|
||||
} else if (fContext->codec_id == CODEC_ID_MPEG1VIDEO){
|
||||
} else if (fContext->codec_id == CODEC_ID_MPEG1VIDEO) {
|
||||
// Needed to avoid using macroblocks in which some coeffs overflow.
|
||||
// This does not happen with normal video, it just happens here as
|
||||
// the motion of the chroma plane does not match the luma plane.
|
||||
fContext->mb_decision = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Unfortunately, we may fail later, when we try to open the codec
|
||||
// for real... but we need to delay this because we still allow
|
||||
@ -491,6 +491,8 @@ AVCodecEncoder::_OpenCodecIfNeeded()
|
||||
if (fCodecInitStatus == CODEC_INIT_FAILED)
|
||||
return false;
|
||||
|
||||
fContext->strict_std_compliance = -2;
|
||||
|
||||
// Open the codec
|
||||
int result = avcodec_open(fContext, fCodec);
|
||||
if (result >= 0)
|
||||
|
@ -171,6 +171,9 @@ AVFormatWriter::StreamCookie::Init(media_format* format,
|
||||
|
||||
// channels
|
||||
fStream->codec->channels = format->u.raw_audio.channel_count;
|
||||
|
||||
// set fStream to the audio format we want to use. This is only a hint
|
||||
// (each encoder has a different set of accepted formats)
|
||||
switch (format->u.raw_audio.format) {
|
||||
case media_raw_audio_format::B_AUDIO_FLOAT:
|
||||
fStream->codec->sample_fmt = AV_SAMPLE_FMT_FLT;
|
||||
@ -193,6 +196,49 @@ AVFormatWriter::StreamCookie::Init(media_format* format,
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
break;
|
||||
}
|
||||
|
||||
// Now negociate the actual format with the encoder
|
||||
// First check if the requested format is acceptable
|
||||
AVCodec* codec = avcodec_find_encoder(fStream->codec->codec_id);
|
||||
const enum AVSampleFormat *p = codec->sample_fmts;
|
||||
for (; *p != -1; p++) {
|
||||
if (*p == fStream->codec->sample_fmt)
|
||||
break;
|
||||
}
|
||||
// If not, force one of the acceptable ones
|
||||
if (*p == -1) {
|
||||
fStream->codec->sample_fmt = codec->sample_fmts[0];
|
||||
|
||||
// And finally set the format struct to the accepted format. It is
|
||||
// then up to the caller to make sure we get data matching that
|
||||
// format.
|
||||
switch (fStream->codec->sample_fmt) {
|
||||
case AV_SAMPLE_FMT_FLT:
|
||||
format->u.raw_audio.format
|
||||
= media_raw_audio_format::B_AUDIO_FLOAT;
|
||||
break;
|
||||
case AV_SAMPLE_FMT_DBL:
|
||||
format->u.raw_audio.format
|
||||
= media_raw_audio_format::B_AUDIO_DOUBLE;
|
||||
break;
|
||||
case AV_SAMPLE_FMT_S32:
|
||||
format->u.raw_audio.format
|
||||
= media_raw_audio_format::B_AUDIO_INT;
|
||||
break;
|
||||
case AV_SAMPLE_FMT_S16:
|
||||
format->u.raw_audio.format
|
||||
= media_raw_audio_format::B_AUDIO_SHORT;
|
||||
break;
|
||||
case AV_SAMPLE_FMT_U8:
|
||||
format->u.raw_audio.format
|
||||
= media_raw_audio_format::B_AUDIO_UCHAR;
|
||||
break;
|
||||
default:
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (format->u.raw_audio.channel_mask == 0) {
|
||||
// guess the channel mask...
|
||||
switch (format->u.raw_audio.channel_count) {
|
||||
@ -418,6 +464,7 @@ AVFormatWriter::CommitHeader()
|
||||
// we have no idea (in the future) what CodecID some encoder uses,
|
||||
// it may be an encoder from a different plugin.
|
||||
AVCodecContext* codecContext = stream->codec;
|
||||
codecContext->strict_std_compliance = -2;
|
||||
AVCodec* codec = avcodec_find_encoder(codecContext->codec_id);
|
||||
if (codec == NULL || avcodec_open(codecContext, codec) < 0) {
|
||||
TRACE(" stream[%u] - failed to open AVCodecContext\n", i);
|
||||
|
@ -102,6 +102,19 @@ const EncoderDescription gEncoderTable[] = {
|
||||
B_MEDIA_ENCODED_AUDIO,
|
||||
10
|
||||
},
|
||||
{
|
||||
{
|
||||
"Advanced Audio Coding (AAC)",
|
||||
"aac",
|
||||
0,
|
||||
CODEC_ID_AAC,
|
||||
{ 0 }
|
||||
},
|
||||
B_MPEG_FORMAT_FAMILY,
|
||||
B_MEDIA_RAW_AUDIO,
|
||||
B_MEDIA_ENCODED_AUDIO,
|
||||
10
|
||||
},
|
||||
{
|
||||
{
|
||||
"Raw audio",
|
||||
@ -115,24 +128,9 @@ const EncoderDescription gEncoderTable[] = {
|
||||
B_MEDIA_ENCODED_AUDIO,
|
||||
1
|
||||
},
|
||||
// All of those crash ffmpeg in one way or another...
|
||||
#if 0
|
||||
{
|
||||
{
|
||||
"Advanced Audio Coding (AAC)",
|
||||
"aac",
|
||||
0,
|
||||
CODEC_ID_AAC,
|
||||
{ 0 }
|
||||
},
|
||||
B_ANY_FORMAT_FAMILY,
|
||||
B_MEDIA_RAW_AUDIO,
|
||||
B_MEDIA_ENCODED_AUDIO,
|
||||
10
|
||||
},
|
||||
{
|
||||
{
|
||||
"Dolby AC-3",
|
||||
"Dolby Digital (AC-3)",
|
||||
"ac3",
|
||||
0,
|
||||
CODEC_ID_AC3,
|
||||
@ -143,6 +141,7 @@ const EncoderDescription gEncoderTable[] = {
|
||||
B_MEDIA_ENCODED_AUDIO,
|
||||
10
|
||||
},
|
||||
#if 0
|
||||
{
|
||||
{
|
||||
"Apple Lossless Audio Codec",
|
||||
@ -221,19 +220,6 @@ const EncoderDescription gEncoderTable[] = {
|
||||
B_MEDIA_ENCODED_AUDIO,
|
||||
10
|
||||
},
|
||||
{
|
||||
{
|
||||
"Dolby Digital (AC-3)",
|
||||
"ac3",
|
||||
0,
|
||||
CODEC_ID_AC3,
|
||||
{ 0 }
|
||||
},
|
||||
B_ANY_FORMAT_FAMILY,
|
||||
B_MEDIA_RAW_AUDIO,
|
||||
B_MEDIA_ENCODED_AUDIO,
|
||||
10
|
||||
},
|
||||
{
|
||||
{
|
||||
"Vorbis audio",
|
||||
|
@ -121,7 +121,7 @@ const media_file_format gMuxerTable[] = {
|
||||
| media_file_format::B_KNOWS_ENCODED_VIDEO
|
||||
| media_file_format::B_KNOWS_ENCODED_AUDIO,
|
||||
{ 0 },
|
||||
B_QUICKTIME_FORMAT_FAMILY,
|
||||
B_ANY_FORMAT_FAMILY,
|
||||
100,
|
||||
{ 0 },
|
||||
"video/x-matroska",
|
||||
|
Loading…
Reference in New Issue
Block a user