Re-packetize h264 bytestream to Matroska output - ffmpeg

I have an app that's capturing multiple video streams from users and put them into one mkv output file.
Data are from RTP packets. I use h264.
I'm creating mkv using ffmpeg and bytedeco/javacpp-presets bridge for Java.
For some reason my output mkv, after changed container to mp4 (ffmpeg -i input.mkv -c copy output.mp4) is not playable by QuickTime Player. It opens the file but shows nothing but black frame for whole duration.
I'm trying to avoid re-coding of the streams.
One of my attempts to fix this was to somehow pack up raw h264 bytestream and use ffmpeg to put it in mkv again:
ffmpeg -i input.mkv -c copy -f h264 - | ffmpeg -i - -c copy output.mkv
But because raw h264 bytestream has no timing information (ffmpeg warns about lack of timestamps here) it packs it with some constant frame rate which results in different video duration than original. So i.e. from 27min video i get 30min with constant frame rate.
I'm looking for a way to re-pack my h264 video data into mkv container without re-coding.
I also tried NUT container for raw data as it persists some timing informations but result was the same as original mkv - black frame in QuickTime.
Maybe there is some other way to debug why QT shows nothing for my file? Is there any verbosity mode i can enable, some logs to see if it complains for something?

At the datastream level, you need to extract SPS and PPS items from H.264's avcC Coder Configuration Atoms at the beginning of each file and put them into a Matroska SimpleBlock chunk before any other H.264 data.
Or, you can put the avcC data buffer verbatim into your .mkv stream in the header at Segment/Tracks/Track/Codec's private data.
SPS and PPS are standalone NALUs, and Matroska stores them concatenated in byte stream format in the SimpleBlocks.
H.264 video decoders need the data in SPS and PPS to work.

Related

Ffmpeg -c copy not carrying over audio track from mkv to hls stream

I am using ffmpeg to create an hls stream. The source is an mkv with multiple audio tracks. I have tried using -map to specify the audio stream as well. I also found that when I point ffmpeg to any other audio stream in the file it works. It's just the first audio stream that does not. At one point I replaced -c copy with -acodec aac -ac 6 on the first stream and I got sound which is great but I am only looking to copy the stream and not re-encode it. The next thing I tried was using other mkv videos I have. All are reflecting the same issue. The mkv's by itself play both audio and video fine in VLC. When playing the output.m3u8 in VLC the option to choose different audio tracks is greyed out. Here is the command I'm using:
ffmpeg -i "./video.mkv" -ss 00:00:00 -t 00:00:30 -c copy -f hls "output.m3u8"
I want the audio of my hls stream to reflect that of the mkv source:
Although what I get returned from the command above gives me no sound and shows me this in mediaInfo:
I've aslo noticed that hls does not support pcm. Is it possible dash could work with this stream because it is pcm?
HLS segments can be either MPEG-TS or fragmented MP4. Neither officially support PCM audio, so you'll have to convert it.
DASH uses fragmented MP4 as segment format.

How do I fix the "PES packet size mismatch" error in FFmpeg?

How to fix the error PES packet size mismatch in FFmpeg -
I'm going to answer my own question, because the phrase PES packet size mismatch comes up regularly in posts relating to ffmpeg, but I've nowhere seen a satisfactory solution to it.
It usually figures in a problem involving .TS transport stream files: either in relation to concatenating such files, or relating to re-muxing them (from .ts to .mp4). Somewhere in the output from ffmpeg, the deadly phrase packet size mismatch will suddenly start repeating.
A solution is to concatenate them as .ts files (i.e. in their original format), then take the output .ts file, split it into a video file (.ts) and an audio file (.ts), then remux them (to either .ts or .mp4) using the "itsoffset" option. Even if stream copy is used, outputting to .mp4 will often give worse picture quality than retaining the .ts format.
The following code does that, outputting either .mp4 video or .ts video (copy the code into a simple .bat batch file, then run that file) -
.
:: Program Location
SET ffmpeg="C:\Program Files\FFmpeg\ffmpeg.exe" -hide_banner
:: STEP 1 -
:: Create File List
IF EXIST mylist.txt DEL mylist.txt
FOR %%i IN (*.ts) DO ECHO file '%%i'>> mylist.txt
:: Concatenate Files : TS
%ffmpeg% -f concat -safe 0 -i mylist.txt -c copy -threads 1 out.ts
:: STEP 2 -
:: Extract Video stream
%ffmpeg% -i out.ts -vcodec copy -an -sn -threads 1 video.ts
:: Extract Audio stream
%ffmpeg% -i out.ts -acodec copy -vn -sn -threads 1 audio.ts
:: STEP 3 -
:: Combine Video and Audio streams (with .MP4 options)
SET mapping=-i video.ts -itsoffset -0 -i audio.ts -map 0:v -map 1:a
SET options=-flags global_header -movflags faststart -threads 1
%ffmpeg% %mapping% -c:v copy -c:a copy %options% output.mp4
:: Combine Video and Audio streams (with .TS options)
SET mapping=-i video.ts -itsoffset -0 -i audio.ts -map 0:v -map 1:a
SET options=-threads 1
%ffmpeg% %mapping% -c:v copy -c:a copy %options% output.ts
.
Addendum :
There seems to be some dispute about my suggested solution, as detailed in the Comments below. It seems to be being said that my solution is ignoring the fact that data is missing in the source files.
I think the least I can do is admit that since ffmpeg is reporting an error in the source files, with its 'packet size mismatch' warning, the objection raised in the Comments might be valid.
However, even if data is missing, my suggested routine will at least give you a file which will play in most media players. In many cases, there will not even be an audible or visual fault at the join point specified in the reported error.
It's difficult to see how the missing data might be restored, but do please chip in with suggestions. There must be scope for improving my script, because so little attention has been paid to this type of fault previously.
Happily, it seems that this type of error will NOT cause the sound to lose synchronisation with the picture. So the audio after the join-point will not go out-of-sync, even if some data is missing at the join.
PES packet size mismatch
Error message (Video files):
PES packet size mismatch
.
Analysis of Error:
A single PES packet can only contain ONE of the three possible types of frame,
namely I, B or P. A single PES packet stores one DTS/PTS pair.
What the muxer does is take the frame (be it I, B or P) and package it into a
PES packet, then add a DTS and a PTS timestamp to that packet, and that's all.
The next frame will be packaged into a separate PES packet.
Sometimes, depending on the encoder and muxer, when a frame is very large (such
as an I-frame in an HD video) it is packed into multiple PES packets which all
have the same DTS/PTS timestamps.
Where the SPS and PPS of the h264 stream are packed, together with an I-frame,
into a single PES packet, if that packet (containing the SPS and PPS) is lost,
the decoder will have to wait until the next SPS and PPS are transmitted --
because without them it cannot decode the stream.
Frame types in MPEG-2 video:
Frame type 001: intra-coded (I) - "i frame"
Frame type 010: predictive-coded (P) - "p frame"
Frame type 011: bidirectionally-predictive-coded (B) - "b frame"
In live streams, all tv stations set PES length to zero for H264 video streams,
as the PES length is a 16 bit value, hence has a maximum size of 65,535 Bytes
(the old standard for MPEG2 video). That is too small for most H264 PES packets,
so it should be set to zero (i.e. "any length").
A problem can arise if the video stream has a non-zero PES length. FFMPEG does
not seem to cope with that. It appears that FFMPEG requires the stream to be
explicitly labelled "any length" (i.e. set to zero).
If I download a raw .ts file and run it through TS_Doctor, the analyser complains:
"PES length on video stream detected. This can be problematic!
Patch PES length on video stream to a safe value - Yes/No."
If I click on "No", then run the output through FFMPEG, a problem is reported of
the sound being out-of-sync. If I click "Yes", then run the output through FFMPEG,
no problem is reported. This suggests the only difference between the output files
is the PES-length fix.
A value of zero for the PES packet length can be added only when the PES packet
payload is a video stream.
.
Workaround:
A possible solution is to concatenate the .ts files, then take the output .ts file,
split this into a video file (.m4v) and an audio file (.m4a), and then remux them
(still as .ts format) using the "itsoffset" option.
Then it should be possible to convert the resulting .ts file to .mp4 or .mkv without
any error.
Not ideal, but it often works.

Is this transcoding the video?

I have an application used in government and subject to regulation that prevents transcoding or altering the video quality in any way.
I’m attempting to utilize FFmpeg to change a video into an MP4 by copying the raw streams to a new container.
This is the command being used:
ffmpeg.exe -y -i INPUT.ASF -c:av copy OUTPUT.MP4
Notice the -c:av copy. The FFmpeg documentation says, “a special value copy (output only) to indicate that the stream is not to be re-encoded.“
Visually the videos before and after appear to be identical quality with no pixelation on the ships.
Is this altering the video quality or could this be considered transcoding?
There's a syntax error but other than that, yes, copy will avoid transcoding of the stream. The hitch is that the output container may not support all codecs that the input container does.
ffmpeg.exe -y -i INPUT.ASF -c copy OUTPUT.MP4
Your current command was transcoding the video since ffmpeg's parser only consumes the first character in stream type i.e. -c:av is treated as -c:a. -c copy will copy all stream types. Use -c:v copy -c:a copy to separately set codec mode for video and audio.

Does ffmpeg supported KLV metadata?

Is ffmpeg metadata, which is also described in:
http://wiki.multimedia.cx/index.php?title=FFmpeg_Metadata
also supported MISB standard UAV metadata 601.5 ?
Is it same as KLV ?
Thanks,
Ran
FFMPEG does not natively support MISB KLV metadata or have demuxers or decoders for KLV metadata of these types at this time.
However, FFMPEG can be used to extract data elementary streams from containers like MPEG Transport Stream (TS) per ISO 13818-1. Such capability works for UDP streams and local MPEG TS Files. See the examples at end of response. The examples simply extract the data from the stream, they do not parse them. Parsing could easily be accomplished in real time by piping the output or post processing using many languages including C and Python.
It would be helpful to know specifically which containers you are trying to extract data from. In lieu of such information I have assumed MPEG TS in my response and examples. I would like to also point out that the current standard for "UAS Local Dataset" is now ST0601.8 at the time of this response.
I have personally tested the following examples with FFMPEG 2.5.4 on Mac OS X 10.9.5.
The following examples can be modified such that the output is sent to stdout by replacing the <outfile> with '-'.
Extract Data Stream From MPEG-TS File at Line Speed and Save to Binary File:
ffmpeg -i <MPEGTS_infile> -map d -codec copy -f data <binary_outfile>
Extract Data Stream From MPEG-TS File at Frame Rate and Save to Binary File:
ffmpeg -re -i <MPEGTS_infile> -map d -codec copy -f data <binary_outfile>
Extract Data Stream From MPEG-TS UDP Stream at Stream Rate and Save to Binary File:
ffmpeg -i udp://#<address:port> -map d -codec copy -f data <binary_outfile>
Extract Data Stream From MPEG-TS UDP Stream at Stream Rate and Direct to STDOUT:
ffmpeg -i udp://#<address:port> -map d -codec copy -f data -
Stream Video, Audio and Data Streams from MPEG-TS file Over UDP at Frame Rate:
ffmpeg -re -i <MPEGTS_infile> -map 0 -c copy -f mpegts udp://<address:port>
I'm unsure if UAV metadata 601.5 is the same as KLV, but FFmpeg can demux KLV metadata since commit 69a042e from 28 Oct 2013:
mpegts: demux synchronous SMPTE 336M Key-Length-Value (KLV) metadata
This fixes ticket #2579: Data stream from UAV video reported as "Unknown" type and without codec_id set, so you may find other relevant information there too.

FFmpeg Stream Transcoding

I have got a streaming application that displays the stream sent from a Flash Media Server.
I want to grab that stream and transcode it to a output stream with a different bitrate using ffmpeg.
Could such kind of thing be done using ffmpeg?
This will get input from a feed, and transcode it to an MKV file with default audio and video codecs, and 1024k bitrate for the video stream (audio bitrate is specified with '-ab'):
ffmpeg -i "http://my_server/video_feed" -b 1024k output.mkv
For a live feed try this (not sure if it'll work, I don't have ffmpeg to test it right now):
ffmpeg -i "http://my_server/input_video_feed" -b 1024 -f flv "http://my_server/output_video_feed"
This should create a FLV feed.

Resources