mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-04 09:42:19 +00:00
avaudenc: port to send_frame / receive_packet
https://bugzilla.gnome.org/show_bug.cgi?id=792900
This commit is contained in:
parent
3e8709d21a
commit
8562f10969
1 changed files with 61 additions and 50 deletions
|
@ -402,15 +402,13 @@ buffer_info_free (void *opaque, guint8 * data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_ffmpegaudenc_encode_audio (GstFFMpegAudEnc * ffmpegaudenc,
|
gst_ffmpegaudenc_send_frame (GstFFMpegAudEnc * ffmpegaudenc, GstBuffer * buffer)
|
||||||
GstBuffer * buffer, gint * have_data)
|
|
||||||
{
|
{
|
||||||
GstAudioEncoder *enc;
|
GstAudioEncoder *enc;
|
||||||
AVCodecContext *ctx;
|
AVCodecContext *ctx;
|
||||||
gint res;
|
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
|
gint res;
|
||||||
GstAudioInfo *info;
|
GstAudioInfo *info;
|
||||||
AVPacket *pkt;
|
|
||||||
AVFrame *frame = ffmpegaudenc->frame;
|
AVFrame *frame = ffmpegaudenc->frame;
|
||||||
gboolean planar;
|
gboolean planar;
|
||||||
gint nsamples = -1;
|
gint nsamples = -1;
|
||||||
|
@ -419,8 +417,6 @@ gst_ffmpegaudenc_encode_audio (GstFFMpegAudEnc * ffmpegaudenc,
|
||||||
|
|
||||||
ctx = ffmpegaudenc->context;
|
ctx = ffmpegaudenc->context;
|
||||||
|
|
||||||
pkt = g_slice_new0 (AVPacket);
|
|
||||||
|
|
||||||
if (buffer != NULL) {
|
if (buffer != NULL) {
|
||||||
BufferInfo *buffer_info = g_slice_new0 (BufferInfo);
|
BufferInfo *buffer_info = g_slice_new0 (BufferInfo);
|
||||||
guint8 *audio_in;
|
guint8 *audio_in;
|
||||||
|
@ -529,28 +525,47 @@ gst_ffmpegaudenc_encode_audio (GstFFMpegAudEnc * ffmpegaudenc,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we have a frame to feed the encoder */
|
/* we have a frame to feed the encoder */
|
||||||
res = avcodec_encode_audio2 (ctx, pkt, frame, have_data);
|
res = avcodec_send_frame (ctx, frame);
|
||||||
|
|
||||||
av_frame_unref (frame);
|
av_frame_unref (frame);
|
||||||
} else {
|
} else {
|
||||||
GST_LOG_OBJECT (ffmpegaudenc, "draining");
|
GST_LOG_OBJECT (ffmpegaudenc, "draining");
|
||||||
/* flushing the encoder */
|
/* flushing the encoder */
|
||||||
res = avcodec_encode_audio2 (ctx, pkt, NULL, have_data);
|
res = avcodec_send_frame (ctx, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res < 0) {
|
if (res == 0) {
|
||||||
char error_str[128] = { 0, };
|
ret = GST_FLOW_OK;
|
||||||
|
} else if (res == AVERROR_EOF) {
|
||||||
g_slice_free (AVPacket, pkt);
|
ret = GST_FLOW_EOS;
|
||||||
av_strerror (res, error_str, sizeof (error_str));
|
} else { /* Any other return value is an error in our context */
|
||||||
GST_ERROR_OBJECT (enc, "Failed to encode buffer: %d - %s", res, error_str);
|
ret = GST_FLOW_OK;
|
||||||
return GST_FLOW_OK;
|
GST_WARNING_OBJECT (ffmpegaudenc, "Failed to encode buffer");
|
||||||
}
|
}
|
||||||
GST_LOG_OBJECT (ffmpegaudenc, "got output size %d", res);
|
|
||||||
|
|
||||||
if (*have_data) {
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_ffmpegaudenc_receive_packet (GstFFMpegAudEnc * ffmpegaudenc,
|
||||||
|
gboolean * got_packet)
|
||||||
|
{
|
||||||
|
GstAudioEncoder *enc;
|
||||||
|
AVCodecContext *ctx;
|
||||||
|
gint res;
|
||||||
|
GstFlowReturn ret;
|
||||||
|
AVPacket *pkt;
|
||||||
|
|
||||||
|
enc = GST_AUDIO_ENCODER (ffmpegaudenc);
|
||||||
|
|
||||||
|
ctx = ffmpegaudenc->context;
|
||||||
|
|
||||||
|
pkt = g_slice_new0 (AVPacket);
|
||||||
|
|
||||||
|
res = avcodec_receive_packet (ctx, pkt);
|
||||||
|
|
||||||
|
if (res == 0) {
|
||||||
GstBuffer *outbuf;
|
GstBuffer *outbuf;
|
||||||
const AVCodec *codec;
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (ffmpegaudenc, "pushing size %d", pkt->size);
|
GST_LOG_OBJECT (ffmpegaudenc, "pushing size %d", pkt->size);
|
||||||
|
|
||||||
|
@ -558,45 +573,39 @@ gst_ffmpegaudenc_encode_audio (GstFFMpegAudEnc * ffmpegaudenc,
|
||||||
gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, pkt->data,
|
gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, pkt->data,
|
||||||
pkt->size, 0, pkt->size, pkt, gst_ffmpegaudenc_free_avpacket);
|
pkt->size, 0, pkt->size, pkt, gst_ffmpegaudenc_free_avpacket);
|
||||||
|
|
||||||
codec = ffmpegaudenc->context->codec;
|
ret =
|
||||||
if ((codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) || !buffer) {
|
gst_audio_encoder_finish_frame (enc, outbuf,
|
||||||
/* FIXME: Not really correct, as -1 means "all the samples we got
|
pkt->duration > 0 ? pkt->duration : -1);
|
||||||
given so far", which may not be true depending on the codec,
|
*got_packet = TRUE;
|
||||||
but we have no way to know AFAICT */
|
|
||||||
ret = gst_audio_encoder_finish_frame (enc, outbuf, -1);
|
|
||||||
} else {
|
|
||||||
ret = gst_audio_encoder_finish_frame (enc, outbuf, nsamples);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
GST_LOG_OBJECT (ffmpegaudenc, "no output produced");
|
GST_LOG_OBJECT (ffmpegaudenc, "no output produced");
|
||||||
g_slice_free (AVPacket, pkt);
|
g_slice_free (AVPacket, pkt);
|
||||||
ret = GST_FLOW_OK;
|
ret = GST_FLOW_OK;
|
||||||
|
*got_packet = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static GstFlowReturn
|
||||||
gst_ffmpegaudenc_drain (GstFFMpegAudEnc * ffmpegaudenc)
|
gst_ffmpegaudenc_drain (GstFFMpegAudEnc * ffmpegaudenc)
|
||||||
{
|
{
|
||||||
GstFFMpegAudEncClass *oclass;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
gboolean got_packet;
|
||||||
|
|
||||||
oclass = (GstFFMpegAudEncClass *) (G_OBJECT_GET_CLASS (ffmpegaudenc));
|
ret = gst_ffmpegaudenc_send_frame (ffmpegaudenc, NULL);
|
||||||
|
|
||||||
if (oclass->in_plugin->capabilities & AV_CODEC_CAP_DELAY) {
|
|
||||||
gint have_data, try = 0;
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (ffmpegaudenc,
|
|
||||||
"codec has delay capabilities, calling until libav has drained everything");
|
|
||||||
|
|
||||||
|
if (ret == GST_FLOW_OK) {
|
||||||
do {
|
do {
|
||||||
GstFlowReturn ret;
|
ret = gst_ffmpegaudenc_receive_packet (ffmpegaudenc, &got_packet);
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
ret = gst_ffmpegaudenc_encode_audio (ffmpegaudenc, NULL, &have_data);
|
|
||||||
if (ret != GST_FLOW_OK || have_data == 0)
|
|
||||||
break;
|
break;
|
||||||
} while (try++ < 10);
|
} while (got_packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
avcodec_flush_buffers (ffmpegaudenc->context);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
|
@ -604,17 +613,15 @@ gst_ffmpegaudenc_handle_frame (GstAudioEncoder * encoder, GstBuffer * inbuf)
|
||||||
{
|
{
|
||||||
GstFFMpegAudEnc *ffmpegaudenc;
|
GstFFMpegAudEnc *ffmpegaudenc;
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
gint have_data;
|
gboolean got_packet;
|
||||||
|
|
||||||
ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
|
ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
|
||||||
|
|
||||||
if (G_UNLIKELY (!ffmpegaudenc->opened))
|
if (G_UNLIKELY (!ffmpegaudenc->opened))
|
||||||
goto not_negotiated;
|
goto not_negotiated;
|
||||||
|
|
||||||
if (!inbuf) {
|
if (!inbuf)
|
||||||
gst_ffmpegaudenc_drain (ffmpegaudenc);
|
return gst_ffmpegaudenc_drain (ffmpegaudenc);
|
||||||
return GST_FLOW_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
inbuf = gst_buffer_ref (inbuf);
|
inbuf = gst_buffer_ref (inbuf);
|
||||||
|
|
||||||
|
@ -632,10 +639,14 @@ gst_ffmpegaudenc_handle_frame (GstAudioEncoder * encoder, GstBuffer * inbuf)
|
||||||
info->channels, info->position, ffmpegaudenc->ffmpeg_layout);
|
info->channels, info->position, ffmpegaudenc->ffmpeg_layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = gst_ffmpegaudenc_encode_audio (ffmpegaudenc, inbuf, &have_data);
|
ret = gst_ffmpegaudenc_send_frame (ffmpegaudenc, inbuf);
|
||||||
|
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
goto push_failed;
|
goto send_frame_failed;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = gst_ffmpegaudenc_receive_packet (ffmpegaudenc, &got_packet);
|
||||||
|
} while (got_packet);
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
|
@ -647,9 +658,9 @@ not_negotiated:
|
||||||
gst_buffer_unref (inbuf);
|
gst_buffer_unref (inbuf);
|
||||||
return GST_FLOW_NOT_NEGOTIATED;
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
}
|
}
|
||||||
push_failed:
|
send_frame_failed:
|
||||||
{
|
{
|
||||||
GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to push buffer %d (%s)", ret,
|
GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to send frame %d (%s)", ret,
|
||||||
gst_flow_get_name (ret));
|
gst_flow_get_name (ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue