mpeg2enc: finalize GstVideoEncoder port

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1491>
This commit is contained in:
Mathieu Duponchelle 2020-08-04 16:05:33 +02:00 committed by GStreamer Merge Bot
parent c9d10e2277
commit 2dfceac9fc
4 changed files with 52 additions and 50 deletions

View file

@ -104,6 +104,8 @@ static void gst_mpeg2enc_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec); guint prop_id, GValue * value, GParamSpec * pspec);
static void gst_mpeg2enc_set_property (GObject * object, static void gst_mpeg2enc_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec); guint prop_id, const GValue * value, GParamSpec * pspec);
static gboolean gst_mpeg2enc_src_activate_mode (GstPad * pad, GstObject * parent,
GstPadMode mode, gboolean active);
#define gst_mpeg2enc_parent_class parent_class #define gst_mpeg2enc_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstMpeg2enc, gst_mpeg2enc, GST_TYPE_VIDEO_ENCODER, G_DEFINE_TYPE_WITH_CODE (GstMpeg2enc, gst_mpeg2enc, GST_TYPE_VIDEO_ENCODER,
@ -177,9 +179,38 @@ gst_mpeg2enc_init (GstMpeg2enc * enc)
enc->frames = g_queue_new (); enc->frames = g_queue_new ();
enc->started = FALSE; enc->started = FALSE;
gst_pad_set_activatemode_function (GST_VIDEO_ENCODER_SRC_PAD (enc),
GST_DEBUG_FUNCPTR (gst_mpeg2enc_src_activate_mode));
gst_mpeg2enc_reset (enc); gst_mpeg2enc_reset (enc);
} }
static gboolean
gst_mpeg2enc_src_activate_mode (GstPad * pad, GstObject * parent,
GstPadMode mode, gboolean active)
{
gboolean result = TRUE;
GstMpeg2enc *enc;
enc = GST_MPEG2ENC (parent);
if (mode != GST_PAD_MODE_PUSH)
return FALSE;
if (active) {
/* setcaps will start task once encoder is setup */
} else {
/* can only end the encoding loop by forcing eos */
GST_MPEG2ENC_MUTEX_LOCK (enc);
enc->eos = TRUE;
enc->srcresult = GST_FLOW_FLUSHING;
GST_MPEG2ENC_SIGNAL (enc);
GST_MPEG2ENC_MUTEX_UNLOCK (enc);
}
return result;
}
static void static void
gst_mpeg2enc_reset (GstMpeg2enc * enc) gst_mpeg2enc_reset (GstMpeg2enc * enc)
{ {
@ -189,8 +220,7 @@ gst_mpeg2enc_reset (GstMpeg2enc * enc)
enc->srcresult = GST_FLOW_OK; enc->srcresult = GST_FLOW_OK;
/* in case of error'ed ending */ /* in case of error'ed ending */
while ((frame = (GstVideoCodecFrame *) g_queue_pop_head (enc->frames))) while ((frame = (GstVideoCodecFrame *) g_queue_pop_head (enc->frames)));
gst_video_codec_frame_unref (frame);
if (enc->encoder) { if (enc->encoder) {
delete enc->encoder; delete enc->encoder;
@ -307,8 +337,8 @@ gst_mpeg2enc_set_format (GstVideoEncoder * video_encoder, GstVideoCodecState * s
enc->input_state = gst_video_codec_state_ref (state); enc->input_state = gst_video_codec_state_ref (state);
/* does not go well to restart stream mid-way */ /* does not go well to restart stream mid-way */
//if (enc->srcresult != GST_FLOW_CUSTOM_SUCCESS) if (enc->encoder != NULL)
// goto refuse_renegotiation; goto refuse_renegotiation;
/* since mpeg encoder does not really check, let's check caps */ /* since mpeg encoder does not really check, let's check caps */
@ -319,7 +349,6 @@ gst_mpeg2enc_set_format (GstVideoEncoder * video_encoder, GstVideoCodecState * s
"systemstream", G_TYPE_BOOLEAN, FALSE, "systemstream", G_TYPE_BOOLEAN, FALSE,
"mpegversion", G_TYPE_INT, (enc->options->mpeg == 1)?1:2, NULL); "mpegversion", G_TYPE_INT, (enc->options->mpeg == 1)?1:2, NULL);
output_state = output_state =
gst_video_encoder_set_output_state (video_encoder, gst_video_encoder_set_output_state (video_encoder,
caps, state); caps, state);
@ -327,8 +356,6 @@ gst_mpeg2enc_set_format (GstVideoEncoder * video_encoder, GstVideoCodecState * s
gst_video_encoder_negotiate (GST_VIDEO_ENCODER (enc)); gst_video_encoder_negotiate (GST_VIDEO_ENCODER (enc));
return TRUE; return TRUE;
refuse_caps: refuse_caps:
@ -337,15 +364,13 @@ refuse_caps:
return FALSE; return FALSE;
} }
/*
refuse_renegotiation: refuse_renegotiation:
{ {
GST_WARNING_OBJECT (enc, "refused renegotiation (to %" GST_PTR_FORMAT ")", GST_WARNING_OBJECT (enc, "refused renegotiation (to %" GST_PTR_FORMAT ")",
caps); state->caps);
return FALSE; return FALSE;
} }
*/
} }
static GstStructure * static GstStructure *
@ -437,7 +462,6 @@ gst_mpeg2enc_getcaps (GstVideoEncoder * video_encoder, GstCaps * filter)
break; break;
} }
GST_DEBUG_OBJECT (enc, "returned caps %" GST_PTR_FORMAT, caps);
return caps; return caps;
} }
@ -520,8 +544,6 @@ static void
gst_mpeg2enc_loop (GstVideoEncoder * video_encoder) gst_mpeg2enc_loop (GstVideoEncoder * video_encoder)
{ {
GstMpeg2enc *enc = GST_MPEG2ENC (video_encoder); GstMpeg2enc *enc = GST_MPEG2ENC (video_encoder);
GstCaps *othercaps = NULL;
gboolean ret = FALSE;
GST_DEBUG_OBJECT (enc, "encoding task loop:START"); GST_DEBUG_OBJECT (enc, "encoding task loop:START");
/* do not try to resume or start when output problems; /* do not try to resume or start when output problems;
@ -556,20 +578,6 @@ gst_mpeg2enc_loop (GstVideoEncoder * video_encoder)
} }
GST_DEBUG_OBJECT (enc, "encoding task loop: setup and init DONE"); GST_DEBUG_OBJECT (enc, "encoding task loop: setup and init DONE");
/* and set caps on other side, which should accept anyway */
othercaps = enc->encoder->getFormat ();
ret = gst_pad_set_caps (video_encoder->srcpad, othercaps);
gst_caps_unref (othercaps);
othercaps = NULL;
if (!ret) {
GST_MPEG2ENC_MUTEX_LOCK (enc);
enc->srcresult = GST_FLOW_NOT_NEGOTIATED;
GST_MPEG2ENC_SIGNAL (enc);
GST_MPEG2ENC_MUTEX_UNLOCK (enc);
goto refuse_caps;
}
GST_DEBUG_OBJECT (enc, "encoding task loop: caps OK");
/* note that init performs a pre-fill and therefore needs buffers */ /* note that init performs a pre-fill and therefore needs buffers */
/* task will stay in here during all of the encoding */ /* task will stay in here during all of the encoding */
enc->encoder->encode (); enc->encoder->encode ();
@ -601,12 +609,6 @@ done:
return; return;
} }
refuse_caps:
{
GST_WARNING_OBJECT (enc, "refused caps %" GST_PTR_FORMAT, enc->input_state->caps);
goto done;
}
encoder: encoder:
{ {
GST_ELEMENT_ERROR (enc, CORE, NEGOTIATION, (NULL), GST_ELEMENT_ERROR (enc, CORE, NEGOTIATION, (NULL),
@ -638,6 +640,7 @@ gst_mpeg2enc_handle_frame (GstVideoEncoder *video_encoder, GstVideoCodecFrame *f
GstMpeg2enc *enc = GST_MPEG2ENC (video_encoder); GstMpeg2enc *enc = GST_MPEG2ENC (video_encoder);
GST_DEBUG_OBJECT (video_encoder, "handle_frame"); GST_DEBUG_OBJECT (video_encoder, "handle_frame");
GST_MPEG2ENC_MUTEX_LOCK (enc);
if (G_UNLIKELY (enc->eos)) if (G_UNLIKELY (enc->eos))
goto eos; goto eos;
@ -647,7 +650,8 @@ gst_mpeg2enc_handle_frame (GstVideoEncoder *video_encoder, GstVideoCodecFrame *f
goto ignore; goto ignore;
GST_DEBUG_OBJECT (video_encoder, "handle_frame: flow OK"); GST_DEBUG_OBJECT (video_encoder, "handle_frame: flow OK");
g_queue_push_tail (enc->frames, gst_video_codec_frame_ref (frame)); g_queue_push_tail (enc->frames, frame);
/* frame will be released by task */ /* frame will be released by task */
if (g_queue_get_length (enc->frames) > 0 && !enc->started) { if (g_queue_get_length (enc->frames) > 0 && !enc->started) {
@ -661,13 +665,16 @@ gst_mpeg2enc_handle_frame (GstVideoEncoder *video_encoder, GstVideoCodecFrame *f
if (enc->started) if (enc->started)
GST_MPEG2ENC_SIGNAL (enc); GST_MPEG2ENC_SIGNAL (enc);
GST_MPEG2ENC_MUTEX_UNLOCK (enc);
return GST_FLOW_OK; return GST_FLOW_OK;
eos: eos:
{ {
GST_DEBUG_OBJECT (enc, "ignoring frame at end-of-stream"); GST_DEBUG_OBJECT (enc, "ignoring frame at end-of-stream");
GST_MPEG2ENC_MUTEX_UNLOCK (enc); GST_MPEG2ENC_MUTEX_UNLOCK (enc);
gst_video_codec_frame_unref (frame); gst_video_encoder_finish_frame (video_encoder, frame);
return GST_FLOW_EOS; return GST_FLOW_EOS;
} }
ignore: ignore:
@ -677,13 +684,12 @@ ignore:
GST_DEBUG_OBJECT (enc, GST_DEBUG_OBJECT (enc,
"ignoring frame because encoding task encountered %s", "ignoring frame because encoding task encountered %s",
gst_flow_get_name (enc->srcresult)); gst_flow_get_name (enc->srcresult));
enc->eos = TRUE;
GST_MPEG2ENC_MUTEX_UNLOCK (enc); GST_MPEG2ENC_MUTEX_UNLOCK (enc);
#if 0 gst_video_encoder_finish_frame (video_encoder, frame);
/* encoding loop should have ended now and can be joined */
- result = gst_pad_stop_task (video_encoder->srcpad);
#endif
gst_video_codec_frame_unref (frame);
return ret; return ret;
} }

View file

@ -500,7 +500,6 @@ GstMpeg2EncOptions::initProperties (GObjectClass * klass)
"Dual Prime Motion Estimation Mode for MPEG-2 I/P-frame only " "Dual Prime Motion Estimation Mode for MPEG-2 I/P-frame only "
"streams. Quite some players do not support this.", "streams. Quite some players do not support this.",
FALSE, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); FALSE, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
#endif
gst_type_mark_as_plugin_api (GST_TYPE_MPEG2ENC_ASPECT, (GstPluginAPIFlags) 0); gst_type_mark_as_plugin_api (GST_TYPE_MPEG2ENC_ASPECT, (GstPluginAPIFlags) 0);
gst_type_mark_as_plugin_api (GST_TYPE_MPEG2ENC_FORMAT, (GstPluginAPIFlags) 0); gst_type_mark_as_plugin_api (GST_TYPE_MPEG2ENC_FORMAT, (GstPluginAPIFlags) 0);

View file

@ -110,15 +110,14 @@ bool
guint8 *frame; guint8 *frame;
GstMpeg2enc *enc; GstMpeg2enc *enc;
GstVideoFrame vframe; GstVideoFrame vframe;
GstVideoCodecFrame *inframe; GstVideoCodecFrame *inframe = NULL;
enc = GST_MPEG2ENC (element); enc = GST_MPEG2ENC (element);
GST_MPEG2ENC_MUTEX_LOCK (enc); GST_MPEG2ENC_MUTEX_LOCK (enc);
inframe = (GstVideoCodecFrame *)g_queue_pop_head (enc->frames);
/* hang around until the element provides us with a buffer */ /* hang around until the element provides us with a buffer */
while (!inframe) { while (!(inframe = (GstVideoCodecFrame *)g_queue_pop_head (enc->frames))) {
if (enc->eos) { if (enc->eos) {
GST_MPEG2ENC_MUTEX_UNLOCK (enc); GST_MPEG2ENC_MUTEX_UNLOCK (enc);
/* inform the mpeg encoding loop that it can give up */ /* inform the mpeg encoding loop that it can give up */
@ -129,7 +128,6 @@ bool
gst_video_frame_map (&vframe, &enc->input_state->info, inframe->input_buffer, GST_MAP_READ); gst_video_frame_map (&vframe, &enc->input_state->info, inframe->input_buffer, GST_MAP_READ);
// frame = GST_BUFFER_DATA (enc->buffer);
frame = GST_VIDEO_FRAME_COMP_DATA (&vframe, 0); frame = GST_VIDEO_FRAME_COMP_DATA (&vframe, 0);
s = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 0); s = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 0);
x = encparams.horizontal_size; x = encparams.horizontal_size;
@ -155,8 +153,6 @@ bool
} }
gst_video_frame_unmap (&vframe); gst_video_frame_unmap (&vframe);
gst_video_codec_frame_unref (inframe);
/* inform the element the buffer has been processed */ /* inform the element the buffer has been processed */
GST_MPEG2ENC_SIGNAL (enc); GST_MPEG2ENC_SIGNAL (enc);
GST_MPEG2ENC_MUTEX_UNLOCK (enc); GST_MPEG2ENC_MUTEX_UNLOCK (enc);

View file

@ -50,6 +50,7 @@ GstMpeg2EncStreamWriter::WriteOutBufferUpto (const guint8 * buffer,
GstVideoCodecFrame *frame; GstVideoCodecFrame *frame;
GstBuffer *buf; GstBuffer *buf;
GstMpeg2enc *enc = GST_MPEG2ENC (video_encoder); GstMpeg2enc *enc = GST_MPEG2ENC (video_encoder);
GstFlowReturn ret;
frame = gst_video_encoder_get_oldest_frame (video_encoder); frame = gst_video_encoder_get_oldest_frame (video_encoder);
g_assert (frame != NULL); g_assert (frame != NULL);
@ -59,12 +60,12 @@ GstMpeg2EncStreamWriter::WriteOutBufferUpto (const guint8 * buffer,
flushed += flush_upto; flushed += flush_upto;
frame->output_buffer = buf; frame->output_buffer = buf;
/* this should not block anything else (e.g. handle_frame), but if it does, /* this should not block anything else (e.g. handle_frame), but if it does,
* it's ok as mpeg2enc is not really a loop-based element, but push-based */ * it's ok as mpeg2enc is not really a loop-based element, but push-based */
ret = gst_video_encoder_finish_frame (video_encoder, frame);
gst_video_codec_frame_unref (frame);
GST_MPEG2ENC_MUTEX_LOCK (enc); GST_MPEG2ENC_MUTEX_LOCK (enc);
enc->srcresult = gst_video_encoder_finish_frame (video_encoder, frame); enc->srcresult = ret;
gst_buffer_unref (buf);
GST_MPEG2ENC_MUTEX_UNLOCK (enc); GST_MPEG2ENC_MUTEX_UNLOCK (enc);
} }