Hello,
It is a typo. Sorry for mistake.
An updated implementation.c is attached to this mail. Also I have been
setting the *format *attribute to vaapipostproc element.
There is no problem getting and encoding a video by using vaapi elements.
The problem is occurred whenever I remove the bin and create a new one to
update filesink's location. ie. I have been encoding the video and writing
to disk successfully for specified time period (10 seconds in
implementation.c line 217). After this period I need to remove the bin
(consists of muxer and filesink, creating by using CreateNewBin function in
implementation.c) create the new one and then try to continue play. At that
time, vaapipostproc element halts the whole pipeline.
The problem still continues and I cannot find a way to handle this problem.
Thank you so much for your consideration.
Regards.
On 16 December 2014 at 09:36, Yuan, Feng <[email protected]> wrote:
>
>
>
> Hi,
>
> From your attachment implementation.c, found
>
> vaapiencoder = gst_element_factory_make ("x264enc", NULL);
>
> Maybe typo. Suppose you want “vaapiencode_h264”. Anyway, I just tried
>
> $ gst-launch-1.0 videotestsrc !
> video/x-raw,format=NV12,width=320,height=240,framerate=30/1 ! vaapipostproc
> ! queue ! vaapiencode_h264 ! fakesink
>
> Failed in latest master branch. This issue caused by gstvaapiencoder need
> strict format check but vaapipostproc with format ‘Encoded’(VASurface).
> After adding a specific ‘format’ for vaapipostproc, encoder works. You can
> take a try .
>
> $ gst-launch-1.0 videotestsrc !
> video/x-raw,format=NV12,width=320,height=240,framerate=30/1 ! vaapipostproc
> format=nv12 ! queue ! vaapiencode_h264 ! fakesink
>
>
>
>
>
> Thanks,
>
> Wind
>
> *From:* Libva [mailto:[email protected]] *On Behalf Of
> *Engin
> Firat
> *Sent:* Friday, December 12, 2014 11:48 PM
> *To:* [email protected]
> *Subject:* [Libva] Problem with vaapipostproc element
>
>
>
> Hello,
>
>
>
> I have a problem related to element called vaapipostproc. The problem is
> as follows:
>
>
>
> I have a pipeline and for specified time intervals I attempt to change
> pipeline dynamically in order to change write location of the filesink. I
> have implemented this functionality and everything works well in case I do
> not use vaapipostproc element. If I use vaapipostproc element, the pipeline
> crashes unexpectedly. An error message is thrown from the element
> vaapipostproc: "failed to create output video buffer" at the immediate
> point the pipeline is changed dynamically.
>
>
>
> My pipeline change strategy is as follows:
>
> 0. Create a bin and place mux and filesink elements inside it. Moreover
> create a queue element before this bin.
>
> 1. For specified intervals, fire a clock event and catch it in a handler
>
> 2. In clock handler place a blocking probe to queue's source pad and
> register a blocking data handler
>
> 3. In blocking data handler unlink queue and bin and send an EOS event to
> bin's sink pad.
>
> 4. Handle EOS event on bin element. In this handler, destroy bin, create a
> new bin with an updated filesink location connect bin with queue. And
> remove the blocking probe.
>
>
>
> This strategy for dynamic pipeline changing works well when I do not use
> vaapipostproc element. But I want to do encoding process on GPU and using
> vaapipostproc is a mandatory.
>
>
>
> I have inspected the source code gstvaapipostproc.c for element
> vaapipostproc and It seem the problem is related to function named as
> *GstBuffer
> * create_output_buffer(GstVaapiPostproc*)*.
>
>
>
> You can find output messages when GST_DEBUG environment variable is set to
> 4. In addition to this, you can also find my implementation to change the
> pipeline dynamically. The implementation won't compile, I just want to
> share a pseudo-code for your well understanding of the implementation.
>
>
>
> I want to share the most interesting part of the out.log file:
>
> 0:00:11.075920072 [334m11325 [00m 0x1dcc720 [36mINFO [00m *[00m
> vaapipostproc
> gstvaapipluginbase.c:532:gst_vaapi_plugin_base_decide_allocation:<GPUPostProcessing>
> [00m no pool or doesn't support GstVaapiVideoMeta, making new pool*
>
> 0:00:11.076231088 [334m11325 [00m 0x1dcc720 [36mINFO [00m [00m
> vaapivideomemory gstvaapivideomemory.c:627:gst_vaapi_video_allocator_new:
> [00m has direct-rendering for NV12 surfaces: no
>
> *0:00:11.076568949 [334m11325 [00m 0x1dcc720 [31;01mERROR [00m [00m
> vaapipostproc gstvaapipostproc.c:412:create_output_buffer: [00m
> failed to create output video buffer*
>
> 0:00:11.076723161 [334m11325 [00m 0x1dcc720 [33;01mWARN [00m [00m
> basetransform
> gstbasetransform.c:2130:gst_base_transform_handle_buffer:<GPUPostProcessing>
> [00m could not get buffer from pool: error
>
> 0:00:11.076773273 [334m11325 [00m 0x1dcc720 [36mINFO [00m *[00m
> task gsttask.c:300:gst_task_func:<queue0:src> [00m Task going
> to paused*
>
>
>
> How can I solve this problem? Any help will be appreciated.
>
>
>
> Regards.
>
>
> Engin FIRAT
>
--
*Engin FIRAT*
Adoniss Yazılım Bilişim
Elektronik Araştırma Geliştirme
Limited Şirketi
+90 506 884 82 07 (Mobile)
ODTÜ Teknokent, ODTÜ-Halıcı Yazılımevi
İnönü Bulvarı / ANKARA (Address)
static
GstPadProbeReturn PadBlockCallback(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
{
//Get the sink pad from muxsinkbin
GstPad *sinkPad = gst_element_get_static_pad(muxsinkBin, "sink");
//Unlink queueBeforeBin's source pad and bin's sink pad
gboolean isUnlinked = gst_pad_unlink(pad, sinkPad);
//Send an EOS event to bin's sinkPad
gboolean isEOSSent = gst_pad_send_event(sinkPad, gst_event_new_eos());
gst_object_unref(sinkPad);
return GST_PAD_PROBE_OK;
}
static
gint ClockCallback(gpointer userData)
{
//This is the clock callback. Add a blocking probe to queueBeforeBin's source pad.
GstPad * q2SrcPad;
q2SrcPad = gst_element_get_static_pad(queueBeforeBin, "src");
//Write added probe id probeId in order to remove the probe from queue later.
probeId = gst_pad_add_probe (q2SrcPad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
PadBlockCallback, userData, NULL);
gst_object_unref(q2SrcPad);
return TRUE;
}
static gboolean
bus_cb (GstBus * bus, GstMessage * msg, gpointer user_data)
{
//GMainLoop *loop = (GMainLoop*)user_data;
GstGPUAnalogVideoElement * callingClass = static_cast<GstGPUAnalogVideoElement*>(user_data);
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_ERROR:{
GError *err = NULL;
gchar *dbg;
gst_message_parse_error (msg, &err, &dbg);
gst_object_default_error (msg->src, err, dbg);
g_error_free (err);
g_free (dbg);
// g_main_loop_quit (loop);
break;
}
case GST_EVENT_EOS:
std::cout << "EOS message is got" << std::endl;
break;
case GST_MESSAGE_ELEMENT:
{
const GstStructure *s = gst_message_get_structure (msg);
if (gst_structure_has_name (s, "GstBinForwarded"))
{
GstMessage *forward_msg = NULL;
gst_structure_get (s, "message", GST_TYPE_MESSAGE, &forward_msg, NULL);
if (GST_MESSAGE_TYPE (forward_msg) == GST_MESSAGE_EOS)
{
g_print ("EOS from element %s\n",
GST_OBJECT_NAME (GST_MESSAGE_SRC (forward_msg)));
//Destroy previous bin
DestroyBin();
//Create a new bin which consists a new muxer element with a new location
CreateNewBin();
//Remove blocking pad from queue's source pad.
RemovePad();
}
gst_message_unref (forward_msg);
}
}
break;
default:
break;
}
return TRUE;
}
void RemovePad()
{
GstPad * q2SrcPad;
q2SrcPad = gst_element_get_static_pad(queueBeforeBin, "src");
gst_pad_remove_probe(q2SrcPad, probeId);
gst_object_unref(q2SrcPad);
}
void DestroyBin()
{
gst_element_set_state(muxsinkBin, GST_STATE_NULL);
gst_bin_remove(GST_BIN(gstPipeline), muxsinkBin);
}
void CreateNewBin()
{
static int i =0 ;
static std::string fileLocPattern = "file%d.mkv";
char buffer[12];
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, fileLocPattern.c_str(), i++);
//Create Muxer Element
matroskaMuxer = gst_element_factory_make("matroskamux", "MatroskaMuxer");
//Create File Sink Element
videoSink= gst_element_factory_make("filesink", buffer);
//GstPad * ghostPadSink = gst_ghost_pad_new_no_target("src", GST_PAD_SRC);
//gst_element_add_pad(fileSink, ghostPadSink);
g_object_set(G_OBJECT(videoSink), "location", buffer, 0);
//Create muxsinkBin
muxsinkBin = gst_bin_new(buffer);
g_object_set(G_OBJECT(muxsinkBin), "message-forward", TRUE, 0);
//Add a src pad to the bin
//GstPad * srcPadFromSink = gst_element_get_static_pad(fileSink, "src");
//GstPad * srcPadFromBin = gst_ghost_pad_new("src", srcPadFromSink);
// GstPad * ghostPad = gst_ghost_pad_new_no_target("src", GST_PAD_SRC);
// gst_element_add_pad(bin, ghostPad);
gst_bin_add_many(GST_BIN(muxsinkBin), matroskaMuxer, videoSink, 0);
gboolean linkState = TRUE;
//Connect elements within muxsink_bin
//Link: matroskamuxer -> filesink
linkState &= gst_element_link_many(matroskaMuxer, videoSink, 0);
//Add this bin to pipeline
gst_bin_add(GST_BIN(gstPipeline), muxsinkBin);
//Create ghostpad and manually link muxsinkBin and remaining part of the pipeline
{
GstPadTemplate * muxerSinkPadTemplate;
GstPad * muxerSinkPad;
if( !(muxerSinkPadTemplate = gst_element_class_get_pad_template(GST_ELEMENT_GET_CLASS(matroskaMuxer), "video_%u")) )
{
std::cout << "Unable to get source pad template from muxing element" << std::endl;
}
//Obtain dynamic pad from element
muxerSinkPad = gst_element_request_pad(matroskaMuxer, muxerSinkPadTemplate, 0, 0);
//Add ghostpad
GstPad * ghostPad = gst_ghost_pad_new("sink", muxerSinkPad);
gst_element_add_pad(muxsinkBin, ghostPad);
gst_object_unref(GST_OBJECT(muxerSinkPad));
gst_element_sync_state_with_parent(muxsinkBin);
//Get src pad from queue element
GstPad * queueBeforeBinSrcPad = gst_element_get_static_pad(queueBeforeBin, "src");
//Link queuebeforebin to ghostpad
if (gst_pad_link(queueBeforeBinSrcPad, ghostPad) != GST_PAD_LINK_OK )
{
std::cout << "QueueBeforeBin cannot be linked to MuxerSinkPad." << std::endl;
//TODO :: throw an exception here
}
gst_object_unref(queueBeforeBinSrcPad);
}
// gst_element_set_state(muxer, GST_STATE_PLAYING);
// gst_element_set_state(sink, GST_STATE_PLAYING);
//gst_element_set_state(bin, GST_STATE_PLAYING);
}
int main()
{
GError *err = NULL;
GMainLoop *loop;
gstPipeline = gst_pipeline_new ("pipeline");
videoSource = gst_element_factory_make ("videotestsrc", NULL);
//g_object_set (src, "is-live", TRUE, NULL);
//Create a caps filter between videosource videoconvert
std::string capsString = "video/x-raw,format=YV12,width=320,height=240,framerate=30/1";
GstCaps * dataFilter = gst_caps_from_string(capsString.c_str());
queue1 = gst_element_factory_make ("queue", NULL);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//Here by simply changing this element into a "queue", the implementation works well without any problems.
vaapipostproc = gst_element_factory_make("vaapipostproc", "GPUPostProcessing");
g_object_set(G_OBJECT(vaapipostproc), "format", 3, 0);
vaapiqueue = gst_element_factory_make("queue", "GPUQueue");
vaapiencoder = gst_element_factory_make ("vaapiencode_h264", NULL);
queueBeforeBin = gst_element_factory_make("queue", NULL);
//blockpad = gst_element_get_static_pad(q2, "src");
gst_bin_add_many(GST_BIN(gstPipeline), videoSource, queue1, vaapipostproc, vaapiqueue, vaapiencoder, queueBeforeBin, 0);
gboolean link = gst_element_link_filtered(videoSource, queue1, dataFilter);
link &= gst_element_link(queue1, vaapipostproc);
link &= gst_element_link(vaapipostproc, vaapiqueue);
link &= gst_element_link(vaapiqueue, vaapiencoder);
link &= gst_element_link(vaapiencoder, queueBeforeBin);
CreateNewBin();
gst_element_set_state (gstPipeline, GST_STATE_PLAYING);
loop = g_main_loop_new (NULL, FALSE);
gst_bus_add_watch (GST_ELEMENT_BUS (gstPipeline), bus_cb, this);
g_timeout_add_seconds (10, ClockCallback, this);
g_main_loop_run (loop);
gst_element_set_state (gstPipeline, GST_STATE_NULL);
gst_object_unref (gstPipeline);
}()
_______________________________________________
Libva mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/libva