mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-23 17:14:23 +00:00
avaudenc: fix audio encoder flushing according to libav docs
* @param[in] frame AVFrame containing the raw audio data to be encoded. * May be NULL when flushing an encoder that has the * CODEC_CAP_DELAY capability set. The AVFrame itself should be null, not the frame.data pointer https://bugzilla.gnome.org/show_bug.cgi?id=724536
This commit is contained in:
parent
7f5132b34f
commit
845b874575
1 changed files with 87 additions and 77 deletions
|
@ -425,98 +425,108 @@ gst_ffmpegaudenc_encode_audio (GstFFMpegAudEnc * ffmpegaudenc,
|
||||||
|
|
||||||
ctx = ffmpegaudenc->context;
|
ctx = ffmpegaudenc->context;
|
||||||
|
|
||||||
GST_LOG_OBJECT (ffmpegaudenc, "encoding buffer ");
|
GST_LOG_OBJECT (ffmpegaudenc, "encoding buffer %p size:%u", audio_in,
|
||||||
|
in_size);
|
||||||
|
|
||||||
memset (&pkt, 0, sizeof (pkt));
|
memset (&pkt, 0, sizeof (pkt));
|
||||||
memset (&frame, 0, sizeof (frame));
|
|
||||||
avcodec_get_frame_defaults (&frame);
|
|
||||||
|
|
||||||
info = gst_audio_encoder_get_audio_info (enc);
|
if (audio_in != NULL) {
|
||||||
planar = av_sample_fmt_is_planar (ffmpegaudenc->context->sample_fmt);
|
memset (&frame, 0, sizeof (frame));
|
||||||
|
avcodec_get_frame_defaults (&frame);
|
||||||
|
|
||||||
if (planar && info->channels > 1) {
|
info = gst_audio_encoder_get_audio_info (enc);
|
||||||
gint channels, nsamples;
|
planar = av_sample_fmt_is_planar (ffmpegaudenc->context->sample_fmt);
|
||||||
gint i, j;
|
|
||||||
|
|
||||||
nsamples = frame.nb_samples = in_size / info->bpf;
|
if (planar && info->channels > 1) {
|
||||||
channels = info->channels;
|
gint channels, nsamples;
|
||||||
|
gint i, j;
|
||||||
|
|
||||||
|
nsamples = frame.nb_samples = in_size / info->bpf;
|
||||||
|
channels = info->channels;
|
||||||
|
|
||||||
|
if (info->channels > AV_NUM_DATA_POINTERS) {
|
||||||
|
frame.extended_data = g_new (uint8_t *, info->channels);
|
||||||
|
} else {
|
||||||
|
frame.extended_data = frame.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.extended_data[0] = g_malloc (in_size);
|
||||||
|
frame.linesize[0] = in_size / channels;
|
||||||
|
for (i = 1; i < channels; i++)
|
||||||
|
frame.extended_data[i] = frame.extended_data[i - 1] + frame.linesize[0];
|
||||||
|
|
||||||
|
switch (info->finfo->width) {
|
||||||
|
case 8:{
|
||||||
|
const guint8 *idata = (const guint8 *) audio_in;
|
||||||
|
|
||||||
|
for (i = 0; i < nsamples; i++) {
|
||||||
|
for (j = 0; j < channels; j++) {
|
||||||
|
((guint8 *) frame.extended_data[j])[i] = idata[j];
|
||||||
|
}
|
||||||
|
idata += channels;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 16:{
|
||||||
|
const guint16 *idata = (const guint16 *) audio_in;
|
||||||
|
|
||||||
|
for (i = 0; i < nsamples; i++) {
|
||||||
|
for (j = 0; j < channels; j++) {
|
||||||
|
((guint16 *) frame.extended_data[j])[i] = idata[j];
|
||||||
|
}
|
||||||
|
idata += channels;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 32:{
|
||||||
|
const guint32 *idata = (const guint32 *) audio_in;
|
||||||
|
|
||||||
|
for (i = 0; i < nsamples; i++) {
|
||||||
|
for (j = 0; j < channels; j++) {
|
||||||
|
((guint32 *) frame.extended_data[j])[i] = idata[j];
|
||||||
|
}
|
||||||
|
idata += channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 64:{
|
||||||
|
const guint64 *idata = (const guint64 *) audio_in;
|
||||||
|
|
||||||
|
for (i = 0; i < nsamples; i++) {
|
||||||
|
for (j = 0; j < channels; j++) {
|
||||||
|
((guint64 *) frame.extended_data[j])[i] = idata[j];
|
||||||
|
}
|
||||||
|
idata += channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (info->channels > AV_NUM_DATA_POINTERS) {
|
|
||||||
frame.extended_data = g_new (uint8_t *, info->channels);
|
|
||||||
} else {
|
} else {
|
||||||
|
frame.data[0] = audio_in;
|
||||||
frame.extended_data = frame.data;
|
frame.extended_data = frame.data;
|
||||||
|
frame.linesize[0] = in_size;
|
||||||
|
frame.nb_samples = in_size / info->bpf;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame.extended_data[0] = g_malloc (in_size);
|
/* we have a frame to feed the encoder */
|
||||||
frame.linesize[0] = in_size / channels;
|
res = avcodec_encode_audio2 (ctx, &pkt, &frame, have_data);
|
||||||
for (i = 1; i < channels; i++)
|
|
||||||
frame.extended_data[i] = frame.extended_data[i - 1] + frame.linesize[0];
|
|
||||||
|
|
||||||
switch (info->finfo->width) {
|
if (planar && info->channels > 1)
|
||||||
case 8:{
|
g_free (frame.data[0]);
|
||||||
const guint8 *idata = (const guint8 *) audio_in;
|
if (frame.extended_data != frame.data)
|
||||||
|
g_free (frame.extended_data);
|
||||||
for (i = 0; i < nsamples; i++) {
|
|
||||||
for (j = 0; j < channels; j++) {
|
|
||||||
((guint8 *) frame.extended_data[j])[i] = idata[j];
|
|
||||||
}
|
|
||||||
idata += channels;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 16:{
|
|
||||||
const guint16 *idata = (const guint16 *) audio_in;
|
|
||||||
|
|
||||||
for (i = 0; i < nsamples; i++) {
|
|
||||||
for (j = 0; j < channels; j++) {
|
|
||||||
((guint16 *) frame.extended_data[j])[i] = idata[j];
|
|
||||||
}
|
|
||||||
idata += channels;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 32:{
|
|
||||||
const guint32 *idata = (const guint32 *) audio_in;
|
|
||||||
|
|
||||||
for (i = 0; i < nsamples; i++) {
|
|
||||||
for (j = 0; j < channels; j++) {
|
|
||||||
((guint32 *) frame.extended_data[j])[i] = idata[j];
|
|
||||||
}
|
|
||||||
idata += channels;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 64:{
|
|
||||||
const guint64 *idata = (const guint64 *) audio_in;
|
|
||||||
|
|
||||||
for (i = 0; i < nsamples; i++) {
|
|
||||||
for (j = 0; j < channels; j++) {
|
|
||||||
((guint64 *) frame.extended_data[j])[i] = idata[j];
|
|
||||||
}
|
|
||||||
idata += channels;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
frame.data[0] = audio_in;
|
/* flushing the encoder */
|
||||||
frame.extended_data = frame.data;
|
res = avcodec_encode_audio2 (ctx, &pkt, NULL, have_data);
|
||||||
frame.linesize[0] = in_size;
|
|
||||||
frame.nb_samples = in_size / info->bpf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res = avcodec_encode_audio2 (ctx, &pkt, &frame, have_data);
|
|
||||||
if (planar && info->channels > 1)
|
|
||||||
g_free (frame.data[0]);
|
|
||||||
if (frame.extended_data != frame.data)
|
|
||||||
g_free (frame.extended_data);
|
|
||||||
|
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
char error_str[128] = { 0, };
|
char error_str[128] = { 0, };
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue