Recover H264 encoded ts segments that dont have PPS/SPS

Nicolas Dufresne nicolas at ndufresne.ca
Thu May 25 19:41:58 UTC 2023


Le mercredi 24 mai 2023 à 18:18 -0700, Guru Govindan via gstreamer-devel a
écrit :
> Hi Nicolas, Vinod,
> 
> I was finally able to get this working with a pipeline like below. For some
> reason, the tsdemux would not take a caps without the capssetter element.
> Adding it here for anyone needing help in future.
> Thanks a lot for your help!
> 
> gst-launch-1.0 filesrc location=broken.ts ! tsdemux ! capssetter
> caps='video/x-h264,stream-format=byte-stream,alignment=nal' ! rtph264pay !
> 'application/x-rtp,encoding-name=H264,sprop-parameter-sets="<sprop parameter
> sets>"' ! rtph264depay ! h264parse config-interval=-1 ! mpegtsmux ! filesink
> location=$fixed.ts

tsdemux does not produce nal aligned output, adding h264parse here should have
done the trick I think.

Nicolas

> 
> Regards,
> Guru
> 
> On Thu, May 11, 2023 at 1:17 AM Guru Govindan <gurunathan.govindan at gmail.com>
> wrote:
> > Hi Vinod, Nicolas,
> > Do you have an example pipeline that you can share? 
> > I tried setting the sprop-parameter-sets in the h264parse caps information,
> > but the pipeline failed with byte-stream not accepted
> > Here is an example pipeline
> > 
> > GST_DEBUG=3 /opt_gst120/bin/gst-launch-1.0  filesrc location=not_working.ts
> > ! tsdemux ! rtph264pay ! 'application/x-rtp,encoding-name=H264,sprop-
> > parameter-sets=(string)"Z2QAMq0AxSAKAC1puAgIDSgAbd0ADN/mAHiRFQ==,aO48sA=="'
> > ! fakesink
> > Setting pipeline to PAUSED ...
> > 0:00:00.020035191  5621 0x5596029ba4f0 WARN                 basesrc
> > gstbasesrc.c:3688:gst_base_src_start_complete:<filesrc0> pad not activated
> > yet
> > Pipeline is PREROLLING ...
> > 0:00:00.020646281  5621 0x5596027cab60 WARN                GST_CAPS
> > gstpad.c:3235:gst_pad_query_accept_caps_default:<rtph264pay0:sink> caps:
> > video/x-h264, stream-format=(string)byte-stream were not compatible with:
> > video/x-h264, stream-format=(string)byte-stream,
> > profile=(string)constrained-baseline, alignment=(string){ nal, au };
> > video/x-h264, stream-format=(string)byte-stream, alignment=(string){ nal, au
> > }
> > 0:00:00.020659449  5621 0x5596027cab60 WARN                GST_CAPS
> > gstpad.c:5757:pre_eventfunc_check:<rtph264pay0:sink> caps video/x-h264,
> > stream-format=(string)byte-stream not accepted
> > 0:00:00.020678024  5621 0x5596027cab60 WARN                GST_CAPS
> > gstpad.c:3235:gst_pad_query_accept_caps_default:<rtph264pay0:sink> caps:
> > video/x-h264, stream-format=(string)byte-stream were not compatible with:
> > video/x-h264, stream-format=(string)byte-stream,
> > profile=(string)constrained-baseline, alignment=(string){ nal, au };
> > video/x-h264, stream-format=(string)byte-stream, alignment=(string){ nal, au
> > }
> > 0:00:00.020683790  5621 0x5596027cab60 WARN                GST_CAPS
> > gstpad.c:5757:pre_eventfunc_check:<rtph264pay0:sink> caps video/x-h264,
> > stream-format=(string)byte-stream not accepted
> > 0:00:00.020697187  5621 0x5596027cab60 WARN                GST_CAPS
> > gstpad.c:3235:gst_pad_query_accept_caps_default:<rtph264pay0:sink> caps:
> > video/x-h264, stream-format=(string)byte-stream were not compatible with:
> > video/x-h264, stream-format=(string)byte-stream,
> > profile=(string)constrained-baseline, alignment=(string){ nal, au };
> > video/x-h264, stream-format=(string)byte-stream, alignment=(string){ nal, au
> > }
> > 0:00:00.020702788  5621 0x5596027cab60 WARN                GST_CAPS
> > gstpad.c:5757:pre_eventfunc_check:<rtph264pay0:sink> caps video/x-h264,
> > stream-format=(string)byte-stream not accepted
> > 0:00:00.020723520  5621 0x5596027cab60 WARN              mpegtsbase
> > mpegtsbase.c:1764:mpegts_base_loop:<tsdemux0> error: Internal data stream
> > error.
> > 0:00:00.020728593  5621 0x5596027cab60 WARN              mpegtsbase
> > mpegtsbase.c:1764:mpegts_base_loop:<tsdemux0> error: streaming stopped,
> > reason not-negotiated (-4)
> > ERROR: from element /GstPipeline:pipeline0/GstTSDemux:tsdemux0: Internal
> > data stream error.
> > 
> > On Tue, May 9, 2023 at 11:28 AM vinod kesti <vinodkesti at yahoo.com> wrote:
> > > Hi Guru.
> > > 
> > > The data used may not be in NAL format. Simply appending SPS and PPS may
> > > not help
> > > Once you pack SPS and PPS as NAL then pass that buffer to the mpegts
> > > muxer. or h264parse can do it for you if you set sprop parameter in the
> > > rtph264parse.
> > > 
> > > 
> > > 
> > > Sent from Yahoo Mail. Get the app
> > >  
> > > 
> > > 
> > >  
> > >  
> > >  
> > > On Wednesday, 3 May, 2023 at 08:43:09 pm GMT-5, Nicolas Dufresne via
> > > gstreamer-devel <gstreamer-devel at lists.freedesktop.org> wrote: 
> > >  
> > > 
> > >  
> > > 
> > >  
> > > 
> > > 
> > > Le mer. 3 mai 2023, 21 h 15, Guru Govindan <gurunathan.govindan at gmail.com>
> > > a écrit :
> > > > Hi Nicolas,
> > > > Thanks for your response, I figured out a way to extract the h264 header
> > > > by making another connection to the camera and extracting data from the
> > > > first stream. I used help from
> > > > here 
> > > > https://stackoverflow.com/questions/24884827/possible-locations-for-sequence-picture-parameter-sets-for-h-264-stream/24890903#24890903
> > > > 
> > > > I also verified that the extracted header is valid by running `ffmpeg -i
> > > > header1.h264 -an -c:v copy -bsf:v trace_headers -f null` and verified
> > > > that it is a valid h264 file and contains SPS and PPS values.
> > > > 
> > > > However when I cat the recovered header and copy the truncated file, it
> > > > says it is not a valid file.
> > > > 
> > > > Any ideas? Should it be inserted before every keyframe and not just in
> > > > front of the file?
> > > 
> > > 
> > > You only need it once, unless you had dynamic resolution change (which
> > > never happen with security cam). My guess would be the stream format (avec
> > > vs byte-stream), you want byte stream for mpeg ts.
> > > 
> > > > 
> > > > 
> > > > On Wed, May 3, 2023 at 12:47 PM Nicolas Dufresne <nicolas at ndufresne.ca>
> > > > wrote:
> > > > > Le mercredi 03 mai 2023 à 10:22 -0700, Guru Govindan via gstreamer-
> > > > > devel a écrit :
> > > > > > Hi There,
> > > > > > I am having an issue where a lot of video footage from a security
> > > > > > camera was recorded without the sprop-parameters-set (SPS/PPS).
> > > > > > 
> > > > > > I am unable to play or transcode these ts files as it does not have
> > > > > > SPS/PPS values. 
> > > > > > 
> > > > > > I tried the following by sending the h264parse the stream format but
> > > > > > that failed
> > > > > 
> > > > > 
> > > > > The only way to recover is to find the origin SPS/PPS, note, this is
> > > > > static on most cameras. The sprop-parameters contains it, just it may
> > > > > need to be transformed. Then something like this may work, but never
> > > > > tried`
> > > > > 
> > > > > gst-launch-1.0 \
> > > > >   filesrc location=truncated.ts ! tsdemux ! filesink
> > > > > location=truncated.h264
> > > > > cat recovered-header.h264 > fixed.h264
> > > > > cat truncated.h264 >> fixed.h264
> > > > > gst-launch-1.0 \
> > > > >   filesrc location=fixed.h264 ! h264parse ! mpegtsmux ! filesink
> > > > > location=fixed.ts
> > > > > 
> > > > > This is video only though, totally untested.
> > > > > 
> > > > > Nicolas
> > > > > 
> > > > > > 
> > > > > > ```
> > > > > > gst-launch-1.0 -v filesrc location=2.ts ! tsparse ! tsdemux
> > > > > > name=demux demux. ! queue ! h264parse ! video/x-h264,stream-
> > > > > > format=avc,alignment=au ! decodebin ! videoconvert ! vaapih264enc !
> > > > > > h264parse ! mpegtsmux alignment=-1 ! filesink location=output.ts
> > > > > > ```
> > > > > > failed with /
> > > > > > GstPipeline:pipeline0/GstH264Parse:h264parse0.GstPad:sink: caps =
> > > > > > video/x-h264, stream-format=(string)byte-stream
> > > > > > ERROR: from element /GstPipeline:pipeline0/GstH264Parse:h264parse0:
> > > > > > No valid frames found before end of stream
> > > > > > 
> > > > > > I then tried to split it as per keyframes and then mux it.. like
> > > > > > below but that failed as well
> > > > > > 
> > > > > > ```
> > > > > > gst-launch-1.0 -v filesrc location=2.ts ! tsdemux name=demux !
> > > > > > h264parse ! splitmuxsink max-size-time=1000000000
> > > > > > location=segment%02d.ts mpegtsmux name=mux ! filesink
> > > > > > location=output.ts demux.video_0 ! queue ! mux.
> > > > > > ```
> > > > > > failed with h264parse0: No valid frames found before end of stream
> > > > > > 
> > > > > > Since it could not find EOS.. I thoiught of sending the entire
> > > > > > manifest.. but that didnt work as well
> > > > > > 
> > > > > > ```
> > > > > > gst-launch-1.0 -v filesrc location="<manifest uri>" ! hlsdemux !
> > > > > > h264parse ! video/x-h264,stream-
> > > > > > format='(string)avc,alignment=(string)au' ! mpegtsmux ! h264parse
> > > > > > config-interval=-1 ! mpegtsmux ! filesink location=output.ts
> > > > > > ```
> > > > > > 
> > > > > > Just like how we can add config-interval to a rtp stream, is there a
> > > > > > way to add it to a ts segment?
> > > > > > 
> > > > > > Best Regards,
> > > > > > Guru
> > > > > > 
> > > > > 
> > > > > 
> > > 
> > >  
> > >  

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20230525/7b195173/attachment-0001.htm>


More information about the gstreamer-devel mailing list