After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 774983 - avdec_h264 is not copying metadata to the outputbuffer
avdec_h264 is not copying metadata to the outputbuffer
Status: RESOLVED DUPLICATE of bug 740222
Product: GStreamer
Classification: Platform
Component: gst-libav
1.10.x
Other Linux
: Normal major
: git master
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2016-11-24 04:18 UTC by parithi
Modified: 2016-11-29 13:57 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
H264 video meta test files (1.48 KB, application/zip)
2016-11-24 13:26 UTC, parithi
Details

Description parithi 2016-11-24 04:18:50 UTC
I have implemented a new GstMeta with tag "video". It is populated in h264parse plugin and sent to downstream along with the output buffer. I am expecting all downstream elements should propagate this meta data along with output buffer. But if I run the following pipeline 

gst-launch-1.0 filesrc location=input.ts ! tsdemux ! h264parse ! 'video/x-h264, stream-format=byte-stream' ! avdec_h264 ! x264enc ! mpegtsmux ! filesink location=out.ts 

I am getting following error. 

(gst-launch-1.0:22191): GStreamer-CRITICAL **: gst_buffer_add_meta: assertion 'gst_buffer_is_writable (buffer)' failed 
Caught SIGSEGV. 

From my analysis, I found that refcount of avdec_h264 output buffer is always 2. So the transform function is failed to append meta data to the outputbuffer. 

Please let me if you have any suggestion/solution for this issue? 

Regards,
Parithi
Comment 1 Matthew Waters (ystreet00) 2016-11-24 04:33:21 UTC
Bugzilla is not a support forum.

What the critical is helpfully telling you is that the buffer is not writable as required when adding meta's to a buffer.  You can ensure writablility with gst_buffer_make_writable().
Comment 2 Sebastian Dröge (slomo) 2016-11-24 06:00:04 UTC
Can you provide a testcase that allows reproducing this problem? Are you certain that this warning comes from avdec_h264 and not your h264parse changes (try running with G_DEBUG=fatal_warnings and get a backtrace of that warning)?
Comment 3 parithi 2016-11-24 07:55:23 UTC
(In reply to Sebastian Dröge (slomo) from comment #2)
> Can you provide a testcase that allows reproducing this problem? Are you
> certain that this warning comes from avdec_h264 and not your h264parse
> changes (try running with G_DEBUG=fatal_warnings and get a backtrace of that
> warning)?

Sebastian,

The test case is, I have created a metadata with custom SEI message that needs to be added after encode.

The "GStreamer-CRITICAL" message is from gst_buffer_add_h264_meta() function. This function uses the buffer sent through gst_video_decoder_finish_frame(). Please refer below gdb back trace.

************************************

G_DEBUG=fatal_warnings gdb --args  gst-launch-1.0 filesrc location=in.ts ! tsdemux ! h264parse ! 'video/x-h264, stream-format=byte-stream' ! avdec_h264 ! x264enc ! mpegtsmux ! filesink location=out.ts

(gdb) r
Starting program: /usr/local/bin/gst-launch-1.0 filesrc location=in.ts \! tsdemux \! h264parse \! video/x-h264,\ stream-format=byte-stream \! avdec_h264 \! x264enc \! mpegtsmux \! filesink location=out.ts
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib64/libthread_db.so.1".
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
Redistribute latency...
Redistribute latency...
Redistribute latency...

(gst-launch-1.0:20583): GStreamer-CRITICAL **: gst_buffer_add_meta: assertion 'gst_buffer_is_writable (buffer)' failed

Program received signal SIGTRAP, Trace/breakpoint trap.

Thread 140737148049152 (LWP 20587)

  • #0 g_logv
  • #1 g_log
  • #2 gst_buffer_add_meta
    at gstbuffer.c line 2161
  • #3 gst_buffer_add_h264_meta
    at gsth264meta.c line 96
  • #4 gst_h264_meta_transform
    at gsth264meta.c line 30
  • #5 foreach_metadata
    at gstvideodecoder.c line 2931
  • #6 gst_buffer_foreach_meta
    at gstbuffer.c line 2311
  • #7 gst_video_decoder_finish_frame
    at gstvideodecoder.c line 3022
  • #8 gst_ffmpegviddec_frame
    at gstavviddec.c line 1487
  • #9 gst_ffmpegviddec_frame
    at gstavviddec.c line 1548
  • #10 gst_ffmpegviddec_handle_frame
    at gstavviddec.c line 1679
  • #11 gst_video_decoder_decode_frame
    at gstvideodecoder.c line 3389
  • #12 gst_video_decoder_chain_forward
    at gstvideodecoder.c line 2131
  • #13 gst_video_decoder_chain
    at gstvideodecoder.c line 2443
  • #14 gst_pad_push_data
    at gstpad.c line 4205
  • #15 gst_pad_push_data
    at gstpad.c line 4457
  • #16 gst_pad_push
    at gstpad.c line 4576
  • #17 gst_base_transform_chain
    at gstbasetransform.c line 2369
  • #18 gst_pad_push_data
    at gstpad.c line 4205
  • #19 gst_pad_push_data
    at gstpad.c line 4457
  • #20 gst_pad_push
    at gstpad.c line 4576
  • #21 gst_base_parse_push_frame
    at gstbaseparse.c line 2543
  • #22 gst_base_parse_finish_frame
    at gstbaseparse.c line 2360
  • #23 gst_base_parse_finish_frame
    at gstbaseparse.c line 2701
  • #24 gst_h264_parse_handle_frame
    at gsth264parse.c line 1257
  • #25 gst_base_parse_handle_buffer

** (gst-launch-1.0:9874): CRITICAL **: gst_video_frame_map_id: assertion 'GST_IS_BUFFER (buffer)' failed
ERROR: from element /GstPipeline:pipeline0/avdec_h264:avdec_h264-0: Cannot access memory for read and write operation.
Additional debug info:
gstavviddec.c(865): gst_ffmpegviddec_get_buffer2 (): /GstPipeline:pipeline0/avdec_h264:avdec_h264-0:
The video memory allocated from downstream pool could not mapped forread and write.
Execution ended after 0:00:00.3756


Regards,
Parithi
Comment 4 Sebastian Dröge (slomo) 2016-11-24 09:49:47 UTC
That's in your own meta. Please provide a testcase with code that we can run. This is most likely a bug in your meta implementation.
Comment 5 parithi 2016-11-24 13:26:28 UTC
Created attachment 340682 [details]
H264 video meta test files
Comment 6 parithi 2016-11-24 13:27:08 UTC
Sebatian,

I've attached my meta test code. And the changes I did in  gst-plugins-bad\gst\videoparsers\gsth264parse.c is below.

In gst_h264_parse_pre_push_frame() function, after the statement
       buffer = frame->buffer;

I've added the following code

  {
      guint length = strlen("Test H264 video meta");
      gst_buffer_add_h264_test_meta(buffer, length, "Test H264 video meta");
  }

You can use any .ts file with h264 elementary stream for testing.
Comment 7 Sebastian Dröge (slomo) 2016-11-24 13:33:31 UTC
Your copy function is wrong and will cause segfaults when both the copy and the original are freed. You have to also create a copy of the payload, e.g. with g_memdup(). That's probably the reason for the other problems.

Apart from that, this might be https://bugzilla.gnome.org/show_bug.cgi?id=740222
Comment 8 parithi 2016-11-26 05:42:44 UTC
Sebastian,
Yes, the copying may cause segfault as you mentioned. But here, that's not the cause for the issue I mentioned. The issue ('gst_buffer_is_writable (buffer)' failed) exists even if there is no payload element in the structure.

I tried the same pipeline with "direct-rendering=false", it works properly.

As per GstVideoDecoder documentation, after calling gst_video_decoder_finish_frame() function, the output buffer of the frame is to be considered read-only.

With direct-rendering=true, which is the default value, output buffer is becoming read-only even before calling gst_video_decoder_finish_frame(). Because of this gst_buffer_add_h264_meta() function, which is called inside gst_video_decoder_finish_frame(), is failing.
Comment 9 Sebastian Dröge (slomo) 2016-11-26 09:48:25 UTC
Thanks for taking the time to report this.
This particular bug has already been reported into our bug tracking system, but please feel free to report any further bugs you find.

*** This bug has been marked as a duplicate of bug 740222 ***
Comment 10 Nicolas Dufresne (ndufresne) 2016-11-26 15:25:09 UTC
I'm not convinced of the resolution is ideal. It's not fully the fact that the memory are mapped read-write, but the fact that the GstBuffer has a refcount of two. It's somehow a side effect, but in your case, calling gst_buffer_make_writable() is free, it will only create a new GstBuffer and ref the memory.

Of course you'll be doing more allocation, but it will work without serious performance (this is low rate, since it's video). To me, the bug is that your new code is not calling make_writable(), the result is not optimal, the remaining would require finding a workaround to the way libav works.
Comment 11 Tim-Philipp Müller 2016-11-26 15:43:49 UTC
Was wondering the same, why we can't just call copy or make writable here.
Comment 12 Sebastian Dröge (slomo) 2016-11-26 15:45:53 UTC
GstVideoDecoder/Encoder should make sure the buffer is writable already when it tries to copy over metas. However as the buffer is mapped writable, a full memory copy will also be done here then, or not?
Comment 13 Nicolas Dufresne (ndufresne) 2016-11-27 01:08:57 UTC
I must say, I just don't remember, would have to test it. Though, I realize that doing so will break the pooling.
Comment 14 parithi 2016-11-29 04:04:20 UTC
Nicolas/Tim,

If I make the buffer writable by adding below code just before gst_video_decoder_finish_frame() call

   if(!gst_buffer_is_writable(out_frame->output_buffer))
   {
         gst_buffer_make_writable(out_frame->output_buffer);
   }


Then I am getting following error



(gst-launch-1.0:10963): GStreamer-CRITICAL **: gst_mini_object_unref: assertion 'mini_object->refcount > 0' failed

** (gst-launch-1.0:10963): CRITICAL **: gst_video_frame_map_id: assertion 'GST_IS_BUFFER (buffer)' failed
ERROR: from element /GstPipeline:pipeline0/avdec_h264:avdec_h264-0: Cannot access memory for read and write operation.
Additional debug info:
gstavviddec.c(865): gst_ffmpegviddec_get_buffer2 (): /GstPipeline:pipeline0/avdec_h264:avdec_h264-0:

The video memory allocated from downstream pool could not mapped forread and write.
Execution ended after 0:00:00.2103
Comment 15 Sebastian Dröge (slomo) 2016-11-29 05:59:25 UTC
That's because gst_buffer_make_writable() takes ownership of whatever you pass to it and returns a new buffer (or the same if nothing was needed).

The general pattern is "out_frame->output_buffer = gst_buffer_make_writable (out_frame->output_buffer)". You also don't need to check for writability first, the function does nothing if not needed.
Comment 16 Nicolas Dufresne (ndufresne) 2016-11-29 13:57:07 UTC
And ref to maintain the baseclass referencence which you don't own.