
Recherche avancée
Médias (1)
-
Video d’abeille en portrait
14 mai 2011, par
Mis à jour : Février 2012
Langue : français
Type : Video
Autres articles (32)
-
Emballe Médias : Mettre en ligne simplement des documents
29 octobre 2010, parLe plugin emballe médias a été développé principalement pour la distribution mediaSPIP mais est également utilisé dans d’autres projets proches comme géodiversité par exemple. Plugins nécessaires et compatibles
Pour fonctionner ce plugin nécessite que d’autres plugins soient installés : CFG Saisies SPIP Bonux Diogène swfupload jqueryui
D’autres plugins peuvent être utilisés en complément afin d’améliorer ses capacités : Ancres douces Légendes photo_infos spipmotion (...) -
Le plugin : Podcasts.
14 juillet 2010, parLe problème du podcasting est à nouveau un problème révélateur de la normalisation des transports de données sur Internet.
Deux formats intéressants existent : Celui développé par Apple, très axé sur l’utilisation d’iTunes dont la SPEC est ici ; Le format "Media RSS Module" qui est plus "libre" notamment soutenu par Yahoo et le logiciel Miro ;
Types de fichiers supportés dans les flux
Le format d’Apple n’autorise que les formats suivants dans ses flux : .mp3 audio/mpeg .m4a audio/x-m4a .mp4 (...) -
Support de tous types de médias
10 avril 2011Contrairement à beaucoup de logiciels et autres plate-formes modernes de partage de documents, MediaSPIP a l’ambition de gérer un maximum de formats de documents différents qu’ils soient de type : images (png, gif, jpg, bmp et autres...) ; audio (MP3, Ogg, Wav et autres...) ; vidéo (Avi, MP4, Ogv, mpg, mov, wmv et autres...) ; contenu textuel, code ou autres (open office, microsoft office (tableur, présentation), web (html, css), LaTeX, Google Earth) (...)
Sur d’autres sites (6490)
-
My python script using ffmpeg captures video content, but the captured content freezes in the middle and jumps frames
11 novembre 2022, par Supriyo MitraI am new to ffmpeg and I am trying to use it through a python script. The python functions that captures the video content is given below. The problem I am facing is that the captured content freezes at (uneven) intervals and skips a few frames every time it happens.


` def capturelivestream(self, argslist):
 streamurl, outnum, feedid, outfilename = argslist[0], argslist[1], argslist[2], argslist[3]
 try:
 info = ffmpeg.probe(streamurl, select_streams='a')
 streams = info.get('streams', [])
 except:
 streams = []
 if len(streams) == 0:
 print('There are no streams available')
 stream = {}
 else:
 stream = streams[0]
 for stream in streams:
 if stream.get('codec_type') != 'audio':
 continue
 else:
 break
 if 'channels' in stream.keys():
 channels = stream['channels']
 samplerate = float(stream['sample_rate'])
 else:
 channels = None
 samplerate = 44100
 process = ffmpeg.input(streamurl).output('pipe:', pix_fmt='yuv420p', format='avi', vcodec='libx264', acodec='pcm_s16le', ac=channels, ar=samplerate, vsync=0, loglevel='quiet').run_async(pipe_stdout=True)
 fpath = os.path.dirname(outfilename)
 fnamefext = os.path.basename(outfilename)
 fname = fnamefext.split(".")[0]
 read_size = 320 * 180 * 3 # This is width * height * 3
 lastcaptured = time.time()
 maxtries = 12
 ntries = 0
 while True:
 if process:
 inbytes = process.stdout.read(read_size)
 if inbytes is not None and inbytes.__len__() > 0:
 try:
 frame = (np.frombuffer(inbytes, np.uint8).reshape([180, 320, 3]))
 except:
 print("Failed to reshape frame: %s"%sys.exc_info()[1].__str__())
 continue # This could be an issue if there is a continuous supply of frames that cannot be reshaped
 self.processq.put([outnum, frame])
 lastcaptured = time.time()
 ntries = 0
 else:
 if self.DEBUG:
 print("Could not read frame for feed ID %s"%feedid)
 t = time.time()
 if t - lastcaptured > 30: # If the frames can't be read for more than 30 seconds...
 print("Reopening feed identified by feed ID %s"%feedid)
 process = ffmpeg.input(streamurl).output('pipe:', pix_fmt='yuv420p', format='avi', vcodec='libx264', acodec='pcm_s16le', ac=channels, ar=samplerate, vsync=0, loglevel='quiet').run_async(pipe_stdout=True)
 ntries += 1
 if ntries > maxtries:
 if self.DEBUG:
 print("Stream %s is no longer available."%streamurl)
 # DB statements removed here
 
 break # Break out of infinite loop.
 continue
 
 return None`




The function that captures the frames is as follows :



` def framewriter(self, outlist):
 isempty = False
 endofrun = False
 while True:
 frame = None
 try:
 args = self.processq.get()
 except: # Sometimes, the program crashes at this point due to lack of memory...
 print("Error in framewriter while reading from queue: %s"%sys.exc_info()[1].__str__())
 continue
 outnum = args[0]
 frame = args[1]
 if outlist.__len__() > outnum:
 out = outlist[outnum]
 else:
 if self.DEBUG == 2:
 print("Could not get writer %s"%outnum)
 continue
 if frame is not None and out is not None:
 out.write(frame)
 isempty = False
 endofrun = False
 else:
 if self.processq.empty() and not isempty:
 isempty = True
 elif self.processq.empty() and isempty: # processq queue is empty now and was empty last time
 print("processq is empty")
 endofrun = True
 elif endofrun and isempty:
 print("Could not find any frames to process. Quitting")
 break
 print("Done writing feeds. Quitting.")
 return None`



The scenario is as follows : There are multiple video streams from a certain website at any time during the day, and the program containing these functions has to capture them as they get streamed. The memory available to this program is 6GB and there could be upto 3 streams running at any instant. Given below is the relevant main section of the script that uses the functions given above.






`itftennis = VideoBot(siteurl)
outlist = []
t = Thread(target=itftennis.framewriter, args=(outlist,))
t.daemon = True
t.start()
tp = Thread(target=handleprocesstermination, args=())
tp.daemon = True
tp.start()
# Create a database connection and as associated cursor object. We will handle database operations from main thread only.
# DB statements removed from here...
feedidlist = []
vidsdict = {}
streampattern = re.compile("\?vid=(\d+)$")
while True:
 streampageurls = itftennis.checkforlivestream()
 if itftennis.DEBUG:
 print("Checking for new urls...")
 print(streampageurls.__len__())
 if streampageurls.__len__() > 0:
 argslist = []
 newurlscount = 0
 for streampageurl in streampageurls:
 newstream = False
 sps = re.search(streampattern, streampageurl)
 if sps:
 streamnum = sps.groups()[0]
 if streamnum not in vidsdict.keys(): # Check if this stream has already been processed.
 vidsdict[streamnum] = 1
 newstream = True
 else:
 continue
 else:
 continue
 print("Detected new live stream... Getting it.")
 streamurl = itftennis.getstreamurlfrompage(streampageurl)
 print("Adding %s to list..."%streamurl)
 if streamurl is not None:
 # Now, get feed metadata...
 metadata = itftennis.getfeedmetadata(streampageurl)
 if metadata is None:
 continue
 # lines to get matchescounter omitted here...
 if matchescounter >= itftennis.__class__.MAX_CONCURRENT_MATCHES:
 break
 if newstream is True:
 newurlscount += 1
 outfilename = time.strftime("./videodump/" + "%Y%m%d%H%M%S",time.localtime())+".avi"
 out = open(outfilename, "wb")
 outlist.append(out) # Save it in the list and take down the number for usage in framewriter
 outnum = outlist.__len__() - 1
 # Save metadata in DB
 # lines omitted here....
 argslist.append([streamurl, outnum, feedid, outfilename]) 
 else:
 print("Couldn't get the stream url from page")
 if newurlscount > 0:
 for args in argslist:
 try:
 p = Process(target=itftennis.capturelivestream, args=(args,))
 p.start()
 processeslist.append(p)
 if itftennis.DEBUG:
 print("Started process with args %s"%args)
 except:
 print("Could not start process due to error: %s"%sys.exc_info()[1].__str__())
 print("Created processes, continuing now...")
 continue
 time.sleep(itftennis.livestreamcheckinterval)
t.join()
tp.join()
for out in outlist:
 out.close()`







Please accept my apologies for swamping with this amount of code. I wanted to provide maximum context to my problem. I have removed the absolutely irrelevant DB statements, but apart from that this is what the code looks like.


If you need to know anything else about the code, please let me know. What I would really like to know is if I am using the ffmpeg streams capturing statements correctly. The stream contains both video and audio components and I need to capture both. Hence I am making the following call :


process = ffmpeg.input(streamurl).output('pipe:', pix_fmt='yuv420p', format='avi', vcodec='libx264', acodec='pcm_s16le', ac=channels, ar=samplerate, vsync=0, loglevel='quiet').run_async(pipe_stdout=True)



Is this how it is supposed to be done ? More importantly, why do I keep getting the freezes in the output video. I have monitored the streams manually, and they are quite consistent. Frame losses do not happen when I view them on the website (at least it is not obviously noticeable). Also, I have run 'top' command on the host running the program. The CPU usage sometimes go over 100% (which, I came to understand from some answers on SO, is to be expected when running ffmpeg) but the memory usage usually remain below 30%. So what is the issue here. What do I need to do in order to fix this problem (other than learn more about how ffmpeg works).


Thanks


I have tried using various ffmpeg options (while trying to find similar issues that others encountered). I also tried running ffmpeg from command line for a limited period of time (11 mins), using the same options as used in the python code, and the captured content came out quite well. No freezes. No jumps in frames. But I need to use it in an automated way and there would be multiple streams at any time. Also, when I try playing the captured content using ffplay, I sometimes get the message "co located POCs unavailable" when these freezes happen. What does it mean ?


-
FFmpeg to get usb camera video and push RSTP stream by c++
8 octobre 2022, par CrazyJack123What I want to do is get usb camera video and push rtsp stream via ffmpeg (not by command).
I've tried a few things and have successfully played RTSP streams through VLC media player using c++.


The problem now is that the rstp video received through the VLC media player has a high delay and is relatively stuck, and it will freeze after a period of time. But this phenomenon does not occur with the ffmpeg command (although there is a little delay, there will be no sucks and freeze).


The ffmpeg command and the c++ code are posted below.Can you help me locate the problem ? any help is greatly appreciated ! Thanks in advance !


By the way, the encoding environment is as follows : windows10, Qt5.9.0 msvc2013_64, ffmpeg-4.4.1-full_build-shared


The ffmpeg command is as follows :


.\ffmpeg.exe -f dshow -rtbufsize 100M -i video="USB Camera" -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -rtsp_transport udp -f rtsp rtsp://127.0.0.1/test



c++ code is as follows,here is
.h
:

#ifndef CAMERATHREADA_H
#define CAMERATHREADA_H

#include <exception>
#include <qimage>
#include <qdebug>
#include <qcamerainfo>
#include <qthread>
#include <qobject>
using namespace std;

extern "C"
{
 #include "libavformat/avformat.h"
 #include "libavutil/hwcontext.h"
 #include "libavutil/opt.h"
 #include "libavutil/time.h"
 #include "libavutil/frame.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/avassert.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/ffversion.h"
 #include "libavcodec/avcodec.h"
 #include "libswscale/swscale.h"
 #include "libavdevice/avdevice.h"
 #include "libavformat/avformat.h"
 #include "libavfilter/avfilter.h"
 #include "libavdevice/avdevice.h"
 #include "libavcodec/avcodec.h"
 #include "libavformat/avformat.h"
 #include "libavutil/pixfmt.h"
 #include "libswscale/swscale.h"
 #include "libavutil/time.h"
 #include "libavutil/mathematics.h"
}


#define FMT_PIC_SHOW AV_PIX_FMT_RGB24
#define FMT_FRM_PUSH AV_PIX_FMT_YUV420P


class CameraThreadA : public QThread
{
 Q_OBJECT
public:
 CameraThreadA();

signals:
 void receiveImage(QImage img);

private:

 //code to h264 and push
 int pushVideoindex;
 AVCodecContext *pushCodecCtx = nullptr;
 AVStream *pushStream;
 AVFormatContext* pushFmtCtx = nullptr;
 AVPacket* pushPkt = nullptr;
 AVCodec * pushCodec = nullptr;
 uint8_t *pushBuffer;
 struct SwsContext *swCtxRGB2YUV = nullptr;
 AVFrame* yuvFrame = av_frame_alloc();

 //receive from camera
 AVFormatContext* rcvFmtCtx = nullptr;
 AVInputFormat* rcvInFmt = nullptr;
 int nVideoIndex = -1;
 AVCodecParameters* rcvCodecPara = nullptr;
 AVCodecContext * rcvCodecCtx = nullptr;
 AVCodec * rcvCodec = nullptr;
 AVFrame* cameraFrame = av_frame_alloc();
 AVFrame* rgbFrame = av_frame_alloc();
 AVPacket* rcvPkt = nullptr;
 uint8_t* showBuffer;
 struct SwsContext *rcvSwsCtx = nullptr;

 // QThread interface
protected:
 void run();
};

#endif // CAMERATHREADA_H


</qobject></qthread></qcamerainfo></qdebug></qimage></exception>


here is
.cpp
:

#include "camerathreada.h"

CameraThreadA::CameraThreadA()
{
 //init camera to rgb
 avdevice_register_all();
 if(nullptr == (rcvFmtCtx = avformat_alloc_context()))
 {
 qDebug() << "create AVFormatContext failed." << endl;
 }
 if(nullptr == (rcvInFmt = const_cast(av_find_input_format("dshow"))))
 {
 qDebug() << "find AVInputFormat failed." << endl;
 }
 QString urlString = QString("video=USB Camera");
 if(avformat_open_input(&rcvFmtCtx
 , urlString.toStdString().c_str()
 , rcvInFmt, NULL) < 0)
 {
 qDebug() << "open camera failed." << endl;
 }
 if(avformat_find_stream_info(rcvFmtCtx, NULL) < 0){
 qDebug() << "cannot find stream info." << endl;
 }
 for(size_t i = 0;i < rcvFmtCtx->nb_streams;i++){
 if(rcvFmtCtx->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_VIDEO){
 nVideoIndex = i;
 }
 }
 if(nVideoIndex == -1){
 qDebug() << "cannot find video stream." << endl;
 }
 rcvCodecPara = rcvFmtCtx->streams[nVideoIndex]->codecpar;
 if(nullptr == (rcvCodec = const_cast(avcodec_find_decoder(rcvCodecPara->codec_id))))
 {
 qDebug() << "cannot find codec." << endl;
 }
 if(nullptr == (rcvCodecCtx = avcodec_alloc_context3(rcvCodec))){
 qDebug() << "cannot alloc codecContext." << endl;
 }
 if(avcodec_parameters_to_context(rcvCodecCtx, rcvCodecPara) < 0){
 qDebug() << "cannot initialize codecContext." << endl;
 }
 if(avcodec_open2(rcvCodecCtx, rcvCodec, NULL) < 0){
 qDebug() << "cannot open codec." << endl;
 return;
 }
 rcvSwsCtx = sws_getContext(rcvCodecCtx->width, rcvCodecCtx->height, rcvCodecCtx->pix_fmt,
 rcvCodecCtx->width, rcvCodecCtx->height, FMT_PIC_SHOW,
 SWS_BICUBIC, NULL, NULL, NULL);
 int numBytes = av_image_get_buffer_size(FMT_PIC_SHOW, rcvCodecCtx->width, rcvCodecCtx->height, 1);
 showBuffer = (unsigned char*)av_malloc(static_cast<unsigned long="long">(numBytes) * sizeof(unsigned char));
 if(av_image_fill_arrays(rgbFrame->data, rgbFrame->linesize,
 showBuffer
 , FMT_PIC_SHOW, rcvCodecCtx->width, rcvCodecCtx->height, 1) < 0)
 {
 qDebug() << "av_image_fill_arrays failed." << endl;
 }
 rcvPkt = av_packet_alloc();
 av_new_packet(rcvPkt, rcvCodecCtx->width * rcvCodecCtx->height);


 //init rgb to yuv
 swCtxRGB2YUV = sws_getContext(rcvCodecCtx->width, rcvCodecCtx->height, FMT_PIC_SHOW,
 rcvCodecCtx->width, rcvCodecCtx->height, FMT_FRM_PUSH,
 SWS_BICUBIC,NULL, NULL, NULL);

 yuvFrame->width = rcvCodecCtx->width;
 yuvFrame->height = rcvCodecCtx->height;
 yuvFrame->format = FMT_FRM_PUSH;
 pushBuffer = (uint8_t *)av_malloc(yuvFrame->width * yuvFrame->height * 1.5);
 if (av_image_fill_arrays(yuvFrame->data, yuvFrame->linesize
 , pushBuffer
 , FMT_FRM_PUSH, yuvFrame->width, yuvFrame->height, 1) < 0){
 qDebug() << "Failed: av_image_fill_arrays\n";
 }


 //init h264 codec
 pushCodec = const_cast(avcodec_find_encoder(AV_CODEC_ID_H264));
 if (!pushCodec){
 qDebug() << ("Fail: avcodec_find_encoder\n");
 }
 pushCodecCtx = avcodec_alloc_context3(pushCodec);
 if (!pushCodecCtx){
 qDebug() << ("Fail: avcodec_alloc_context3\n");
 }
 pushCodecCtx->pix_fmt = FMT_FRM_PUSH;
 pushCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
 pushCodecCtx->width = rcvCodecCtx->width;
 pushCodecCtx->height = rcvCodecCtx->height;
 pushCodecCtx->channels = 3;
 pushCodecCtx->time_base = { 1, 25 };
 pushCodecCtx->gop_size = 5; 
 pushCodecCtx->max_b_frames = 0;
 pushCodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
 av_opt_set(pushCodecCtx->priv_data, "preset", "ultrafast", 0);
 av_opt_set(pushCodecCtx->priv_data, "tune", "zerolatency", 0);
 if (avcodec_open2(pushCodecCtx, pushCodec, NULL) < 0){
 qDebug() << ("Fail: avcodec_open2\n");
 }
 pushPkt = av_packet_alloc();


 //init rtsp pusher
 QString des = QString("rtsp://127.0.0.1/test")
 if (avformat_alloc_output_context2(&pushFmtCtx, NULL, "rtsp", des.toStdString().c_str()) < 0){
 qDebug() << ("Fail: avformat_alloc_output_context2\n");
 }
 av_opt_set(pushFmtCtx->priv_data, "rtsp_transport", "udp", 0);
 pushFmtCtx->max_interleave_delta = 1000000;
 pushStream = avformat_new_stream(pushFmtCtx, pushCodec);
 if (!pushStream){
 qDebug() << ("Fail: avformat_new_stream\n");
 }
 pushStream->time_base = { 1, 25 };
 pushVideoindex = pushStream->id = pushFmtCtx->nb_streams - 1;
 pushCodecCtx->codec_tag = 0;
 if (pushFmtCtx->oformat->flags & AVFMT_GLOBALHEADER)
 {
 pushCodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
 }
 int ret = 0;
 ret = avcodec_parameters_from_context(pushStream->codecpar, pushCodecCtx);
 if (ret < 0)
 {
 qDebug() <<("Failed to copy codec context to out_stream codecpar context\n");
 }
 //av_dump_format(pushFmtCtx, 0, pushFmtCtx->filename, 1);
 if (!(pushFmtCtx->oformat->flags & AVFMT_NOFILE)) {
 if (avio_open(&pushFmtCtx->pb, "rtsp://127.0.0.1/test", AVIO_FLAG_WRITE) < 0) {
 qDebug() <<("Fail: avio_open('%s')\n rtsp://127.0.0.1/test");
 }
 }
 avformat_write_header(pushFmtCtx, NULL);
 
}

void CameraThreadA::run()
{
 int testCount = 0;
 int ret;
 while(av_read_frame(rcvFmtCtx, rcvPkt) >= 0){
 if(rcvPkt->stream_index == nVideoIndex){
 if(avcodec_send_packet(rcvCodecCtx, rcvPkt)>=0){
 while((ret = avcodec_receive_frame(rcvCodecCtx, cameraFrame)) >= 0){
 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
 return;
 else if (ret < 0) {
 return;
 }

 //rcv
 sws_scale(rcvSwsCtx,
 cameraFrame->data, cameraFrame->linesize,
 0, rcvCodecCtx->height,
 rgbFrame->data, rgbFrame->linesize);
 QImage img(showBuffer, rcvCodecCtx->width, rcvCodecCtx->height, QImage::Format_RGB888);
 emit receiveImage(img);
 
 //rgb 2 YUV
 if (sws_scale(swCtxRGB2YUV,
 rgbFrame->data, rgbFrame->linesize,
 0, rcvCodecCtx->height,
 yuvFrame->data, yuvFrame->linesize) < 0)
 {
 qDebug() << "fail : rgb 2 YUV\n";
 }
 yuvFrame->pts = av_gettime();

 //code h264
 ret = avcodec_send_frame(pushCodecCtx, yuvFrame);
 if (ret < 0){
 qDebug() << "send frame fail\n" << ret;
 }
 while (ret >= 0){
 ret = avcodec_receive_packet(pushCodecCtx, pushPkt);
 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF){
 qDebug() <<("ret == AVERROR(EAGAIN) || ret == AVERROR_EOF\n");
 break;
 }else if (ret < 0){
 qDebug() <<("Error during encoding\n");
 break;
 }else{
 pushPkt->stream_index = pushVideoindex;
 if (av_interleaved_write_frame(pushFmtCtx, pushPkt) < 0) {
 qDebug() << ("Error muxing packet\n");
 }
 av_packet_unref(pushPkt);
 }
 }
 testCount ++;
 QThread::msleep(10);
 }
 }
 av_packet_unref(rcvPkt);
 }
 }
}

</unsigned>


-
Getting shifted timestamps when encoding a fragmented h264 mp4 with ffmpeg
14 septembre 2022, par Martin CastinI am trying to encode a fragmented h264 mp4 with ffmpeg. I tried the following command :


ffmpeg -i input.mp4 -movflags +frag_keyframe+separate_moof+omit_tfhd_offset+empty_moov output.mp4



It does give me a fragmented mp4 but the timestamps of the frames seem to be shifted by 0.04s when I read the video with mpv. The first frame has a timestamp of 0.04s instead of 0s, as in the input video (1920x1080, 50 fps). I encountered the problem both with ffmpeg 5.1 and ffmpeg 3.4.11.


I tried to add several flags, as
-avoid_negative_ts make_zero
or-copyts -output_ts_offset -0.04
, but it did not help.

I am also trying to achieve this using the ffmpeg libav libraries in C++ but did not get to better result. Here are the code fragments I used.


avformat_alloc_output_context2(&oc, NULL, NULL, filename);

 if (oc_->oformat->flags & AVFMT_GLOBALHEADER) {
 codecCtx_->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
 }
...
 AVDictionary* opts = NULL;

 av_dict_set(&opts, "movflags", "frag_keyframe+separate_moof+omit_tfhd_offset+empty_moov", 0);

 ret = avformat_write_header(oc_, &opts);



Do you know how to avoid this behaviour of shifted timestamps for fragmented mp4, either with ffmpeg or libav ?


Edit : example videos and complete code example


I also tried with the following ffmpeg build


ffmpeg version 5.0.1-static https://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2022 the FFmpeg developers
built with gcc 8 (Debian 8.3.0-6)
configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gmp --enable-libgme --enable-gray --enable-libaom --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libdav1d --enable-libxvid --enable-libzvbi --enable-libzimg
libavutil 57. 17.100 / 57. 17.100
libavcodec 59. 18.100 / 59. 18.100
libavformat 59. 16.100 / 59. 16.100
libavdevice 59. 4.100 / 59. 4.100
libavfilter 8. 24.100 / 8. 24.100
libswscale 6. 4.100 / 6. 4.100
libswresample 4. 3.100 / 4. 3.100
libpostproc 56. 3.100 / 56. 3.100



and with the sintel trailer as input video, which is 24fps, and I thus get a timeshift of 83ms. Here is the output I get.


Here is a complete code example, slightly adapted from the
muxing.c
ffmpeg example (audio removed and adapted for c++). This code shows exactly the same problem.

You can just comment the line 383 (that is calling
av_dict_set
) to switch back to a not fragmented mp4 that will not have the timestamp shift.

/*
 * Copyright (c) 2003 Fabrice Bellard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
 * @file
 * libavformat API example.
 *
 * Output a media file in any supported libavformat format. The default
 * codecs are used.
 * @example muxing.c
 */

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>

extern "C"
{
#define __STDC_CONSTANT_MACROS
#include <libavutil></libavutil>avassert.h>
#include <libavutil></libavutil>channel_layout.h>
#include <libavutil></libavutil>opt.h>
#include <libavutil></libavutil>mathematics.h>
#include <libavutil></libavutil>timestamp.h>
#include <libavcodec></libavcodec>avcodec.h>
#include <libavformat></libavformat>avformat.h>
#include <libswscale></libswscale>swscale.h>
#include <libswresample></libswresample>swresample.h>
}

#define STREAM_DURATION 10.0
#define STREAM_FRAME_RATE 25 /* 25 images/s */
#define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */

#define SCALE_FLAGS SWS_BICUBIC

// a wrapper around a single output AVStream
typedef struct OutputStream {
 AVStream *st;
 AVCodecContext *enc;

 /* pts of the next frame that will be generated */
 int64_t next_pts;
 int samples_count;

 AVFrame *frame;
 AVFrame *tmp_frame;

 AVPacket *tmp_pkt;

 float t, tincr, tincr2;

 struct SwsContext *sws_ctx;
 struct SwrContext *swr_ctx;
} OutputStream;

static void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt)
{
 AVRational *time_base = &fmt_ctx->streams[pkt->stream_index]->time_base;

// printf("pts:%s pts_time:%s dts:%s dts_time:%s duration:%s duration_time:%s stream_index:%d\n",
// av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, time_base),
// av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, time_base),
// av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, time_base),
// pkt->stream_index);
}

static int write_frame(AVFormatContext *fmt_ctx, AVCodecContext *c,
 AVStream *st, AVFrame *frame, AVPacket *pkt)
{
 int ret;

 // send the frame to the encoder
 ret = avcodec_send_frame(c, frame);
 if (ret < 0) {
 fprintf(stderr, "Error sending a frame to the encoder");
 exit(1);
 }

 while (ret >= 0) {
 ret = avcodec_receive_packet(c, pkt);
 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
 break;
 else if (ret < 0) {
 fprintf(stderr, "Error encoding a frame\n");
 exit(1);
 }

 /* rescale output packet timestamp values from codec to stream timebase */
 av_packet_rescale_ts(pkt, c->time_base, st->time_base);
 pkt->stream_index = st->index;

 /* Write the compressed frame to the media file. */
 log_packet(fmt_ctx, pkt);
 ret = av_interleaved_write_frame(fmt_ctx, pkt);
 /* pkt is now blank (av_interleaved_write_frame() takes ownership of
 * its contents and resets pkt), so that no unreferencing is necessary.
 * This would be different if one used av_write_frame(). */
 if (ret < 0) {
 fprintf(stderr, "Error while writing output packet\n");
 exit(1);
 }
 }

 return ret == AVERROR_EOF ? 1 : 0;
}

/* Add an output stream. */
static void add_stream(OutputStream *ost, AVFormatContext *oc,
 const AVCodec **codec,
 enum AVCodecID codec_id)
{
 AVCodecContext *c;
 int i;

 /* find the encoder */
 *codec = avcodec_find_encoder(codec_id);
 if (!(*codec)) {
 fprintf(stderr, "Could not find encoder for '%s'\n",
 avcodec_get_name(codec_id));
 exit(1);
 }

 ost->tmp_pkt = av_packet_alloc();
 if (!ost->tmp_pkt) {
 fprintf(stderr, "Could not allocate AVPacket\n");
 exit(1);
 }

 ost->st = avformat_new_stream(oc, NULL);
 if (!ost->st) {
 fprintf(stderr, "Could not allocate stream\n");
 exit(1);
 }
 ost->st->id = oc->nb_streams-1;
 c = avcodec_alloc_context3(*codec);
 if (!c) {
 fprintf(stderr, "Could not alloc an encoding context\n");
 exit(1);
 }
 ost->enc = c;

 switch ((*codec)->type) {
 case AVMEDIA_TYPE_VIDEO:
 c->codec_id = codec_id;

 c->bit_rate = 400000;
 /* Resolution must be a multiple of two. */
 c->width = 352;
 c->height = 288;
 /* timebase: This is the fundamental unit of time (in seconds) in terms
 * of which frame timestamps are represented. For fixed-fps content,
 * timebase should be 1/framerate and timestamp increments should be
 * identical to 1. */
 ost->st->time_base = (AVRational){ 1, STREAM_FRAME_RATE };
 c->time_base = ost->st->time_base;

 c->gop_size = 12; /* emit one intra frame every twelve frames at most */
 c->pix_fmt = STREAM_PIX_FMT;
 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
 /* just for testing, we also add B-frames */
 c->max_b_frames = 2;
 }
 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
 /* Needed to avoid using macroblocks in which some coeffs overflow.
 * This does not happen with normal video, it just happens here as
 * the motion of the chroma plane does not match the luma plane. */
 c->mb_decision = 2;
 }
 break;

 default:
 break;
 }

 /* Some formats want stream headers to be separate. */
 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}

/**************************************************************/
/* video output */

static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height)
{
 AVFrame *picture;
 int ret;

 picture = av_frame_alloc();
 if (!picture)
 return NULL;

 picture->format = pix_fmt;
 picture->width = width;
 picture->height = height;

 /* allocate the buffers for the frame data */
 ret = av_frame_get_buffer(picture, 0);
 if (ret < 0) {
 fprintf(stderr, "Could not allocate frame data.\n");
 exit(1);
 }

 return picture;
}

static void open_video(AVFormatContext *oc, const AVCodec *codec,
 OutputStream *ost, AVDictionary *opt_arg)
{
 int ret;
 AVCodecContext *c = ost->enc;
 AVDictionary *opt = NULL;

 av_dict_copy(&opt, opt_arg, 0);

 /* open the codec */
 ret = avcodec_open2(c, codec, &opt);
 av_dict_free(&opt);
 if (ret < 0) {
 fprintf(stderr, "Could not open video codec\n");
 exit(1);
 }

 /* allocate and init a re-usable frame */
 ost->frame = alloc_picture(c->pix_fmt, c->width, c->height);
 if (!ost->frame) {
 fprintf(stderr, "Could not allocate video frame\n");
 exit(1);
 }

 /* If the output format is not YUV420P, then a temporary YUV420P
 * picture is needed too. It is then converted to the required
 * output format. */
 ost->tmp_frame = NULL;
 if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
 ost->tmp_frame = alloc_picture(AV_PIX_FMT_YUV420P, c->width, c->height);
 if (!ost->tmp_frame) {
 fprintf(stderr, "Could not allocate temporary picture\n");
 exit(1);
 }
 }

 /* copy the stream parameters to the muxer */
 ret = avcodec_parameters_from_context(ost->st->codecpar, c);
 if (ret < 0) {
 fprintf(stderr, "Could not copy the stream parameters\n");
 exit(1);
 }
}

/* Prepare a dummy image. */
static void fill_yuv_image(AVFrame *pict, int frame_index,
 int width, int height)
{
 int x, y, i;

 i = frame_index;

 /* Y */
 for (y = 0; y < height; y++)
 for (x = 0; x < width; x++)
 pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;

 /* Cb and Cr */
 for (y = 0; y < height / 2; y++) {
 for (x = 0; x < width / 2; x++) {
 pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
 pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
 }
 }
}

static AVFrame *get_video_frame(OutputStream *ost)
{
 AVCodecContext *c = ost->enc;

 /* check if we want to generate more frames */
 if (av_compare_ts(ost->next_pts, c->time_base,
 STREAM_DURATION, (AVRational){ 1, 1 }) > 0)
 return NULL;

 /* when we pass a frame to the encoder, it may keep a reference to it
 * internally; make sure we do not overwrite it here */
 if (av_frame_make_writable(ost->frame) < 0)
 exit(1);

 if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
 /* as we only generate a YUV420P picture, we must convert it
 * to the codec pixel format if needed */
 if (!ost->sws_ctx) {
 ost->sws_ctx = sws_getContext(c->width, c->height,
 AV_PIX_FMT_YUV420P,
 c->width, c->height,
 c->pix_fmt,
 SCALE_FLAGS, NULL, NULL, NULL);
 if (!ost->sws_ctx) {
 fprintf(stderr,
 "Could not initialize the conversion context\n");
 exit(1);
 }
 }
 fill_yuv_image(ost->tmp_frame, ost->next_pts, c->width, c->height);
 sws_scale(ost->sws_ctx, (const uint8_t * const *) ost->tmp_frame->data,
 ost->tmp_frame->linesize, 0, c->height, ost->frame->data,
 ost->frame->linesize);
 } else {
 fill_yuv_image(ost->frame, ost->next_pts, c->width, c->height);
 }

 ost->frame->pts = ost->next_pts++;

 return ost->frame;
}

/*
 * encode one video frame and send it to the muxer
 * return 1 when encoding is finished, 0 otherwise
 */
static int write_video_frame(AVFormatContext *oc, OutputStream *ost)
{
 return write_frame(oc, ost->enc, ost->st, get_video_frame(ost), ost->tmp_pkt);
}

static void close_stream(AVFormatContext *oc, OutputStream *ost)
{
 avcodec_free_context(&ost->enc);
 av_frame_free(&ost->frame);
 av_frame_free(&ost->tmp_frame);
 av_packet_free(&ost->tmp_pkt);
 sws_freeContext(ost->sws_ctx);
 swr_free(&ost->swr_ctx);
}

/**************************************************************/
/* media file output */

int main(int argc, char **argv)
{
 OutputStream video_st = { 0 }, audio_st = { 0 };
 const AVOutputFormat *fmt;
 const char *filename;
 AVFormatContext *oc;
 const AVCodec *audio_codec, *video_codec;
 int ret;
 int have_video = 0, have_audio = 0;
 int encode_video = 0, encode_audio = 0;
 AVDictionary *opt = NULL;
 int i;

 if (argc < 2) {
 printf("usage: %s output_file\n"
 "API example program to output a media file with libavformat.\n"
 "This program generates a synthetic audio and video stream, encodes and\n"
 "muxes them into a file named output_file.\n"
 "The output format is automatically guessed according to the file extension.\n"
 "Raw images can also be output by using '%%d' in the filename.\n"
 "\n", argv[0]);
 return 1;
 }

 filename = argv[1];

 av_dict_set(&opt, "movflags", "frag_keyframe+separate_moof+omit_tfhd_offset+empty_moov", 0);

 /* allocate the output media context */
 avformat_alloc_output_context2(&oc, NULL, NULL, filename);
 if (!oc) {
 printf("Could not deduce output format from file extension: using MPEG.\n");
 avformat_alloc_output_context2(&oc, NULL, "mpeg", filename);
 }
 if (!oc)
 return 1;

 fmt = oc->oformat;

 /* Add the audio and video streams using the default format codecs
 * and initialize the codecs. */
 if (fmt->video_codec != AV_CODEC_ID_NONE) {
 add_stream(&video_st, oc, &video_codec, fmt->video_codec);
 have_video = 1;
 encode_video = 1;
 }

 /* Now that all the parameters are set, we can open the audio and
 * video codecs and allocate the necessary encode buffers. */
 if (have_video)
 open_video(oc, video_codec, &video_st, opt);


 av_dump_format(oc, 0, filename, 1);

 /* open the output file, if needed */
 if (!(fmt->flags & AVFMT_NOFILE)) {
 ret = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE);
 if (ret < 0) {
 fprintf(stderr, "Could not open '%s'\n", filename);
 return 1;
 }
 }

 /* Write the stream header, if any. */
 ret = avformat_write_header(oc, &opt);
 if (ret < 0) {
 fprintf(stderr, "Error occurred when opening output file\n");
 return 1;
 }

 while (encode_video || encode_audio) {
 /* select the stream to encode */
 if (encode_video &&
 (!encode_audio || av_compare_ts(video_st.next_pts, video_st.enc->time_base,
 audio_st.next_pts, audio_st.enc->time_base) <= 0)) {
 encode_video = !write_video_frame(oc, &video_st);
 }
 }

 av_write_trailer(oc);

 /* Close each codec. */
 if (have_video)
 close_stream(oc, &video_st);
 if (have_audio)
 close_stream(oc, &audio_st);

 if (!(fmt->flags & AVFMT_NOFILE))
 /* Close the output file. */
 avio_closep(&oc->pb);

 /* free the stream */
 avformat_free_context(oc);

 return 0;
}
</cmath></cstring></cstdio></cstdlib>