I would like to achieve the exact same result as this ffmpeg command line call does from code:
ffmpeg -i CAMERARTSPLINK -c:v copy -an -movflags +frag_keyframe+empty_moov -f mp4
When I run the above command it gives this binary result:
got 36 bytes: 0, 0, 0, 36, 102, 116, 121, 112, ..., 111, 54, 109, 112, 52, 49,
got 512 bytes: 0, 0, 3, 76, 109, 111, 111, 118, 0, 0, 0, ..., 132, 0, 0, 3, 0, 4, 0, 0, 3, 0, 202,
The code can utilize ffmpeg libraries and includes, but I don't want to use ffmpeg as a program call (i.e. exec* functions are not preferred).
I have created a small demonstration code example with avformat
for an RTSP H264 to MP4 remux.
The code is highly reuses horgh's nice videostreamer library.
I posted the sample code to pastebin.com (400 loc). It builds successfully but you need to link it against avformat
, avdevice
, avcodec
and avutil
.
I tried to do my best to reach the same result, however when I run this code, the first few bytes after byte #38 are different (maybe not just those, I did not compare anything after byte #548):
writeOutput: writing 36 bytes: 0, 0, 0, 36, 102, 116, 121, 112, ..., 111, 54, 109, 112, 52, 49,
writeOutput: writing 512 bytes: 0, 0, 0, 0, 109, 111, 111, 118, 0, 0, 0, ..., 132, 0, 0, 3, 0, 4, 0, 0, 3, 0, 202,
You can see on the second line of my code's output starts with 0
0
0
0
109
,
whereas the ffmpeg gave 0
0
3
76
109
.
All the rest (even the bytes are not pasted here) data are totally the same (at least for the first 548 bytes).
What is wrong with my code? These 2 bytes seems super-important for decoding this stream.
This was a silly mistake of ffmpeg's limited logging functionality plus my limited knowledge in video codecs.
The problem was that ffmpeg (with h264 input) when writes an atom to the output buffer:
This is all good, but during filling the rest of the buffer, it uses avio_w8 and avio_w8 will flush the buffer, if it reaches the end of it.
If you are using custom IO with avio_alloc_context
AND you don't define a buffer which is large enough AND you don't define the seek operation either AND the atom being written is larger than your buffer size, it will be flushed out and ffmpeg will not be able to seek back to update the atom's size.
And this will probably result in a corrupted (and unplayable) video output file or stream.
So the solution was to increase the buffer size from 512 to 4096 in this case moov atom can be fit even without seeking operation.
This is pretty straightforward if you know that the moov atom is larger that 512 bytes in length and look my sample code.