At least on FFmpeg 2.8.x (but oldie should works too) you can use
lavfi as input format and complex filter graph using
setpts filters as a argument for
Next command doing this work for you:
ffmpeg -re -f lavfi -i "movie=filename=input.mp4:loop=0, setpts=N/(FRAME_RATE*TB)" output.mp4
loop= arguments means infinity loop. Values greater zero sets repeat counts.
setpts filters required for PTS adjusting for second and later repeats, otherwise most output muxers will fails with non-monotonic PTS increasing: loop does not recalc PTS.
Note, that using filters assuming that bypass frames without decoding/encoding is impossible: by design filters deals with decoded frames only.
At the FFmpeg 2.8.2 new input option
-stream_loop inroduced. I first look it works more simple and allows copy content without transcoding:
ffmpeg -re -stream_loop -1 -i input.mp4 -c copy -y output.mp4
But it does not recalculate PTS and output file is wrong. If you add filter to fix PTS (see
setpts) you must remove
-c copy too. Only bitstream filters can deals with encoded packets, but there is no any bitstream filters to fix PTS (see: https://ffmpeg.org/ffmpeg-bitstream-filters.html)
In any case ffmpeg on second pass fails with error:
input.mp4: Resource temporarily unavailable
Known work around for me: use container for input file without PTS limits (streaming container). One of them, known me, is MPEG-TS. So, you can simple convert your MP4 file to the MPEG-TS:
ffmpeg -i input.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts input.ts
And use next command to compose infinity file:
ffmpeg -re -stream_loop -1 -i input.ts -c copy -strict -2 -bsf:a aac_adtstoasc -y output.mp4
(bitstream filters should be used only if needed, on my samples it is required)
FFmpeg >= 2.8.2 is required in this case.