typefind: audio/mpeg icecast stream misdetected as h264 video
Trying to play the following web radio station (which uses icecast) fails:
gst-launch-1.0 -v uridecodebin uri=http://192.99.39.108:7872/stream ! audioconvert ! audioresample ! autoaudiosink
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0: source = "\(GstSoupHTTPSrc\)\ source"
Got context from element 'source': gst.soup.session=context, session=(SoupSession)NULL, force=(boolean)false;
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstSoupHTTPSrc:source.GstPad:src: caps = application/x-icy, metadata-interval=(int)8192
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstTypeFindElement:typefindelement0.GstPad:src: caps = application/x-icy, metadata-interval=(int)8192
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind: force-caps = application/x-icy, metadata-interval=(int)8192
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0: sink-caps = application/x-icy, metadata-interval=(int)8192
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0: bitrate = 0
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0: bitrate = 0
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0: bitrate = 0
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0.GstPad:sink: caps = application/x-icy, metadata-interval=(int)8192
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstTypeFindElement:typefindelement0.GstPad:sink: caps = application/x-icy, metadata-interval=(int)8192
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstSoupHTTPSrc:source.GstPad:src: caps = application/x-icy, metadata-interval=(int)8192, content-type=(string)audio/mpeg
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstTypeFindElement:typefindelement0.GstPad:src: caps = application/x-icy, metadata-interval=(int)8192, content-type=(string)audio/mpeg
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0: bitrate = 0
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0.GstPad:src: caps = application/x-icy, metadata-interval=(int)8192
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0.GstPad:src: caps = application/x-icy, metadata-interval=(int)8192
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0: bitrate = 0
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0: bitrate = 0
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0.GstGhostPad:sink.GstProxyPad:proxypad1: caps = application/x-icy, metadata-interval=(int)8192
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind.GstPad:src: caps = application/x-icy, metadata-interval=(int)8192
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0: bitrate = 0
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0: bitrate = 0
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0: bitrate = 0
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstICYDemux:icydemux0.GstPad:sink: caps = application/x-icy, metadata-interval=(int)8192
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind.GstPad:sink: caps = application/x-icy, metadata-interval=(int)8192
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0.GstGhostPad:sink: caps = application/x-icy, metadata-interval=(int)8192
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0.GstPad:src: caps = application/x-icy, metadata-interval=(int)8192, content-type=(string)audio/mpeg
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0.GstGhostPad:sink.GstProxyPad:proxypad1: caps = application/x-icy, metadata-interval=(int)8192, content-type=(string)audio/mpeg
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind.GstPad:src: caps = application/x-icy, metadata-interval=(int)8192, content-type=(string)audio/mpeg
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstICYDemux:icydemux0.GstPad:sink: caps = application/x-icy, metadata-interval=(int)8192, content-type=(string)audio/mpeg
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind.GstPad:sink: caps = application/x-icy, metadata-interval=(int)8192, content-type=(string)audio/mpeg
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0.GstGhostPad:sink: caps = application/x-icy, metadata-interval=(int)8192, content-type=(string)audio/mpeg
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0: bitrate = 0
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0: bitrate = 0
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0: bitrate = 0
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstQueue2:queue2-0: bitrate = 0
/GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstH264Parse:h264parse0.GstPad:sink: caps = video/x-h264, stream-format=(string)byte-stream
ERROR: from element /GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstH264Parse:h264parse0: Error parsing H.264 stream
Additional debug info:
gsth264parse.c(1307): gst_h264_parse_handle_frame (): /GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstH264Parse:h264parse0:
No H.264 NAL unit found
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...
I traced the problem to mp3_type_find_at_offset
. The problem is that the mp3 frame size is 1044 bytes, but gst_type_find_peek
keeps failing (regardless of GST_MP3_TYPEFIND_SYNC_SIZE
) until size is reduced to 1024. So it finds the first header, then somehow the second (even though it is at offset 1044), but then because it considers the second as only partial, it reduces found
to 1. And because found
is less than GST_MP3_TYPEFIND_MIN_HEADERS
(which is defined as 2), it never even considers it as a valid mp3 stream.
The logic of how this function walks through the byte stream doesn't make a whole lot of sense to me.
See typefind.log with my added log statements.
Playing the same station with VLC works as expected.