Recherche avancée

Médias (0)

Mot : - Tags -/performance

Aucun média correspondant à vos critères n’est disponible sur le site.

Autres articles (61)

  • Websites made ​​with MediaSPIP

    2 mai 2011, par

    This page lists some websites based on MediaSPIP.

  • Creating farms of unique websites

    13 avril 2011, par

    MediaSPIP platforms can be installed as a farm, with a single "core" hosted on a dedicated server and used by multiple websites.
    This allows (among other things) : implementation costs to be shared between several different projects / individuals rapid deployment of multiple unique sites creation of groups of like-minded sites, making it possible to browse media in a more controlled and selective environment than the major "open" (...)

  • Ecrire une actualité

    21 juin 2013, par

    Présentez les changements dans votre MédiaSPIP ou les actualités de vos projets sur votre MédiaSPIP grâce à la rubrique actualités.
    Dans le thème par défaut spipeo de MédiaSPIP, les actualités sont affichées en bas de la page principale sous les éditoriaux.
    Vous pouvez personnaliser le formulaire de création d’une actualité.
    Formulaire de création d’une actualité Dans le cas d’un document de type actualité, les champs proposés par défaut sont : Date de publication ( personnaliser la date de publication ) (...)

Sur d’autres sites (7208)

  • creating a video from images

    12 septembre 2022, par ALAEDDIN

    My goal is to create a video from images using videoshow : a utility for node/io.js to create straightforward video slideshows based on images using FFmpeg.

    


    The problem i have is when i add more images like 3 with a display resolution of 1024x instead of 640x as in default the program/virtual machine (aws - t3.micro) freezes..until i force a restart in the console.. , but with 2 images the video is rendered just fine..

    


    I guess it's related to the memory.. how i can solve the issue and where i can see the logs ?

    


  • Getting shifted timestamps when encoding a fragmented h264 mp4 with ffmpeg

    14 septembre 2022, par Martin Castin

    I 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.

    


    /*&#xA; * Copyright (c) 2003 Fabrice Bellard&#xA; *&#xA; * Permission is hereby granted, free of charge, to any person obtaining a copy&#xA; * of this software and associated documentation files (the "Software"), to deal&#xA; * in the Software without restriction, including without limitation the rights&#xA; * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell&#xA; * copies of the Software, and to permit persons to whom the Software is&#xA; * furnished to do so, subject to the following conditions:&#xA; *&#xA; * The above copyright notice and this permission notice shall be included in&#xA; * all copies or substantial portions of the Software.&#xA; *&#xA; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR&#xA; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,&#xA; * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL&#xA; * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER&#xA; * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,&#xA; * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN&#xA; * THE SOFTWARE.&#xA; */&#xA;&#xA;/**&#xA; * @file&#xA; * libavformat API example.&#xA; *&#xA; * Output a media file in any supported libavformat format. The default&#xA; * codecs are used.&#xA; * @example muxing.c&#xA; */&#xA;&#xA;#include <cstdlib>&#xA;#include <cstdio>&#xA;#include <cstring>&#xA;#include <cmath>&#xA;&#xA;extern "C"&#xA;{&#xA;#define __STDC_CONSTANT_MACROS&#xA;#include <libavutil></libavutil>avassert.h>&#xA;#include <libavutil></libavutil>channel_layout.h>&#xA;#include <libavutil></libavutil>opt.h>&#xA;#include <libavutil></libavutil>mathematics.h>&#xA;#include <libavutil></libavutil>timestamp.h>&#xA;#include <libavcodec></libavcodec>avcodec.h>&#xA;#include <libavformat></libavformat>avformat.h>&#xA;#include <libswscale></libswscale>swscale.h>&#xA;#include <libswresample></libswresample>swresample.h>&#xA;}&#xA;&#xA;#define STREAM_DURATION   10.0&#xA;#define STREAM_FRAME_RATE 25 /* 25 images/s */&#xA;#define STREAM_PIX_FMT    AV_PIX_FMT_YUV420P /* default pix_fmt */&#xA;&#xA;#define SCALE_FLAGS SWS_BICUBIC&#xA;&#xA;// a wrapper around a single output AVStream&#xA;typedef struct OutputStream {&#xA;  AVStream *st;&#xA;  AVCodecContext *enc;&#xA;&#xA;  /* pts of the next frame that will be generated */&#xA;  int64_t next_pts;&#xA;  int samples_count;&#xA;&#xA;  AVFrame *frame;&#xA;  AVFrame *tmp_frame;&#xA;&#xA;  AVPacket *tmp_pkt;&#xA;&#xA;  float t, tincr, tincr2;&#xA;&#xA;  struct SwsContext *sws_ctx;&#xA;  struct SwrContext *swr_ctx;&#xA;} OutputStream;&#xA;&#xA;static void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt)&#xA;{&#xA;  AVRational *time_base = &amp;fmt_ctx->streams[pkt->stream_index]->time_base;&#xA;&#xA;//  printf("pts:%s pts_time:%s dts:%s dts_time:%s duration:%s duration_time:%s stream_index:%d\n",&#xA;//         av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, time_base),&#xA;//         av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, time_base),&#xA;//         av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, time_base),&#xA;//         pkt->stream_index);&#xA;}&#xA;&#xA;static int write_frame(AVFormatContext *fmt_ctx, AVCodecContext *c,&#xA;                       AVStream *st, AVFrame *frame, AVPacket *pkt)&#xA;{&#xA;  int ret;&#xA;&#xA;  // send the frame to the encoder&#xA;  ret = avcodec_send_frame(c, frame);&#xA;  if (ret &lt; 0) {&#xA;    fprintf(stderr, "Error sending a frame to the encoder");&#xA;    exit(1);&#xA;  }&#xA;&#xA;  while (ret >= 0) {&#xA;    ret = avcodec_receive_packet(c, pkt);&#xA;    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)&#xA;      break;&#xA;    else if (ret &lt; 0) {&#xA;      fprintf(stderr, "Error encoding a frame\n");&#xA;      exit(1);&#xA;    }&#xA;&#xA;    /* rescale output packet timestamp values from codec to stream timebase */&#xA;    av_packet_rescale_ts(pkt, c->time_base, st->time_base);&#xA;    pkt->stream_index = st->index;&#xA;&#xA;    /* Write the compressed frame to the media file. */&#xA;    log_packet(fmt_ctx, pkt);&#xA;    ret = av_interleaved_write_frame(fmt_ctx, pkt);&#xA;    /* pkt is now blank (av_interleaved_write_frame() takes ownership of&#xA;     * its contents and resets pkt), so that no unreferencing is necessary.&#xA;     * This would be different if one used av_write_frame(). */&#xA;    if (ret &lt; 0) {&#xA;      fprintf(stderr, "Error while writing output packet\n");&#xA;      exit(1);&#xA;    }&#xA;  }&#xA;&#xA;  return ret == AVERROR_EOF ? 1 : 0;&#xA;}&#xA;&#xA;/* Add an output stream. */&#xA;static void add_stream(OutputStream *ost, AVFormatContext *oc,&#xA;                       const AVCodec **codec,&#xA;                       enum AVCodecID codec_id)&#xA;{&#xA;  AVCodecContext *c;&#xA;  int i;&#xA;&#xA;  /* find the encoder */&#xA;  *codec = avcodec_find_encoder(codec_id);&#xA;  if (!(*codec)) {&#xA;    fprintf(stderr, "Could not find encoder for &#x27;%s&#x27;\n",&#xA;            avcodec_get_name(codec_id));&#xA;    exit(1);&#xA;  }&#xA;&#xA;  ost->tmp_pkt = av_packet_alloc();&#xA;  if (!ost->tmp_pkt) {&#xA;    fprintf(stderr, "Could not allocate AVPacket\n");&#xA;    exit(1);&#xA;  }&#xA;&#xA;  ost->st = avformat_new_stream(oc, NULL);&#xA;  if (!ost->st) {&#xA;    fprintf(stderr, "Could not allocate stream\n");&#xA;    exit(1);&#xA;  }&#xA;  ost->st->id = oc->nb_streams-1;&#xA;  c = avcodec_alloc_context3(*codec);&#xA;  if (!c) {&#xA;    fprintf(stderr, "Could not alloc an encoding context\n");&#xA;    exit(1);&#xA;  }&#xA;  ost->enc = c;&#xA;&#xA;  switch ((*codec)->type) {&#xA;    case AVMEDIA_TYPE_VIDEO:&#xA;      c->codec_id = codec_id;&#xA;&#xA;      c->bit_rate = 400000;&#xA;      /* Resolution must be a multiple of two. */&#xA;      c->width    = 352;&#xA;      c->height   = 288;&#xA;      /* timebase: This is the fundamental unit of time (in seconds) in terms&#xA;       * of which frame timestamps are represented. For fixed-fps content,&#xA;       * timebase should be 1/framerate and timestamp increments should be&#xA;       * identical to 1. */&#xA;      ost->st->time_base = (AVRational){ 1, STREAM_FRAME_RATE };&#xA;      c->time_base       = ost->st->time_base;&#xA;&#xA;      c->gop_size      = 12; /* emit one intra frame every twelve frames at most */&#xA;      c->pix_fmt       = STREAM_PIX_FMT;&#xA;      if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {&#xA;        /* just for testing, we also add B-frames */&#xA;        c->max_b_frames = 2;&#xA;      }&#xA;      if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {&#xA;        /* Needed to avoid using macroblocks in which some coeffs overflow.&#xA;         * This does not happen with normal video, it just happens here as&#xA;         * the motion of the chroma plane does not match the luma plane. */&#xA;        c->mb_decision = 2;&#xA;      }&#xA;      break;&#xA;&#xA;    default:&#xA;      break;&#xA;  }&#xA;&#xA;  /* Some formats want stream headers to be separate. */&#xA;  if (oc->oformat->flags &amp; AVFMT_GLOBALHEADER)&#xA;    c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;&#xA;}&#xA;&#xA;/**************************************************************/&#xA;/* video output */&#xA;&#xA;static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height)&#xA;{&#xA;  AVFrame *picture;&#xA;  int ret;&#xA;&#xA;  picture = av_frame_alloc();&#xA;  if (!picture)&#xA;    return NULL;&#xA;&#xA;  picture->format = pix_fmt;&#xA;  picture->width  = width;&#xA;  picture->height = height;&#xA;&#xA;  /* allocate the buffers for the frame data */&#xA;  ret = av_frame_get_buffer(picture, 0);&#xA;  if (ret &lt; 0) {&#xA;    fprintf(stderr, "Could not allocate frame data.\n");&#xA;    exit(1);&#xA;  }&#xA;&#xA;  return picture;&#xA;}&#xA;&#xA;static void open_video(AVFormatContext *oc, const AVCodec *codec,&#xA;                       OutputStream *ost, AVDictionary *opt_arg)&#xA;{&#xA;  int ret;&#xA;  AVCodecContext *c = ost->enc;&#xA;  AVDictionary *opt = NULL;&#xA;&#xA;  av_dict_copy(&amp;opt, opt_arg, 0);&#xA;&#xA;  /* open the codec */&#xA;  ret = avcodec_open2(c, codec, &amp;opt);&#xA;  av_dict_free(&amp;opt);&#xA;  if (ret &lt; 0) {&#xA;    fprintf(stderr, "Could not open video codec\n");&#xA;    exit(1);&#xA;  }&#xA;&#xA;  /* allocate and init a re-usable frame */&#xA;  ost->frame = alloc_picture(c->pix_fmt, c->width, c->height);&#xA;  if (!ost->frame) {&#xA;    fprintf(stderr, "Could not allocate video frame\n");&#xA;    exit(1);&#xA;  }&#xA;&#xA;  /* If the output format is not YUV420P, then a temporary YUV420P&#xA;   * picture is needed too. It is then converted to the required&#xA;   * output format. */&#xA;  ost->tmp_frame = NULL;&#xA;  if (c->pix_fmt != AV_PIX_FMT_YUV420P) {&#xA;    ost->tmp_frame = alloc_picture(AV_PIX_FMT_YUV420P, c->width, c->height);&#xA;    if (!ost->tmp_frame) {&#xA;      fprintf(stderr, "Could not allocate temporary picture\n");&#xA;      exit(1);&#xA;    }&#xA;  }&#xA;&#xA;  /* copy the stream parameters to the muxer */&#xA;  ret = avcodec_parameters_from_context(ost->st->codecpar, c);&#xA;  if (ret &lt; 0) {&#xA;    fprintf(stderr, "Could not copy the stream parameters\n");&#xA;    exit(1);&#xA;  }&#xA;}&#xA;&#xA;/* Prepare a dummy image. */&#xA;static void fill_yuv_image(AVFrame *pict, int frame_index,&#xA;                           int width, int height)&#xA;{&#xA;  int x, y, i;&#xA;&#xA;  i = frame_index;&#xA;&#xA;  /* Y */&#xA;  for (y = 0; y &lt; height; y&#x2B;&#x2B;)&#xA;    for (x = 0; x &lt; width; x&#x2B;&#x2B;)&#xA;      pict->data[0][y * pict->linesize[0] &#x2B; x] = x &#x2B; y &#x2B; i * 3;&#xA;&#xA;  /* Cb and Cr */&#xA;  for (y = 0; y &lt; height / 2; y&#x2B;&#x2B;) {&#xA;    for (x = 0; x &lt; width / 2; x&#x2B;&#x2B;) {&#xA;      pict->data[1][y * pict->linesize[1] &#x2B; x] = 128 &#x2B; y &#x2B; i * 2;&#xA;      pict->data[2][y * pict->linesize[2] &#x2B; x] = 64 &#x2B; x &#x2B; i * 5;&#xA;    }&#xA;  }&#xA;}&#xA;&#xA;static AVFrame *get_video_frame(OutputStream *ost)&#xA;{&#xA;  AVCodecContext *c = ost->enc;&#xA;&#xA;  /* check if we want to generate more frames */&#xA;  if (av_compare_ts(ost->next_pts, c->time_base,&#xA;                    STREAM_DURATION, (AVRational){ 1, 1 }) > 0)&#xA;    return NULL;&#xA;&#xA;  /* when we pass a frame to the encoder, it may keep a reference to it&#xA;   * internally; make sure we do not overwrite it here */&#xA;  if (av_frame_make_writable(ost->frame) &lt; 0)&#xA;    exit(1);&#xA;&#xA;  if (c->pix_fmt != AV_PIX_FMT_YUV420P) {&#xA;    /* as we only generate a YUV420P picture, we must convert it&#xA;     * to the codec pixel format if needed */&#xA;    if (!ost->sws_ctx) {&#xA;      ost->sws_ctx = sws_getContext(c->width, c->height,&#xA;                                    AV_PIX_FMT_YUV420P,&#xA;                                    c->width, c->height,&#xA;                                    c->pix_fmt,&#xA;                                    SCALE_FLAGS, NULL, NULL, NULL);&#xA;      if (!ost->sws_ctx) {&#xA;        fprintf(stderr,&#xA;                "Could not initialize the conversion context\n");&#xA;        exit(1);&#xA;      }&#xA;    }&#xA;    fill_yuv_image(ost->tmp_frame, ost->next_pts, c->width, c->height);&#xA;    sws_scale(ost->sws_ctx, (const uint8_t * const *) ost->tmp_frame->data,&#xA;              ost->tmp_frame->linesize, 0, c->height, ost->frame->data,&#xA;              ost->frame->linesize);&#xA;  } else {&#xA;    fill_yuv_image(ost->frame, ost->next_pts, c->width, c->height);&#xA;  }&#xA;&#xA;  ost->frame->pts = ost->next_pts&#x2B;&#x2B;;&#xA;&#xA;  return ost->frame;&#xA;}&#xA;&#xA;/*&#xA; * encode one video frame and send it to the muxer&#xA; * return 1 when encoding is finished, 0 otherwise&#xA; */&#xA;static int write_video_frame(AVFormatContext *oc, OutputStream *ost)&#xA;{&#xA;  return write_frame(oc, ost->enc, ost->st, get_video_frame(ost), ost->tmp_pkt);&#xA;}&#xA;&#xA;static void close_stream(AVFormatContext *oc, OutputStream *ost)&#xA;{&#xA;  avcodec_free_context(&amp;ost->enc);&#xA;  av_frame_free(&amp;ost->frame);&#xA;  av_frame_free(&amp;ost->tmp_frame);&#xA;  av_packet_free(&amp;ost->tmp_pkt);&#xA;  sws_freeContext(ost->sws_ctx);&#xA;  swr_free(&amp;ost->swr_ctx);&#xA;}&#xA;&#xA;/**************************************************************/&#xA;/* media file output */&#xA;&#xA;int main(int argc, char **argv)&#xA;{&#xA;  OutputStream video_st = { 0 }, audio_st = { 0 };&#xA;  const AVOutputFormat *fmt;&#xA;  const char *filename;&#xA;  AVFormatContext *oc;&#xA;  const AVCodec *audio_codec, *video_codec;&#xA;  int ret;&#xA;  int have_video = 0, have_audio = 0;&#xA;  int encode_video = 0, encode_audio = 0;&#xA;  AVDictionary *opt = NULL;&#xA;  int i;&#xA;&#xA;  if (argc &lt; 2) {&#xA;    printf("usage: %s output_file\n"&#xA;           "API example program to output a media file with libavformat.\n"&#xA;           "This program generates a synthetic audio and video stream, encodes and\n"&#xA;           "muxes them into a file named output_file.\n"&#xA;           "The output format is automatically guessed according to the file extension.\n"&#xA;           "Raw images can also be output by using &#x27;%%d&#x27; in the filename.\n"&#xA;           "\n", argv[0]);&#xA;    return 1;&#xA;  }&#xA;&#xA;  filename = argv[1];&#xA;&#xA;  av_dict_set(&amp;opt, "movflags", "frag_keyframe&#x2B;separate_moof&#x2B;omit_tfhd_offset&#x2B;empty_moov", 0);&#xA;&#xA;  /* allocate the output media context */&#xA;  avformat_alloc_output_context2(&amp;oc, NULL, NULL, filename);&#xA;  if (!oc) {&#xA;    printf("Could not deduce output format from file extension: using MPEG.\n");&#xA;    avformat_alloc_output_context2(&amp;oc, NULL, "mpeg", filename);&#xA;  }&#xA;  if (!oc)&#xA;    return 1;&#xA;&#xA;  fmt = oc->oformat;&#xA;&#xA;  /* Add the audio and video streams using the default format codecs&#xA;   * and initialize the codecs. */&#xA;  if (fmt->video_codec != AV_CODEC_ID_NONE) {&#xA;    add_stream(&amp;video_st, oc, &amp;video_codec, fmt->video_codec);&#xA;    have_video = 1;&#xA;    encode_video = 1;&#xA;  }&#xA;&#xA;  /* Now that all the parameters are set, we can open the audio and&#xA;   * video codecs and allocate the necessary encode buffers. */&#xA;  if (have_video)&#xA;    open_video(oc, video_codec, &amp;video_st, opt);&#xA;&#xA;&#xA;  av_dump_format(oc, 0, filename, 1);&#xA;&#xA;  /* open the output file, if needed */&#xA;  if (!(fmt->flags &amp; AVFMT_NOFILE)) {&#xA;    ret = avio_open(&amp;oc->pb, filename, AVIO_FLAG_WRITE);&#xA;    if (ret &lt; 0) {&#xA;      fprintf(stderr, "Could not open &#x27;%s&#x27;\n", filename);&#xA;      return 1;&#xA;    }&#xA;  }&#xA;&#xA;  /* Write the stream header, if any. */&#xA;  ret = avformat_write_header(oc, &amp;opt);&#xA;  if (ret &lt; 0) {&#xA;    fprintf(stderr, "Error occurred when opening output file\n");&#xA;    return 1;&#xA;  }&#xA;&#xA;  while (encode_video || encode_audio) {&#xA;    /* select the stream to encode */&#xA;    if (encode_video &amp;&amp;&#xA;        (!encode_audio || av_compare_ts(video_st.next_pts, video_st.enc->time_base,&#xA;                                        audio_st.next_pts, audio_st.enc->time_base) &lt;= 0)) {&#xA;      encode_video = !write_video_frame(oc, &amp;video_st);&#xA;    }&#xA;  }&#xA;&#xA;  av_write_trailer(oc);&#xA;&#xA;  /* Close each codec. */&#xA;  if (have_video)&#xA;    close_stream(oc, &amp;video_st);&#xA;  if (have_audio)&#xA;    close_stream(oc, &amp;audio_st);&#xA;&#xA;  if (!(fmt->flags &amp; AVFMT_NOFILE))&#xA;    /* Close the output file. */&#xA;    avio_closep(&amp;oc->pb);&#xA;&#xA;  /* free the stream */&#xA;  avformat_free_context(oc);&#xA;&#xA;  return 0;&#xA;}&#xA;</cmath></cstring></cstdio></cstdlib>

    &#xA;

  • Trying to get the current FPS and Frametime value into Matplotlib title

    16 juin 2022, par TiSoBr

    I try to turn an exported CSV with benchmark logs into an animated graph. Works so far, but I can't get the Titles on top of both plots with their current FPS and frametime in ms values animated.

    &#xA;

    Thats the output I'm getting. Looks like he simply stores all values in there instead of updating them ?

    &#xA;

    Screengrab of cli output&#xA;Screengrab of the final output (inverted)

    &#xA;

    from __future__ import division&#xA;import sys, getopt&#xA;import time&#xA;import matplotlib&#xA;import numpy as np&#xA;import subprocess&#xA;import math&#xA;import re&#xA;import argparse&#xA;import os&#xA;import glob&#xA;&#xA;import matplotlib.animation as animation&#xA;import matplotlib.pyplot as plt&#xA;&#xA;&#xA;def check_pos(arg):&#xA;    ivalue = int(arg)&#xA;    if ivalue &lt;= 0:&#xA;        raise argparse.ArgumentTypeError("%s Not a valid positive integer value" % arg)&#xA;    return True&#xA;    &#xA;def moving_average(x, w):&#xA;    return np.convolve(x, np.ones(w), &#x27;valid&#x27;) / w&#xA;    &#xA;&#xA;parser = argparse.ArgumentParser(&#xA;    description = "Example Usage python frame_scan.py -i mangohud -c &#x27;#fff&#x27; -o mymov",&#xA;    formatter_class=argparse.ArgumentDefaultsHelpFormatter)&#xA;parser.add_argument("-i", "--input", help = "Input data set from mangohud", required = True, nargs=&#x27;&#x2B;&#x27;, type=argparse.FileType(&#x27;r&#x27;), default=sys.stdin)&#xA;parser.add_argument("-o", "--output", help = "Output file name", required = True, type=str, default = "")&#xA;parser.add_argument("-r", "--framerate", help = "Set the desired framerate", required = False, type=float, default = 60)&#xA;parser.add_argument("-c", "--colors", help = "Colors for the line graphs; must be in quotes", required = True, type=str, nargs=&#x27;&#x2B;&#x27;, default = 60)&#xA;parser.add_argument("--fpslength", help = "Configures how long the data will be shown on the FPS graph", required = False, type=float, default = 5)&#xA;parser.add_argument("--fpsthickness", help = "Changes the line width for the FPS graph", required = False, type=float, default = 3)&#xA;parser.add_argument("--frametimelength", help = "Configures how long the data will be shown on the frametime graph", required = False, type=float, default = 2.5)&#xA;parser.add_argument("--frametimethickness", help = "Changes the line width for the frametime graph", required = False, type=float, default = 1.5)&#xA;parser.add_argument("--graphcolor", help = "Changes all of the line colors on the graph; expects hex value", required = False, default = &#x27;#FFF&#x27;)&#xA;parser.add_argument("--graphthicknes", help = "Changes the line width of the graph", required = False, type=float, default = 1)&#xA;parser.add_argument("-ts","--textsize", help = "Changes the the size of numbers marking the ticks", required = False, type=float, default = 23)&#xA;parser.add_argument("-fsM","--fpsmax", help = "Changes the the size of numbers marking the ticks", required = False, type=float, default = 180)&#xA;parser.add_argument("-fsm","--fpsmin", help = "Changes the the size of numbers marking the ticks", required = False, type=float, default = 0)&#xA;parser.add_argument("-fss","--fpsstep", help = "Changes the the size of numbers marking the ticks", required = False, type=float, default = 30)&#xA;parser.add_argument("-ftM","--frametimemax", help = "Changes the the size of numbers marking the ticks", required = False, type=float, default = 50)&#xA;parser.add_argument("-ftm","--frametimemin", help = "Changes the the size of numbers marking the ticks", required = False, type=float, default = 0)&#xA;parser.add_argument("-fts","--frametimestep", help = "Changes the the size of numbers marking the ticks", required = False, type=float, default = 10)&#xA;&#xA;arg = parser.parse_args()&#xA;status = False&#xA;&#xA;&#xA;if arg.input:&#xA;    status = True&#xA;if arg.output:&#xA;    status = True&#xA;if arg.framerate:&#xA;    status = check_pos(arg.framerate)&#xA;if arg.fpslength:&#xA;    status = check_pos(arg.fpslength)&#xA;if arg.fpsthickness:&#xA;    status = check_pos(arg.fpsthickness)&#xA;if arg.frametimelength:&#xA;    status = check_pos(arg.frametimelength)&#xA;if arg.frametimethickness:&#xA;    status = check_pos(arg.frametimethickness)&#xA;if arg.colors:&#xA;    if len(arg.output) != len(arg.colors):&#xA;        for i in arg.colors:&#xA;            if re.match(r"^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$", i):&#xA;                status = True&#xA;            else:&#xA;                print(&#x27;{} : Isn\&#x27;t a valid hex value!&#x27;.format(i))&#xA;                status = False&#xA;    else:&#xA;        print(&#x27;You must have the same amount of colors as files in input!&#x27;)&#xA;        status = False&#xA;if arg.graphcolor:&#xA;    if re.match(r"^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$", arg.graphcolor):&#xA;        status = True&#xA;    else:&#xA;        print(&#x27;{} : Isn\&#x27;t a vaild hex value!&#x27;.format(arg.graphcolor))&#xA;        status = False&#xA;if arg.graphthicknes:&#xA;    status = check_pos(arg.graphthicknes)&#xA;if arg.textsize:&#xA;    status = check_pos(arg.textsize)&#xA;if not status:&#xA;    print("For a list of arguments try -h or --help") &#xA;    exit()&#xA;&#xA;&#xA;# Empty output folder&#xA;files = glob.glob(&#x27;/output/*&#x27;)&#xA;for f in files:&#xA;    os.remove(f)&#xA;&#xA;&#xA;# We need to know the longest recording out of all inputs so we know when to stop the video&#xA;longest_data = 0&#xA;&#xA;# Format the raw data into a list of tuples (fps, frame time in ms, time from start in micro seconds)&#xA;# The first three lines of our data are setup so we ignore them&#xA;data_formated = []&#xA;for li, i in enumerate(arg.input):&#xA;    t = 0&#xA;    sublist = []&#xA;    for line in i.readlines()[3:]:&#xA;        x = line[:-1].split(&#x27;,&#x27;)&#xA;        fps = float(x[0])&#xA;        frametime = int(x[1])/1000 # convert from microseconds to milliseconds&#xA;        elapsed = int(x[11])/1000 # convert from nanosecond to microseconds&#xA;        data = (fps, frametime, elapsed)&#xA;        sublist.append(data)&#xA;    # Compare last entry of each list with the &#xA;    if sublist[-1][2] >= longest_data:&#xA;        longest_data = sublist[-1][2]&#xA;    data_formated.append(sublist)&#xA;&#xA;&#xA;max_blocksize = max(arg.fpslength, arg.frametimelength) * arg.framerate&#xA;blockSize = arg.framerate * arg.fpslength&#xA;&#xA;&#xA;# Get step time in microseconds&#xA;step = (1/arg.framerate) * 1000000 # 1000000 is one second in microseconds&#xA;frame_size_fps = (arg.fpslength * arg.framerate) * step&#xA;frame_size_frametime = (arg.frametimelength * arg.framerate) * step&#xA;&#xA;&#xA;# Total frames will have to be updated for more then one source&#xA;total_frames = int(int(longest_data) / step)&#xA;&#xA;&#xA;if True: # Gonna be honest, this only exists so I can collapse this block of code&#xA;&#xA;    # Sets up our figures to be next to each other (horizontally) and with a ratio 3:1 to each other&#xA;    fig, (ax1, ax2) = plt.subplots(1, 2, gridspec_kw={&#x27;width_ratios&#x27;: [3, 1]})&#xA;&#xA;    # Size of whole output 1920x360 1080/3=360&#xA;    fig.set_size_inches(19.20, 3.6)&#xA;&#xA;    # Make the background transparent&#xA;    fig.patch.set_alpha(0)&#xA;&#xA;&#xA;    # Loop through all active axes; saves a lot of lines in ax1.do_thing(x) ax2.do_thing(x)&#xA;    for axes in fig.axes:&#xA;&#xA;        # Set all splines to the same color and width&#xA;        for loc, spine in axes.spines.items():&#xA;            axes.spines[loc].set_color(arg.graphcolor)&#xA;            axes.spines[loc].set_linewidth(arg.graphthicknes)&#xA;&#xA;        # Make sure we don&#x27;t render any data points as this will be our background&#xA;        axes.set_xlim(-(max_blocksize * step), 0)&#xA;        &#xA;&#xA;        # Make both plots transparent as well as the background&#xA;        axes.patch.set_alpha(.5)&#xA;        axes.patch.set_color(&#x27;#020202&#x27;)&#xA;&#xA;        # Change the Y axis info to be on the right side&#xA;        axes.yaxis.set_label_position("right")&#xA;        axes.yaxis.tick_right()&#xA;&#xA;        # Add the white lines across the graphs; the location of the lines are based off set_{}ticks&#xA;        axes.grid(alpha=.8, b=True, which=&#x27;both&#x27;, axis=&#x27;y&#x27;, color=arg.graphcolor, linewidth=arg.graphthicknes)&#xA;&#xA;        # Remove X axis info&#xA;        axes.set_xticks([])&#xA;&#xA;    # Add a another Y axis so ticks are on both sides&#xA;    tmp_ax1 = ax1.secondary_yaxis("left")&#xA;    tmp_ax2 = ax2.secondary_yaxis("left")&#xA;&#xA;    # Set both to the same values&#xA;    ax1.set_yticks(np.arange(arg.fpsmin, arg.fpsmax &#x2B; 1, step=arg.fpsstep))&#xA;    ax2.set_yticks(np.arange(arg.frametimemin, arg.frametimemax &#x2B; 1, step=arg.frametimestep))&#xA;    tmp_ax1.set_yticks(np.arange(arg.fpsmin , arg.fpsmax &#x2B; 1, step=arg.fpsstep))&#xA;    tmp_ax2.set_yticks(np.arange(arg.frametimemin, arg.frametimemax &#x2B; 1, step=arg.frametimestep))&#xA;&#xA;    # Change the "ticks" to be white and correct size also change font size&#xA;    ax1.tick_params(axis=&#x27;y&#x27;, color=arg.graphcolor ,width=arg.graphthicknes, length=16, labelsize=arg.textsize, labelcolor=arg.graphcolor)&#xA;    ax2.tick_params(axis=&#x27;y&#x27;, color=arg.graphcolor ,width=arg.graphthicknes, length=16, labelsize=arg.textsize, labelcolor=arg.graphcolor)&#xA;    tmp_ax1.tick_params(axis=&#x27;y&#x27;, color=arg.graphcolor ,width=arg.graphthicknes, length=8, labelsize=0) # Label size of 0 disables the fps/frame numbers&#xA;    tmp_ax2.tick_params(axis=&#x27;y&#x27;, color=arg.graphcolor ,width=arg.graphthicknes, length=8, labelsize=0)&#xA;&#xA;&#xA;    # Limits Y scale&#xA;    ax1.set_ylim(arg.fpsmin,arg.fpsmax &#x2B; 1)&#xA;    ax2.set_ylim(arg.frametimemin,arg.frametimemax &#x2B; 1)&#xA;&#xA;    # Add an empty plot&#xA;    line = ax1.plot([], lw=arg.fpsthickness)&#xA;    line2 = ax2.plot([], lw=arg.frametimethickness)&#xA;&#xA;    # Sets all the data for our benchmark&#xA;    for benchmarks, color in zip(data_formated, arg.colors):&#xA;        y = moving_average([x[0] for x in benchmarks], 25)&#xA;        y2 = [x[1] for x in benchmarks]&#xA;        x = [x[2] for x in benchmarks]&#xA;        line &#x2B;= ax1.plot(x[12:-12],y, c=color, lw=arg.fpsthickness)&#xA;        line2 &#x2B;= ax2.step(x,y2, c=color, lw=arg.fpsthickness)&#xA;    &#xA;    # Add titles with values&#xA;    ax1.set_title("Avg. frames per second: {}".format(y2), color=arg.graphcolor, fontsize=20, fontweight=&#x27;bold&#x27;, loc=&#x27;left&#x27;)&#xA;    ax2.set_title("Frametime in ms: {}".format(y2), color=arg.graphcolor, fontsize=20, fontweight=&#x27;bold&#x27;, loc=&#x27;left&#x27;)  &#xA;&#xA;    # Removes unwanted white space; also controls the space between the two graphs&#xA;    plt.tight_layout(pad=0, h_pad=0, w_pad=2.5)&#xA;    &#xA;    fig.canvas.draw()&#xA;&#xA;    # Cache the background&#xA;    axbackground = fig.canvas.copy_from_bbox(ax1.bbox)&#xA;    ax2background = fig.canvas.copy_from_bbox(ax2.bbox)&#xA;&#xA;&#xA;# Create a ffmpeg instance as a subprocess we will pipe the finished frame into ffmpeg&#xA;# encoded in Apple QuickTime (qtrle) for small(ish) file size and alpha support&#xA;# There are free and opensource types that will also do this but with much larger sizes&#xA;canvas_width, canvas_height = fig.canvas.get_width_height()&#xA;outf = &#x27;{}.mov&#x27;.format(arg.output)&#xA;cmdstring = (&#x27;ffmpeg&#x27;,&#xA;                &#x27;-stats&#x27;, &#x27;-hide_banner&#x27;, &#x27;-loglevel&#x27;, &#x27;error&#x27;, # Makes ffmpeg less annoying / to much console output&#xA;                &#x27;-y&#x27;, &#x27;-r&#x27;, &#x27;60&#x27;, # set the fps of the video&#xA;                &#x27;-s&#x27;, &#x27;%dx%d&#x27; % (canvas_width, canvas_height), # size of image string&#xA;                &#x27;-pix_fmt&#x27;, &#x27;argb&#x27;, # format cant be changed since this is what  `fig.canvas.tostring_argb()` outputs&#xA;                &#x27;-f&#x27;, &#x27;rawvideo&#x27;,  &#x27;-i&#x27;, &#x27;-&#x27;, # tell ffmpeg to expect raw video from the pipe&#xA;                &#x27;-vcodec&#x27;, &#x27;qtrle&#x27;, outf) # output encoding must support alpha channel&#xA;pipe = subprocess.Popen(cmdstring, stdin=subprocess.PIPE)&#xA;&#xA;def render_frame(frame : int):&#xA;&#xA;    # Set the bounds of the graph for each frame to render the correct data&#xA;    start = (frame * step) - frame_size_fps&#xA;    end = start &#x2B; frame_size_fps&#xA;    ax1.set_xlim(start,end)&#xA;     &#xA;     &#xA;    start = (frame * step) - frame_size_frametime&#xA;    end = start &#x2B; frame_size_frametime&#xA;    ax2.set_xlim(start,end)&#xA;    &#xA;&#xA;    # Restore background&#xA;    fig.canvas.restore_region(axbackground)&#xA;    fig.canvas.restore_region(ax2background)&#xA;&#xA;    # Redraw just the points will only draw points with in `axes.set_xlim`&#xA;    for i in line:&#xA;        ax1.draw_artist(i)&#xA;        &#xA;    for i in line2:&#xA;        ax2.draw_artist(i)&#xA;&#xA;    # Fill in the axes rectangle&#xA;    fig.canvas.blit(ax1.bbox)&#xA;    fig.canvas.blit(ax2.bbox)&#xA;    &#xA;    fig.canvas.flush_events()&#xA;&#xA;    # Converts the finished frame to ARGB&#xA;    string = fig.canvas.tostring_argb()&#xA;    return string&#xA;&#xA;&#xA;&#xA;&#xA;#import multiprocessing&#xA;#p = multiprocessing.Pool()&#xA;#for i, _ in enumerate(p.imap(render_frame, range(0, int(total_frames &#x2B; max_blocksize))), 20):&#xA;#    pipe.stdin.write(_)&#xA;#    sys.stderr.write(&#x27;\rdone {0:%}&#x27;.format(i/(total_frames &#x2B; max_blocksize)))&#xA;#p.close()&#xA;&#xA;#Signle Threaded not much slower then multi-threading&#xA;if __name__ == "__main__":&#xA;    for i , _ in enumerate(range(0, int(total_frames &#x2B; max_blocksize))):&#xA;        render_frame(_)&#xA;        pipe.stdin.write(render_frame(_))&#xA;        sys.stderr.write(&#x27;\rdone {0:%}&#x27;.format(i/(total_frames &#x2B; max_blocksize)))&#xA;

    &#xA;