ext/ffmpeg/gstffmpegcodecmap.*: Add mapping for EAC3 and QCELP audio codecs.

Original commit message from CVS:
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ff_aud_caps_new),
(gst_ffmpeg_codecid_to_caps), (gst_ffmpeg_smpfmt_to_caps),
(gst_ffmpeg_codectype_to_caps), (gst_ffmpeg_caps_to_smpfmt),
(gst_ffmpeg_caps_to_codecid), (av_smp_format_depth):
* ext/ffmpeg/gstffmpegcodecmap.h:
Add mapping for EAC3 and QCELP audio codecs.
Add conversion functions for all available audo SampleFormat.
* ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_open),
(gst_ffmpegdec_setcaps), (gst_ffmpegdec_negotiate),
(clip_audio_buffer), (gst_ffmpegdec_audio_frame):
Remove assumptions that we can only handle stereo 16bit signed integer
audio, and store the depth locally.
This commit is contained in:
Edward Hervey 2008-12-17 12:05:12 +00:00
parent 75694feb3b
commit 3d089f4862
4 changed files with 125 additions and 20 deletions

View file

@ -1,3 +1,18 @@
2008-12-17 Edward Hervey <edward.hervey@collabora.co.uk>
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ff_aud_caps_new),
(gst_ffmpeg_codecid_to_caps), (gst_ffmpeg_smpfmt_to_caps),
(gst_ffmpeg_codectype_to_caps), (gst_ffmpeg_caps_to_smpfmt),
(gst_ffmpeg_caps_to_codecid), (av_smp_format_depth):
* ext/ffmpeg/gstffmpegcodecmap.h:
Add mapping for EAC3 and QCELP audio codecs.
Add conversion functions for all available audo SampleFormat.
* ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_open),
(gst_ffmpegdec_setcaps), (gst_ffmpegdec_negotiate),
(clip_audio_buffer), (gst_ffmpegdec_audio_frame):
Remove assumptions that we can only handle stereo 16bit signed integer
audio, and store the depth locally.
2008-12-16 Stefan Kost <ensonic@users.sf.net>
* configure.ac:

View file

@ -322,6 +322,7 @@ gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id,
rates = l_rates;
break;
}
case CODEC_ID_EAC3:
case CODEC_ID_AC3:
{
const static gint l_rates[] = { 48000, 44100, 32000 };
@ -361,6 +362,7 @@ gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id,
* they support, we whitelist them here. */
switch (codec_id) {
case CODEC_ID_AC3:
case CODEC_ID_EAC3:
case CODEC_ID_AAC:
case CODEC_ID_DTS:
maxchannels = 6;
@ -560,6 +562,11 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id,
caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-ac3", NULL);
break;
case CODEC_ID_EAC3:
/* FIXME: bitrate */
caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-eac3", NULL);
break;
case CODEC_ID_ATRAC3:
caps = gst_ff_aud_caps_new (context, codec_id, "audio/atrac3", NULL);
break;
@ -986,6 +993,10 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id,
gst_ff_aud_caps_new (context, codec_id, "audio/x-truespeech", NULL);
break;
case CODEC_ID_QCELP:
caps = gst_ff_aud_caps_new (context, codec_id, "audio/qcelp", NULL);
break;
case CODEC_ID_WS_VQA:
case CODEC_ID_IDCIN:
case CODEC_ID_8BPS:
@ -1529,6 +1540,7 @@ gst_ffmpeg_smpfmt_to_caps (enum SampleFormat sample_fmt,
GstCaps *caps = NULL;
int bpp = 0;
gboolean integer = TRUE;
gboolean signedness = FALSE;
switch (sample_fmt) {
@ -1537,16 +1549,36 @@ gst_ffmpeg_smpfmt_to_caps (enum SampleFormat sample_fmt,
bpp = 16;
break;
case SAMPLE_FMT_S32:
signedness = TRUE;
bpp = 32;
break;
case SAMPLE_FMT_FLT:
integer = FALSE;
bpp = 32;
break;
case SAMPLE_FMT_DBL:
integer = FALSE;
bpp = 64;
break;
default:
/* .. */
break;
}
if (bpp) {
caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-raw-int",
"signed", G_TYPE_BOOLEAN, signedness,
"endianness", G_TYPE_INT, G_BYTE_ORDER,
"width", G_TYPE_INT, bpp, "depth", G_TYPE_INT, bpp, NULL);
if (integer) {
caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-raw-int",
"signed", G_TYPE_BOOLEAN, signedness,
"endianness", G_TYPE_INT, G_BYTE_ORDER,
"width", G_TYPE_INT, bpp, "depth", G_TYPE_INT, bpp, NULL);
} else {
caps = gst_ff_aud_caps_new (context, codec_id, "audio/x-raw-float",
"endianness", G_TYPE_INT, G_BYTE_ORDER,
"width", G_TYPE_INT, bpp, NULL);
}
}
if (caps != NULL) {
@ -1603,7 +1635,7 @@ gst_ffmpeg_codectype_to_caps (enum CodecType codec_type,
ctx.channels = -1;
caps = gst_caps_new_empty ();
for (i = 0; i <= SAMPLE_FMT_S16; i++) {
for (i = 0; i <= SAMPLE_FMT_DBL; i++) {
temp = gst_ffmpeg_smpfmt_to_caps (i, encode ? &ctx : NULL, codec_id);
if (temp != NULL) {
gst_caps_append (caps, temp);
@ -1646,13 +1678,29 @@ gst_ffmpeg_caps_to_smpfmt (const GstCaps * caps,
if (!raw)
return;
if (gst_structure_get_int (structure, "width", &width) &&
gst_structure_get_int (structure, "depth", &depth) &&
gst_structure_get_boolean (structure, "signed", &signedness) &&
gst_structure_get_int (structure, "endianness", &endianness)) {
if (width == 16 && depth == 16 &&
endianness == G_BYTE_ORDER && signedness == TRUE) {
context->sample_fmt = SAMPLE_FMT_S16;
if (!strcmp (gst_structure_get_name (structure), "audio/x-raw-float")) {
/* FLOAT */
if (gst_structure_get_int (structure, "width", &width) &&
gst_structure_get_int (structure, "endianness", &endianness)) {
if (endianness == G_BYTE_ORDER) {
if (width == 32)
context->sample_fmt = SAMPLE_FMT_FLT;
else if (width == 64)
context->sample_fmt = SAMPLE_FMT_DBL;
}
}
} else {
/* INT */
if (gst_structure_get_int (structure, "width", &width) &&
gst_structure_get_int (structure, "depth", &depth) &&
gst_structure_get_boolean (structure, "signed", &signedness) &&
gst_structure_get_int (structure, "endianness", &endianness)) {
if ((endianness == G_BYTE_ORDER) && (signedness == TRUE)) {
if ((width == 16) && (depth == 16))
context->sample_fmt = SAMPLE_FMT_S16;
else if ((width == 32) && (depth == 32))
context->sample_fmt = SAMPLE_FMT_S32;
}
}
}
}
@ -2550,6 +2598,9 @@ gst_ffmpeg_caps_to_codecid (const GstCaps * caps, AVCodecContext * context)
} else if (!strcmp (mimetype, "audio/x-ac3")) {
id = CODEC_ID_AC3;
audio = TRUE;
} else if (!strcmp (mimetype, "audio/x-eac3")) {
id = CODEC_ID_EAC3;
audio = TRUE;
} else if (!strcmp (mimetype, "audio/atrac3")) {
id = CODEC_ID_ATRAC3;
audio = TRUE;
@ -2821,6 +2872,9 @@ gst_ffmpeg_caps_to_codecid (const GstCaps * caps, AVCodecContext * context)
} else if (!strcmp (mimetype, "audio/AMR-WB")) {
id = CODEC_ID_AMR_WB;
audio = TRUE;
} else if (!strcmp (mimetype, "audio/qcelp")) {
id = CODEC_ID_QCELP;
audio = TRUE;
} else if (!strcmp (mimetype, "video/x-h264")) {
id = CODEC_ID_H264;
video = TRUE;
@ -3236,3 +3290,28 @@ gst_ffmpeg_avpicture_fill (AVPicture * picture,
return 0;
}
gint
av_smp_format_depth (enum SampleFormat smp_fmt)
{
gint depth = -1;
switch (smp_fmt) {
case SAMPLE_FMT_U8:
depth = 1;
break;
case SAMPLE_FMT_S16:
depth = 2;
break;
case SAMPLE_FMT_S32:
case SAMPLE_FMT_FLT:
depth = 4;
break;
case SAMPLE_FMT_DBL:
depth = 8;
break;
default:
GST_ERROR ("UNHANDLED SAMPLE FORMAT !");
break;
}
return depth;
}

View file

@ -163,4 +163,7 @@ gst_ffmpeg_time_gst_to_ff (guint64 time, AVRational base)
void
gst_ffmpeg_init_pix_fmt_info();
gint
av_smp_format_depth(enum SampleFormat smp_fmt);
#endif /* __GST_FFMPEG_CODECMAP_H__ */

View file

@ -67,6 +67,7 @@ struct _GstFFMpegDec
{
gint channels;
gint samplerate;
gint depth;
} audio;
} format;
gboolean waiting_for_key;
@ -587,6 +588,7 @@ gst_ffmpegdec_open (GstFFMpegDec * ffmpegdec)
case CODEC_TYPE_AUDIO:
ffmpegdec->format.audio.samplerate = 0;
ffmpegdec->format.audio.channels = 0;
ffmpegdec->format.audio.depth = 0;
break;
default:
break;
@ -707,8 +709,7 @@ gst_ffmpegdec_setcaps (GstPad * pad, GstCaps * caps)
GST_DEBUG_OBJECT (ffmpegdec, "enabled direct rendering");
ffmpegdec->current_dr = TRUE;
}
}
else {
} else {
GST_DEBUG_OBJECT (ffmpegdec, "direct rendering not supported");
}
}
@ -1075,16 +1076,22 @@ gst_ffmpegdec_negotiate (GstFFMpegDec * ffmpegdec)
ffmpegdec->format.video.pix_fmt = ffmpegdec->context->pix_fmt;
break;
case CODEC_TYPE_AUDIO:
{
gint depth = av_smp_format_depth (ffmpegdec->context->sample_fmt);
if (ffmpegdec->format.audio.samplerate ==
ffmpegdec->context->sample_rate &&
ffmpegdec->format.audio.channels == ffmpegdec->context->channels)
ffmpegdec->format.audio.channels == ffmpegdec->context->channels &&
ffmpegdec->format.audio.depth == depth)
return TRUE;
GST_DEBUG_OBJECT (ffmpegdec,
"Renegotiating audio from %dHz@%dchannels to %dHz@%dchannels",
"Renegotiating audio from %dHz@%dchannels (%d) to %dHz@%dchannels (%d)",
ffmpegdec->format.audio.samplerate, ffmpegdec->format.audio.channels,
ffmpegdec->context->sample_rate, ffmpegdec->context->channels);
ffmpegdec->format.audio.depth,
ffmpegdec->context->sample_rate, ffmpegdec->context->channels, depth);
ffmpegdec->format.audio.samplerate = ffmpegdec->context->sample_rate;
ffmpegdec->format.audio.channels = ffmpegdec->context->channels;
ffmpegdec->format.audio.depth = depth;
}
break;
default:
break;
@ -1738,7 +1745,7 @@ clip_audio_buffer (GstFFMpegDec * dec, GstBuffer * buf, GstClockTime in_ts,
/* bring clipped time to bytes */
diff =
gst_util_uint64_scale_int (diff, dec->format.audio.samplerate,
GST_SECOND) * (2 * dec->format.audio.channels);
GST_SECOND) * (dec->format.audio.depth * dec->format.audio.channels);
GST_DEBUG_OBJECT (dec, "clipping start to %" GST_TIME_FORMAT " %"
G_GINT64_FORMAT " bytes", GST_TIME_ARGS (ctime), diff);
@ -1750,7 +1757,7 @@ clip_audio_buffer (GstFFMpegDec * dec, GstBuffer * buf, GstClockTime in_ts,
/* bring clipped time to bytes */
diff =
gst_util_uint64_scale_int (diff, dec->format.audio.samplerate,
GST_SECOND) * (2 * dec->format.audio.channels);
GST_SECOND) * (dec->format.audio.depth * dec->format.audio.channels);
GST_DEBUG_OBJECT (dec, "clipping stop to %" GST_TIME_FORMAT " %"
G_GINT64_FORMAT " bytes", GST_TIME_ARGS (cstop), diff);
@ -1824,7 +1831,8 @@ gst_ffmpegdec_audio_frame (GstFFMpegDec * ffmpegdec,
* 1) calculate based on number of samples
*/
in_duration = gst_util_uint64_scale_int (have_data, GST_SECOND,
2 * ffmpegdec->context->channels * ffmpegdec->context->sample_rate);
ffmpegdec->format.audio.depth * ffmpegdec->format.audio.channels *
ffmpegdec->format.audio.samplerate);
GST_DEBUG_OBJECT (ffmpegdec,
"Buffer created. Size:%d , timestamp:%" GST_TIME_FORMAT " , duration:%"