Recherche avancée

Médias (91)

Autres articles (105)

  • Personnaliser les catégories

    21 juin 2013, par

    Formulaire de création d’une catégorie
    Pour ceux qui connaissent bien SPIP, une catégorie peut être assimilée à une rubrique.
    Dans le cas d’un document de type catégorie, les champs proposés par défaut sont : Texte
    On peut modifier ce formulaire dans la partie :
    Administration > Configuration des masques de formulaire.
    Dans le cas d’un document de type média, les champs non affichés par défaut sont : Descriptif rapide
    Par ailleurs, c’est dans cette partie configuration qu’on peut indiquer le (...)

  • Supporting all media types

    13 avril 2011, par

    Unlike most software and media-sharing platforms, MediaSPIP aims to manage as many different media types as possible. The following are just a few examples from an ever-expanding list of supported formats : images : png, gif, jpg, bmp and more audio : MP3, Ogg, Wav and more video : AVI, MP4, OGV, mpg, mov, wmv and more text, code and other data : OpenOffice, Microsoft Office (Word, PowerPoint, Excel), web (html, CSS), LaTeX, Google Earth and (...)

  • MediaSPIP Player : problèmes potentiels

    22 février 2011, par

    Le lecteur ne fonctionne pas sur Internet Explorer
    Sur Internet Explorer (8 et 7 au moins), le plugin utilise le lecteur Flash flowplayer pour lire vidéos et son. Si le lecteur ne semble pas fonctionner, cela peut venir de la configuration du mod_deflate d’Apache.
    Si dans la configuration de ce module Apache vous avez une ligne qui ressemble à la suivante, essayez de la supprimer ou de la commenter pour voir si le lecteur fonctionne correctement : /** * GeSHi (C) 2004 - 2007 Nigel McNie, (...)

Sur d’autres sites (13940)

  • ffmpeg/libx264 C API : frames dropped from end of short MP4

    19 juillet 2017, par Blake McConnell

    In my C++ application, I am taking a series of JPEG images, manipulating their data using FreeImage, and then encoding the bitmaps as H264 using the ffmpeg/libx264 C API. The output is an MP4 which shows the series of 22 images at 12fps. My code is adapted from the "muxing" example that comes with ffmpeg C source code.

    My problem : no matter how I tune the codec parameters, a certain number of frames at the end of the sequence which are passed to the encoder do not appear in the final output. I’ve set the AVCodecContext parameters like this :

    //set context params
    ctx->codec_id = AV_CODEC_ID_H264;
    ctx->bit_rate = 4000 * 1000;
    ctx->width = _width;
    ctx->height = _height;
    ost->st->time_base = AVRational{ 1, 12 };
    ctx->time_base = ost->st->time_base;
    ctx->gop_size = 1;
    ctx->pix_fmt = AV_PIX_FMT_YUV420P;

    I have found that the higher the gop_size the more frames are dropped from the end of the video. I can also see from the output that, with this gop size (where I’m essentially directing that all output frames be I frames) that only 9 frames are written.

    I’m not sure why this is occurring. I experimented with encoding duplicate frames and making a much longer video. This resulted in no frames being dropped. I know with the ffmpeg command line tool there is a concatenation command that accomplishes what I am trying to do, but I’m not sure how to accomplish the same goal using the C API.

    Here’s the output I’m getting from the console :

    [libx264 @ 026d81c0] using cpu capabilities : MMX2 SSE2Fast SSSE3
    SSE4.2 AVX FMA3 BMI2 AVX2 [libx264 @ 026d81c0] profile High, level
    3.1 [libx264 @ 026d81c0] 264 - core 152 r2851 ba24899 - H.264/MPEG-4 AVC codec - Cop yleft 2003-2017 - http://www.videolan.org/x264.html -
    options : cabac=1 ref=1 deb lock=1:0:0 analyse=0x3:0x113 me=hex subme=7
    psy=1 psy_rd=1.00:0.00 mixed_ref=0 m e_range=16 chroma_me=1 trellis=1
    8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chro ma_qp_offset=-2
    threads=12 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1
    interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0
    keyint=1 ke yint_min=1 scenecut=40 intra_refresh=0 rc=abr mbtree=0
    bitrate=4000 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4
    ip_ratio=1.40 aq=1:1.00 Output #0, mp4, to
    ’....\images\c411a991-46f6-400c-8bb0-77af3738559a.mp4’ :
    Stream #0:0 : Video : h264, yuv420p, 700x700, q=2-31, 4000 kb/s, 12 tbn

    [libx264 @ 026d81c0] frame I:9 Avg QP:17.83 size:111058 [libx264
    @ 026d81c0] mb I I16..4 : 1.9% 47.7% 50.5% [libx264 @ 026d81c0] final
    ratefactor : 19.14 [libx264 @ 026d81c0] 8x8 transform intra:47.7%
    [libx264 @ 026d81c0] coded y,uvDC,uvAC intra : 98.4% 96.9% 89.5%
    [libx264 @ 026d81c0] i16 v,h,dc,p : 64% 6% 2% 28% [libx264 @
    026d81c0] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu : 32% 15% 9% 5% 5% 6% 8%
    10% 10% [libx264 @ 026d81c0] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu : 28% 18%
    7% 6% 8% 8% 8% 9% 8% [libx264 @ 026d81c0] i8c dc,h,v,p : 43% 22%
    25% 10% [libx264 @ 026d81c0] kb/s:10661.53

    Code included below :

    MP4Writer.h

    #ifndef MPEG_WRITER
    #define MPEG_WRITER

    #include <iostream>
    #include <string>
    #include <vector>
    #include
    extern "C" {
       #include <libavformat></libavformat>avformat.h>
       #include <libswscale></libswscale>swscale.h>
       #include <libswresample></libswresample>swresample.h>
       #include <libswscale></libswscale>swscale.h>
    }

    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;

       float t, tincr, tincr2;

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

    class MP4Writer {
       public:
           MP4Writer();
           void Init();
           int16_t SetOutput( const std::string &amp; path );
           int16_t AddFrame( uint8_t * imgData );
           int16_t Write( std::vector<imgdata> &amp; imgData );
           int16_t Finalize();
           void SetHeight( const int height ) { _height = _width = height; } //assuming 1:1 aspect ratio

       private:
           int16_t AddStream( OutputStream * ost, AVFormatContext * formatCtx, AVCodec ** codec, enum AVCodecID codecId );
           int16_t OpenVideo( AVFormatContext * formatCtx, AVCodec *codec, OutputStream * ost, AVDictionary * optArg );
           static AVFrame * AllocPicture( enum AVPixelFormat pixFmt, int width, int height );
           static AVFrame * GetVideoFrame( uint8_t * imgData, OutputStream * ost, const int width, const int height );
           static int WriteFrame( AVFormatContext * formatCtx, const AVRational * timeBase, AVStream * stream, AVPacket * packet );

           int _width;
           int _height;
           OutputStream _ost;
           AVFormatContext * _formatCtx;
           AVDictionary * _dict;
    };

    #endif //MPEG_WRITER
    </imgdata></vector></string></iostream>

    MP4Writer.cpp

    #include
    #include <algorithm>

    MP4Writer::MP4Writer()
    {
       _width = 0;
       _height = 0;
    }

    void MP4Writer::Init()
    {
       av_register_all();
    }

    /**
    sets up output stream for the specified path.
    note that the output format is deduced automatically from the file extension passed
    @param path: output file path
    @returns: -1 = output could not be deduced, -2 = invalid codec, -3 = error opening output file,
              -4 = error writing header
    */
    int16_t MP4Writer::SetOutput( const std::string &amp; path )
    {
       int error;
       AVCodec * codec;
       AVOutputFormat * format;

       _ost = OutputStream{}; //TODO reset state in a more focused way?

       //allocate output media context
       avformat_alloc_output_context2( &amp;_formatCtx, NULL, NULL, path.c_str() );
       if ( !_formatCtx ) {
           std::cout &lt;&lt; "could not deduce output format from file extension.  aborting" &lt;&lt; std::endl;
           return -1;
       }
       //set format
       format = _formatCtx->oformat;
       if ( format->video_codec != AV_CODEC_ID_NONE ) {
           AddStream( &amp;_ost, _formatCtx, &amp;codec, format->video_codec );
       }
       else {
           std::cout &lt;&lt; "there is no video codec set.  aborting" &lt;&lt; std::endl;
           return -2;
       }

       OpenVideo( _formatCtx, codec, &amp;_ost, _dict );

       av_dump_format( _formatCtx, 0, path.c_str(), 1 );

       //open output file
       if ( !( format->flags &amp; AVFMT_NOFILE )) {
           error = avio_open( &amp;_formatCtx->pb, path.c_str(), AVIO_FLAG_WRITE );
           if ( error &lt; 0 ) {
               std::cout &lt;&lt; "there was an error opening output file " &lt;&lt; path &lt;&lt; ".  aborting" &lt;&lt; std::endl;
               return -3;
           }
       }

       //write header
       error = avformat_write_header( _formatCtx, &amp;_dict );
       if ( error &lt; 0 ) {
           std::cout &lt;&lt; "an error occurred writing header. aborting" &lt;&lt; std::endl;
           return -4;
       }

       return 0;
    }

    /**
    initialize the output stream
    @param ost: the output stream
    @param formatCtx: the context format
    @param codec: the output codec
    @param codec: the ffmpeg enumerated id of the codec
    @returns: -1 = encoder not found, -2 = stream could not be allocated, -3 = encoding context could not be allocated
    */
    int16_t MP4Writer::AddStream( OutputStream * ost, AVFormatContext * formatCtx, AVCodec ** codec, enum AVCodecID codecId )
    {
       AVCodecContext * ctx; //TODO not sure why this is here, could just set ost->enc directly
       int i;

       //detect the encoder
       *codec = avcodec_find_encoder( codecId );
       if ( (*codec) == NULL ) {
           std::cout &lt;&lt; "could not find encoder.  aborting" &lt;&lt; std::endl;
           return -1;
       }

       //allocate stream
       ost->st = avformat_new_stream( formatCtx, NULL );
       if ( ost->st == NULL ) {
           std::cout &lt;&lt; "could not allocate stream.  aborting" &lt;&lt; std::endl;
           return -2;
       }

       //allocate encoding context
       ost->st->id = formatCtx->nb_streams - 1;
       ctx = avcodec_alloc_context3( *codec );
       if ( ctx == NULL ) {
           std::cout &lt;&lt; "could not allocate encoding context.  aborting" &lt;&lt; std::endl;
           return -3;
       }

       ost->enc = ctx;

       //set context params
       ctx->codec_id = AV_CODEC_ID_H264;
       ctx->bit_rate = 4000 * 1000;
       ctx->width = _width;
       ctx->height = _height;
       ost->st->time_base = AVRational{ 1, 12 };
       ctx->time_base = ost->st->time_base;
       ctx->gop_size = 1;
       ctx->pix_fmt = AV_PIX_FMT_YUV420P;

       //if neccesary, set stream headers and formats separately
       if ( formatCtx->oformat->flags &amp; AVFMT_GLOBALHEADER ) {
           std::cout &lt;&lt; "setting stream and headers to be separate" &lt;&lt; std::endl;
           ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
       }

       return 0;
    }

    /**
    open the video for writing
    @param formatCtx: the format context
    @param codec: output codec
    @param ost: output stream
    @param optArg: dictionary
    @return: -1 = error opening codec, -2 = allocate new frame, -3 = copy stream params
    */
    int16_t MP4Writer::OpenVideo( AVFormatContext * formatCtx, AVCodec *codec, OutputStream * ost, AVDictionary * optArg )
    {
       int error;
       AVCodecContext * ctx = ost->enc;
       AVDictionary * dict = NULL;
       av_dict_copy( &amp;dict, optArg, 0 );

       //open codec
       error = avcodec_open2( ctx, codec, &amp;dict );
       av_dict_free( &amp;dict );
       if ( error &lt; 0 ) {
           std::cout &lt;&lt; "there was an error opening the codec.  aborting" &lt;&lt; std::endl;
           return -1;
       }

       //allocate new frame
       ost->frame = AllocPicture( ctx->pix_fmt, ctx->width, ctx->height );
       if ( ost->frame == NULL ) {
           std::cout &lt;&lt; "there was an error allocating a new frame.  aborting" &lt;&lt; std::endl;
           return -2;
       }

       //copy steam params
       error = avcodec_parameters_from_context( ost->st->codecpar, ctx );
       if ( error &lt; 0 ) {
           std::cout &lt;&lt; "could not copy stream parameters.  aborting" &lt;&lt; std::endl;
           return -3;
       }

       return 0;
    }

    /**
    allocate a new frame
    @param pixFmt: ffmpeg enumerated pixel format
    @param width: output width
    @param height: output height
    @returns: an inititalized frame
    */
    AVFrame * MP4Writer::AllocPicture( enum AVPixelFormat pixFmt, int width, int height )
    {
       AVFrame * picture;
       int error;

       //allocate the frame
       picture = av_frame_alloc();
       if ( picture == NULL ) {
           std::cout &lt;&lt; "there was an error allocating the picture" &lt;&lt; std::endl;
           return NULL;
       }

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

       //allocate the frame's data buffer
       error = av_frame_get_buffer( picture, 32 );
       if ( error &lt; 0 ) {
           std::cout &lt;&lt; "could not allocate frame data" &lt;&lt; std::endl;
           return NULL;
       }
       picture->pts = 0;
       return picture;
    }

    /**
    convert raw RGB buffer to YUV frame
    @return: frame that contains image data
    */
    AVFrame * MP4Writer::GetVideoFrame( uint8_t * imgData, OutputStream * ost, const int width, const int height )
    {
       int error;
       AVCodecContext * ctx = ost->enc;

       //prepare the frame
       error = av_frame_make_writable( ost->frame );
       if ( error &lt; 0 ) {
           std::cout &lt;&lt; "could not make frame writeable" &lt;&lt; std::endl;
           return NULL;
       }

       //TODO set this context one time per run, or even better, one time at init
       //convert RGB to YUV
       struct SwsContext* fooContext = sws_getContext( width, height, AV_PIX_FMT_BGR24,
           width, height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL );
       int inLinesize[1] = { 3 * width }; // RGB stride
       uint8_t * inData[1] = { imgData };
       int sliceHeight = sws_scale( fooContext, inData, inLinesize, 0, height, ost->frame->data, ost->frame->linesize );
       sws_freeContext( fooContext );

       ost->frame->pts = ost->next_pts++;
       //TODO does the frame need to be returned here as it is available at the class level?
       return ost->frame;
    }

    /**
    write frame to file
    @param formatCtx: the output format context
    @param timeBase: the framerate
    @param stream: output stream
    @param packet: data packet
    @returns: see return values for av_interleaved_write_frame
    */
    int MP4Writer::WriteFrame( AVFormatContext * formatCtx, const AVRational * timeBase, AVStream * stream, AVPacket * packet )
    {
       av_packet_rescale_ts( packet, *timeBase, stream->time_base );
       packet->stream_index = stream->index;

       //write compressed file to media file
       return av_interleaved_write_frame( formatCtx, packet );
    }

    int16_t MP4Writer::Write( std::vector<imgdata> &amp; imgData )
    {
       int16_t errorCount = 0;
       int16_t retVal = 0;
       bool countingUp = true;
       size_t i = 0;
       while ( true ) {
           //don't show first frame again when counting back down
           if ( !countingUp &amp;&amp; i == 0 ) {
               break;
           }
           uint8_t * pixels = imgData[i].GetBits( imgData[i].mp4Input );
           AddFrame( pixels );

           //handle inc/dec without repeating last frame
           if ( countingUp ) {
               if ( i == imgData.size() -1 ) {
                   countingUp = false;
                   i--;
               }
               else {
                   i++;
               }
           }
           else {
               i--;
           }
       }
       Finalize();
       return 0; //TODO return error code
    }

    /**
    add another frame to output video
    @param imgData: the raw image data
    @returns -1 = error encoding video frame, -2 = error writing frame
    */
    int16_t MP4Writer::AddFrame( uint8_t * imgData )
    {
       int error;
       AVCodecContext * ctx;
       AVFrame * frame;
       int gotPacket = 0;
       AVPacket pkt = { 0 };

       ctx = _ost.enc;
       av_init_packet( &amp;pkt );

       frame = GetVideoFrame( imgData, &amp;_ost, _width, _height );

       //encode the image
       error = avcodec_encode_video2( ctx, &amp;pkt, frame, &amp;gotPacket );
       if ( error &lt; 0 ) {
           std::cout &lt;&lt; "there was an error encoding the video frame" &lt;&lt; std::endl;
           return -1;
       }

       //write the frame.  NOTE: this doesn't kick in until the encoder has received a certain number of frames
       if ( gotPacket ) {
           error = WriteFrame( _formatCtx, &amp;ctx->time_base, _ost.st, &amp;pkt );
           if ( error &lt; 0 ) {
               std::cout &lt;&lt; "the video frame could not be written" &lt;&lt; std::endl;
               return -2;
           }
       }
       return 0;
    }

    /**
    finalize output video and cleanup
    */
    int16_t MP4Writer::Finalize()
    {
       av_write_trailer( _formatCtx );
       avcodec_free_context( &amp;_ost.enc );
       av_frame_free( &amp;_ost.frame);
       av_frame_free( &amp;_ost.tmp_frame );
       avio_closep( &amp;_formatCtx->pb );
       avformat_free_context( _formatCtx );
       sws_freeContext( _ost.sws_ctx );
       swr_free( &amp;_ost.swr_ctx);
       return 0;
    }
    </imgdata></algorithm>

    usage

    #include
    #include
    #include <vector>

    struct ImgData
    {
       unsigned int width;
       unsigned int height;
       std::string path;
       FIBITMAP * mp4Input;

       uint8_t * GetBits( FIBITMAP * bmp ) { return FreeImage_GetBits( bmp ); }
    };

    int main()
    {
        std::vector<imgdata> imgDataVec;
        //load images and push to imgDataVec
        MP4Writer mp4Writer;
        mp4Writer.SetHeight( 1200 ); //assumes 1:1 aspect ratio
        mp4Writer.Init();
        mp4Writer.SetOutput( "test.mp4" );
        mp4Writer.Write( imgDataVec );
    }
    </imgdata></vector>
  • ffmpeg/libx264 C API : frames dropped from end of short MP4

    19 juillet 2017, par Blake McConnell

    In my C++ application, I am taking a series of JPEG images, manipulating their data using FreeImage, and then encoding the bitmaps as H264 using the ffmpeg/libx264 C API. The output is an MP4 which shows the series of 22 images at 12fps. My code is adapted from the "muxing" example that comes with ffmpeg C source code.

    My problem : no matter how I tune the codec parameters, a certain number of frames at the end of the sequence which are passed to the encoder do not appear in the final output. I’ve set the AVCodecContext parameters like this :

    //set context params
    ctx->codec_id = AV_CODEC_ID_H264;
    ctx->bit_rate = 4000 * 1000;
    ctx->width = _width;
    ctx->height = _height;
    ost->st->time_base = AVRational{ 1, 12 };
    ctx->time_base = ost->st->time_base;
    ctx->gop_size = 1;
    ctx->pix_fmt = AV_PIX_FMT_YUV420P;

    I have found that the higher the gop_size the more frames are dropped from the end of the video. I can also see from the output that, with this gop size (where I’m essentially directing that all output frames be I frames) that only 9 frames are written.

    I’m not sure why this is occurring. I experimented with encoding duplicate frames and making a much longer video. This resulted in no frames being dropped. I know with the ffmpeg command line tool there is a concatenation command that accomplishes what I am trying to do, but I’m not sure how to accomplish the same goal using the C API.

    Here’s the output I’m getting from the console :

    [libx264 @ 026d81c0] using cpu capabilities : MMX2 SSE2Fast SSSE3
    SSE4.2 AVX FMA3 BMI2 AVX2 [libx264 @ 026d81c0] profile High, level
    3.1 [libx264 @ 026d81c0] 264 - core 152 r2851 ba24899 - H.264/MPEG-4 AVC codec - Cop yleft 2003-2017 - http://www.videolan.org/x264.html -
    options : cabac=1 ref=1 deb lock=1:0:0 analyse=0x3:0x113 me=hex subme=7
    psy=1 psy_rd=1.00:0.00 mixed_ref=0 m e_range=16 chroma_me=1 trellis=1
    8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chro ma_qp_offset=-2
    threads=12 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1
    interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0
    keyint=1 ke yint_min=1 scenecut=40 intra_refresh=0 rc=abr mbtree=0
    bitrate=4000 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4
    ip_ratio=1.40 aq=1:1.00 Output #0, mp4, to
    ’....\images\c411a991-46f6-400c-8bb0-77af3738559a.mp4’ :
    Stream #0:0 : Video : h264, yuv420p, 700x700, q=2-31, 4000 kb/s, 12 tbn

    [libx264 @ 026d81c0] frame I:9 Avg QP:17.83 size:111058 [libx264
    @ 026d81c0] mb I I16..4 : 1.9% 47.7% 50.5% [libx264 @ 026d81c0] final
    ratefactor : 19.14 [libx264 @ 026d81c0] 8x8 transform intra:47.7%
    [libx264 @ 026d81c0] coded y,uvDC,uvAC intra : 98.4% 96.9% 89.5%
    [libx264 @ 026d81c0] i16 v,h,dc,p : 64% 6% 2% 28% [libx264 @
    026d81c0] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu : 32% 15% 9% 5% 5% 6% 8%
    10% 10% [libx264 @ 026d81c0] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu : 28% 18%
    7% 6% 8% 8% 8% 9% 8% [libx264 @ 026d81c0] i8c dc,h,v,p : 43% 22%
    25% 10% [libx264 @ 026d81c0] kb/s:10661.53

    Code included below :

    MP4Writer.h

    #ifndef MPEG_WRITER
    #define MPEG_WRITER

    #include <iostream>
    #include <string>
    #include <vector>
    #include
    extern "C" {
       #include <libavformat></libavformat>avformat.h>
       #include <libswscale></libswscale>swscale.h>
       #include <libswresample></libswresample>swresample.h>
       #include <libswscale></libswscale>swscale.h>
    }

    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;

       float t, tincr, tincr2;

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

    class MP4Writer {
       public:
           MP4Writer();
           void Init();
           int16_t SetOutput( const std::string &amp; path );
           int16_t AddFrame( uint8_t * imgData );
           int16_t Write( std::vector<imgdata> &amp; imgData );
           int16_t Finalize();
           void SetHeight( const int height ) { _height = _width = height; } //assuming 1:1 aspect ratio

       private:
           int16_t AddStream( OutputStream * ost, AVFormatContext * formatCtx, AVCodec ** codec, enum AVCodecID codecId );
           int16_t OpenVideo( AVFormatContext * formatCtx, AVCodec *codec, OutputStream * ost, AVDictionary * optArg );
           static AVFrame * AllocPicture( enum AVPixelFormat pixFmt, int width, int height );
           static AVFrame * GetVideoFrame( uint8_t * imgData, OutputStream * ost, const int width, const int height );
           static int WriteFrame( AVFormatContext * formatCtx, const AVRational * timeBase, AVStream * stream, AVPacket * packet );

           int _width;
           int _height;
           OutputStream _ost;
           AVFormatContext * _formatCtx;
           AVDictionary * _dict;
    };

    #endif //MPEG_WRITER
    </imgdata></vector></string></iostream>

    MP4Writer.cpp

    #include
    #include <algorithm>

    MP4Writer::MP4Writer()
    {
       _width = 0;
       _height = 0;
    }

    void MP4Writer::Init()
    {
       av_register_all();
    }

    /**
    sets up output stream for the specified path.
    note that the output format is deduced automatically from the file extension passed
    @param path: output file path
    @returns: -1 = output could not be deduced, -2 = invalid codec, -3 = error opening output file,
              -4 = error writing header
    */
    int16_t MP4Writer::SetOutput( const std::string &amp; path )
    {
       int error;
       AVCodec * codec;
       AVOutputFormat * format;

       _ost = OutputStream{}; //TODO reset state in a more focused way?

       //allocate output media context
       avformat_alloc_output_context2( &amp;_formatCtx, NULL, NULL, path.c_str() );
       if ( !_formatCtx ) {
           std::cout &lt;&lt; "could not deduce output format from file extension.  aborting" &lt;&lt; std::endl;
           return -1;
       }
       //set format
       format = _formatCtx->oformat;
       if ( format->video_codec != AV_CODEC_ID_NONE ) {
           AddStream( &amp;_ost, _formatCtx, &amp;codec, format->video_codec );
       }
       else {
           std::cout &lt;&lt; "there is no video codec set.  aborting" &lt;&lt; std::endl;
           return -2;
       }

       OpenVideo( _formatCtx, codec, &amp;_ost, _dict );

       av_dump_format( _formatCtx, 0, path.c_str(), 1 );

       //open output file
       if ( !( format->flags &amp; AVFMT_NOFILE )) {
           error = avio_open( &amp;_formatCtx->pb, path.c_str(), AVIO_FLAG_WRITE );
           if ( error &lt; 0 ) {
               std::cout &lt;&lt; "there was an error opening output file " &lt;&lt; path &lt;&lt; ".  aborting" &lt;&lt; std::endl;
               return -3;
           }
       }

       //write header
       error = avformat_write_header( _formatCtx, &amp;_dict );
       if ( error &lt; 0 ) {
           std::cout &lt;&lt; "an error occurred writing header. aborting" &lt;&lt; std::endl;
           return -4;
       }

       return 0;
    }

    /**
    initialize the output stream
    @param ost: the output stream
    @param formatCtx: the context format
    @param codec: the output codec
    @param codec: the ffmpeg enumerated id of the codec
    @returns: -1 = encoder not found, -2 = stream could not be allocated, -3 = encoding context could not be allocated
    */
    int16_t MP4Writer::AddStream( OutputStream * ost, AVFormatContext * formatCtx, AVCodec ** codec, enum AVCodecID codecId )
    {
       AVCodecContext * ctx; //TODO not sure why this is here, could just set ost->enc directly
       int i;

       //detect the encoder
       *codec = avcodec_find_encoder( codecId );
       if ( (*codec) == NULL ) {
           std::cout &lt;&lt; "could not find encoder.  aborting" &lt;&lt; std::endl;
           return -1;
       }

       //allocate stream
       ost->st = avformat_new_stream( formatCtx, NULL );
       if ( ost->st == NULL ) {
           std::cout &lt;&lt; "could not allocate stream.  aborting" &lt;&lt; std::endl;
           return -2;
       }

       //allocate encoding context
       ost->st->id = formatCtx->nb_streams - 1;
       ctx = avcodec_alloc_context3( *codec );
       if ( ctx == NULL ) {
           std::cout &lt;&lt; "could not allocate encoding context.  aborting" &lt;&lt; std::endl;
           return -3;
       }

       ost->enc = ctx;

       //set context params
       ctx->codec_id = AV_CODEC_ID_H264;
       ctx->bit_rate = 4000 * 1000;
       ctx->width = _width;
       ctx->height = _height;
       ost->st->time_base = AVRational{ 1, 12 };
       ctx->time_base = ost->st->time_base;
       ctx->gop_size = 1;
       ctx->pix_fmt = AV_PIX_FMT_YUV420P;

       //if neccesary, set stream headers and formats separately
       if ( formatCtx->oformat->flags &amp; AVFMT_GLOBALHEADER ) {
           std::cout &lt;&lt; "setting stream and headers to be separate" &lt;&lt; std::endl;
           ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
       }

       return 0;
    }

    /**
    open the video for writing
    @param formatCtx: the format context
    @param codec: output codec
    @param ost: output stream
    @param optArg: dictionary
    @return: -1 = error opening codec, -2 = allocate new frame, -3 = copy stream params
    */
    int16_t MP4Writer::OpenVideo( AVFormatContext * formatCtx, AVCodec *codec, OutputStream * ost, AVDictionary * optArg )
    {
       int error;
       AVCodecContext * ctx = ost->enc;
       AVDictionary * dict = NULL;
       av_dict_copy( &amp;dict, optArg, 0 );

       //open codec
       error = avcodec_open2( ctx, codec, &amp;dict );
       av_dict_free( &amp;dict );
       if ( error &lt; 0 ) {
           std::cout &lt;&lt; "there was an error opening the codec.  aborting" &lt;&lt; std::endl;
           return -1;
       }

       //allocate new frame
       ost->frame = AllocPicture( ctx->pix_fmt, ctx->width, ctx->height );
       if ( ost->frame == NULL ) {
           std::cout &lt;&lt; "there was an error allocating a new frame.  aborting" &lt;&lt; std::endl;
           return -2;
       }

       //copy steam params
       error = avcodec_parameters_from_context( ost->st->codecpar, ctx );
       if ( error &lt; 0 ) {
           std::cout &lt;&lt; "could not copy stream parameters.  aborting" &lt;&lt; std::endl;
           return -3;
       }

       return 0;
    }

    /**
    allocate a new frame
    @param pixFmt: ffmpeg enumerated pixel format
    @param width: output width
    @param height: output height
    @returns: an inititalized frame
    */
    AVFrame * MP4Writer::AllocPicture( enum AVPixelFormat pixFmt, int width, int height )
    {
       AVFrame * picture;
       int error;

       //allocate the frame
       picture = av_frame_alloc();
       if ( picture == NULL ) {
           std::cout &lt;&lt; "there was an error allocating the picture" &lt;&lt; std::endl;
           return NULL;
       }

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

       //allocate the frame's data buffer
       error = av_frame_get_buffer( picture, 32 );
       if ( error &lt; 0 ) {
           std::cout &lt;&lt; "could not allocate frame data" &lt;&lt; std::endl;
           return NULL;
       }
       picture->pts = 0;
       return picture;
    }

    /**
    convert raw RGB buffer to YUV frame
    @return: frame that contains image data
    */
    AVFrame * MP4Writer::GetVideoFrame( uint8_t * imgData, OutputStream * ost, const int width, const int height )
    {
       int error;
       AVCodecContext * ctx = ost->enc;

       //prepare the frame
       error = av_frame_make_writable( ost->frame );
       if ( error &lt; 0 ) {
           std::cout &lt;&lt; "could not make frame writeable" &lt;&lt; std::endl;
           return NULL;
       }

       //TODO set this context one time per run, or even better, one time at init
       //convert RGB to YUV
       struct SwsContext* fooContext = sws_getContext( width, height, AV_PIX_FMT_BGR24,
           width, height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL );
       int inLinesize[1] = { 3 * width }; // RGB stride
       uint8_t * inData[1] = { imgData };
       int sliceHeight = sws_scale( fooContext, inData, inLinesize, 0, height, ost->frame->data, ost->frame->linesize );
       sws_freeContext( fooContext );

       ost->frame->pts = ost->next_pts++;
       //TODO does the frame need to be returned here as it is available at the class level?
       return ost->frame;
    }

    /**
    write frame to file
    @param formatCtx: the output format context
    @param timeBase: the framerate
    @param stream: output stream
    @param packet: data packet
    @returns: see return values for av_interleaved_write_frame
    */
    int MP4Writer::WriteFrame( AVFormatContext * formatCtx, const AVRational * timeBase, AVStream * stream, AVPacket * packet )
    {
       av_packet_rescale_ts( packet, *timeBase, stream->time_base );
       packet->stream_index = stream->index;

       //write compressed file to media file
       return av_interleaved_write_frame( formatCtx, packet );
    }

    int16_t MP4Writer::Write( std::vector<imgdata> &amp; imgData )
    {
       int16_t errorCount = 0;
       int16_t retVal = 0;
       bool countingUp = true;
       size_t i = 0;
       while ( true ) {
           //don't show first frame again when counting back down
           if ( !countingUp &amp;&amp; i == 0 ) {
               break;
           }
           uint8_t * pixels = imgData[i].GetBits( imgData[i].mp4Input );
           AddFrame( pixels );

           //handle inc/dec without repeating last frame
           if ( countingUp ) {
               if ( i == imgData.size() -1 ) {
                   countingUp = false;
                   i--;
               }
               else {
                   i++;
               }
           }
           else {
               i--;
           }
       }
       Finalize();
       return 0; //TODO return error code
    }

    /**
    add another frame to output video
    @param imgData: the raw image data
    @returns -1 = error encoding video frame, -2 = error writing frame
    */
    int16_t MP4Writer::AddFrame( uint8_t * imgData )
    {
       int error;
       AVCodecContext * ctx;
       AVFrame * frame;
       int gotPacket = 0;
       AVPacket pkt = { 0 };

       ctx = _ost.enc;
       av_init_packet( &amp;pkt );

       frame = GetVideoFrame( imgData, &amp;_ost, _width, _height );

       //encode the image
       error = avcodec_encode_video2( ctx, &amp;pkt, frame, &amp;gotPacket );
       if ( error &lt; 0 ) {
           std::cout &lt;&lt; "there was an error encoding the video frame" &lt;&lt; std::endl;
           return -1;
       }

       //write the frame.  NOTE: this doesn't kick in until the encoder has received a certain number of frames
       if ( gotPacket ) {
           error = WriteFrame( _formatCtx, &amp;ctx->time_base, _ost.st, &amp;pkt );
           if ( error &lt; 0 ) {
               std::cout &lt;&lt; "the video frame could not be written" &lt;&lt; std::endl;
               return -2;
           }
       }
       return 0;
    }

    /**
    finalize output video and cleanup
    */
    int16_t MP4Writer::Finalize()
    {
       av_write_trailer( _formatCtx );
       avcodec_free_context( &amp;_ost.enc );
       av_frame_free( &amp;_ost.frame);
       av_frame_free( &amp;_ost.tmp_frame );
       avio_closep( &amp;_formatCtx->pb );
       avformat_free_context( _formatCtx );
       sws_freeContext( _ost.sws_ctx );
       swr_free( &amp;_ost.swr_ctx);
       return 0;
    }
    </imgdata></algorithm>

    usage

    #include
    #include
    #include <vector>

    struct ImgData
    {
       unsigned int width;
       unsigned int height;
       std::string path;
       FIBITMAP * mp4Input;

       uint8_t * GetBits( FIBITMAP * bmp ) { return FreeImage_GetBits( bmp ); }
    };

    int main()
    {
        std::vector<imgdata> imgDataVec;
        //load images and push to imgDataVec
        MP4Writer mp4Writer;
        mp4Writer.SetHeight( 1200 ); //assumes 1:1 aspect ratio
        mp4Writer.Init();
        mp4Writer.SetOutput( "test.mp4" );
        mp4Writer.Write( imgDataVec );
    }
    </imgdata></vector>
  • Video rotating to left by 90 degree when converted using ffmpeg

    15 juillet 2017, par Herdesh Verma

    I developed a below code :

    extern "C"
    {
    #include <libavutil></libavutil>imgutils.h>
    #include <libavutil></libavutil>opt.h>
    #include <libavcodec></libavcodec>avcodec.h>
    #include <libavutil></libavutil>mathematics.h>
    #include <libavutil></libavutil>samplefmt.h>
    #include <libavutil></libavutil>timestamp.h>
    #include <libavformat></libavformat>avformat.h>
    #include <libavfilter></libavfilter>avfiltergraph.h>
    #include <libswscale></libswscale>swscale.h>
    }
    #include
    static AVFormatContext *fmt_ctx = NULL;

    static int frame_index = 0;

    static int j = 0, nbytes=0;
    uint8_t *video_outbuf = NULL;
    static AVPacket *pAVPacket=NULL;
    static int value=0;
    static AVFrame *pAVFrame=NULL;
    static AVFrame *outFrame=NULL;
    static AVStream *video_st=NULL;
    static AVFormatContext *outAVFormatContext=NULL;
    static AVCodec *outAVCodec=NULL;
    static AVOutputFormat *output_format=NULL;
    static AVCodecContext *video_dec_ctx = NULL, *audio_dec_ctx;
    static AVCodecContext *outAVCodecContext=NULL;
    static int width, height;
    static enum AVPixelFormat pix_fmt;
    static AVStream *video_stream = NULL, *audio_stream = NULL;
    static const char *src_filename = NULL;
    static const char *video_dst_filename = NULL;
    static const char *audio_dst_filename = NULL;
    static FILE *video_dst_file = NULL;
    static FILE *audio_dst_file = NULL;
    static uint8_t *video_dst_data[4] = {NULL};
    static int      video_dst_linesize[4];
    static int video_dst_bufsize;
    static int video_stream_idx = -1, audio_stream_idx = -1;
    static AVPacket *pkt=NULL;
    static AVPacket *pkt1=NULL;
    static AVFrame *frame = NULL;
    //static AVPacket pkt;
    static int video_frame_count = 0;
    static int audio_frame_count = 0;
    static int refcount = 0;
    AVCodec *codec;
    static struct SwsContext *sws_ctx;
    AVCodecContext *c= NULL;
    int i, out_size, size, x, y, outbuf_size;
    AVFrame *picture;
    uint8_t *outbuf, *picture_buf;
    int video_outbuf_size;
    int w, h;
    AVPixelFormat pixFmt;
    uint8_t *data[4];
    int linesize[4];

    static int open_codec_context(int *stream_idx,
                             AVCodecContext **dec_ctx, AVFormatContext
    *fmt_ctx, enum AVMediaType type)
    {
    int ret, stream_index;
    AVStream *st;
    AVCodec *dec = NULL;
    AVDictionary *opts = NULL;
    ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
    if (ret &lt; 0) {
       printf("Could not find %s stream in input file '%s'\n",
               av_get_media_type_string(type), src_filename);
       return ret;
    } else {
       stream_index = ret;
       st = fmt_ctx->streams[stream_index];
       /* find decoder for the stream */
       dec = avcodec_find_decoder(st->codecpar->codec_id);
       if (!dec) {
           printf("Failed to find %s codec\n",
                   av_get_media_type_string(type));
           return AVERROR(EINVAL);
       }
       /* Allocate a codec context for the decoder */
       *dec_ctx = avcodec_alloc_context3(dec);
       if (!*dec_ctx) {
           printf("Failed to allocate the %s codec context\n",
                   av_get_media_type_string(type));
           return AVERROR(ENOMEM);
       }
       /* Copy codec parameters from input stream to output codec context */
       if ((ret = avcodec_parameters_to_context(*dec_ctx, st->codecpar)) &lt; 0) {
           printf("Failed to copy %s codec parameters to decoder context\n",
                   av_get_media_type_string(type));
           return ret;
       }
       /* Init the decoders, with or without reference counting */
       av_dict_set(&amp;opts, "refcounted_frames", refcount ? "1" : "0", 0);
       if ((ret = avcodec_open2(*dec_ctx, dec, &amp;opts)) &lt; 0) {
           printf("Failed to open %s codec\n",
                   av_get_media_type_string(type));
           return ret;
       }
       *stream_idx = stream_index;
    }
    return 0;
    }



    int main (int argc, char **argv)
    {
    int ret = 0, got_frame;
    src_filename = argv[1];
    video_dst_filename = argv[2];
    audio_dst_filename = argv[3];
    av_register_all();
    avcodec_register_all();
    printf("Registered all\n");

    /* open input file, and allocate format context */
    if (avformat_open_input(&amp;fmt_ctx, src_filename, NULL, NULL) &lt; 0) {
       printf("Could not open source file %s\n", src_filename);
       exit(1);
    }

    /* retrieve stream information */
    if (avformat_find_stream_info(fmt_ctx, NULL) &lt; 0) {
       printf("Could not find stream information\n");
       exit(1);
    }

    if (open_codec_context(&amp;video_stream_idx, &amp;video_dec_ctx, fmt_ctx,
    AVMEDIA_TYPE_VIDEO) >= 0) {
       video_stream = fmt_ctx->streams[video_stream_idx];
       avformat_alloc_output_context2(&amp;outAVFormatContext, NULL, NULL,
    video_dst_filename);
       if (!outAVFormatContext)
       {
               printf("\n\nError : avformat_alloc_output_context2()");
               return -1;
       }
    }

    if (open_codec_context(&amp;audio_stream_idx, &amp;audio_dec_ctx, fmt_ctx,
    AVMEDIA_TYPE_AUDIO) >= 0) {
       audio_stream = fmt_ctx->streams[audio_stream_idx];
       audio_dst_file = fopen(audio_dst_filename, "wb");
       if (!audio_dst_file) {
           printf("Could not open destination file %s\n", audio_dst_filename);
           ret = 1;
           goto end;
       }
    }
    /* dump input information to stderr */
    av_dump_format(fmt_ctx, 0, src_filename, 0);

    if (!audio_stream &amp;&amp; !video_stream) {
       printf("Could not find audio or video stream in the input, aborting\n");
       ret = 1;
       goto end;
    }

       output_format = av_guess_format(NULL, video_dst_filename, NULL);
       if( !output_format )
       {
        printf("\n\nError : av_guess_format()");
        return -1;
       }

       video_st = avformat_new_stream(outAVFormatContext ,NULL);
       if( !video_st )
       {
               printf("\n\nError : avformat_new_stream()");
         return -1;
       }

       outAVCodecContext = avcodec_alloc_context3(outAVCodec);
       if( !outAVCodecContext )
       {
         printf("\n\nError : avcodec_alloc_context3()");
         return -1;
       }


       outAVCodecContext = video_st->codec;
       outAVCodecContext->codec_id = AV_CODEC_ID_MPEG4;// AV_CODEC_ID_MPEG4; //
    AV_CODEC_ID_H264 // AV_CODEC_ID_MPEG1VIDEO
       outAVCodecContext->codec_type = AVMEDIA_TYPE_VIDEO;
       outAVCodecContext->pix_fmt  = AV_PIX_FMT_YUV420P;
       outAVCodecContext->bit_rate = 400000; // 2500000
       outAVCodecContext->width = 1920;
       //outAVCodecContext->width = 500;
       outAVCodecContext->height = 1080;
       //outAVCodecContext->height = 500;
       outAVCodecContext->gop_size = 3;
       outAVCodecContext->max_b_frames = 2;
       outAVCodecContext->time_base.num = 1;
       outAVCodecContext->time_base.den = 30; // 15fps

       if (outAVCodecContext->codec_id == AV_CODEC_ID_H264)
       {
        av_opt_set(outAVCodecContext->priv_data, "preset", "slow", 0);
       }

       outAVCodec = avcodec_find_encoder(AV_CODEC_ID_MPEG4);
       if( !outAVCodec )
       {
        printf("\n\nError : avcodec_find_encoder()");
        return -1;
       }

       /* Some container formats (like MP4) require global headers to be
    present
          Mark the encoder so that it behaves accordingly. */

       if ( outAVFormatContext->oformat->flags &amp; AVFMT_GLOBALHEADER)
       {
               outAVCodecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
       }

       value = avcodec_open2(outAVCodecContext, outAVCodec, NULL);
       if( value &lt; 0)
       {
               printf("\n\nError : avcodec_open2()");
               return -1;
       }

    /* create empty video file */
       if ( !(outAVFormatContext->flags &amp; AVFMT_NOFILE) )
       {
        if( avio_open2(&amp;outAVFormatContext->pb , video_dst_filename,
    AVIO_FLAG_WRITE ,NULL, NULL) &lt; 0 )
        {
         printf("\n\nError : avio_open2()");
        }
       }

       if(!outAVFormatContext->nb_streams)
       {
               printf("\n\nError : Output file dose not contain any stream");
         return -1;
       }

       /* imp: mp4 container or some advanced container file required header
    information*/
       value = avformat_write_header(outAVFormatContext , NULL);
       if(value &lt; 0)
       {
               printf("\n\nError : avformat_write_header()");
               return -1;
       }

       printf("\n\nOutput file information :\n\n");
       av_dump_format(outAVFormatContext , 0 ,video_dst_filename ,1);


       int flag;
       int frameFinished;


       value = 0;

       pAVPacket = (AVPacket *)av_malloc(sizeof(AVPacket));
       av_init_packet(pAVPacket);

       pAVFrame = av_frame_alloc();
       if( !pAVFrame )
       {
        printf("\n\nError : av_frame_alloc()");
        return -1;
       }

       outFrame = av_frame_alloc();//Allocate an AVFrame and set its fields to
    default values.
       if( !outFrame )
       {
        printf("\n\nError : av_frame_alloc()");
        return -1;
       }

       nbytes = av_image_get_buffer_size(outAVCodecContext-
    >pix_fmt,outAVCodecContext->width,outAVCodecContext->height,32);
       video_outbuf = (uint8_t*)av_malloc(nbytes);
       if( video_outbuf == NULL )
       {
       printf("\n\nError : av_malloc()");
       }


       value = av_image_fill_arrays( outFrame->data, outFrame->linesize,
    video_outbuf , AV_PIX_FMT_YUV420P, outAVCodecContext-
    >width,outAVCodecContext->height,1 ); // returns : the size in bytes
    required for src
       if(value &lt; 0)
       {
       printf("\n\nError : av_image_fill_arrays()");
       }

       SwsContext* swsCtx_ ;

       // Allocate and return swsContext.
       // a pointer to an allocated context, or NULL in case of error
       // Deprecated : Use sws_getCachedContext() instead.
       swsCtx_ = sws_getContext(video_dec_ctx->width,
                               video_dec_ctx->height,
                               video_dec_ctx->pix_fmt,
                               video_dec_ctx->width,
                               video_dec_ctx->height,
                               video_dec_ctx->pix_fmt,
                               SWS_BICUBIC, NULL, NULL, NULL);


       AVPacket outPacket;

       int got_picture;

       while( av_read_frame( fmt_ctx , pAVPacket ) >= 0 )
       {
               if(pAVPacket->stream_index == video_stream_idx)
               {
                       value = avcodec_decode_video2(video_dec_ctx , pAVFrame ,
     &amp;frameFinished , pAVPacket );
                       if( value &lt; 0)
                       {
                               printf("Error : avcodec_decode_video2()");
                       }

                       if(frameFinished)// Frame successfully decoded :)
                       {
                               sws_scale(swsCtx_, pAVFrame->data, pAVFrame-
    >linesize,0, video_dec_ctx->height, outFrame->data,outFrame->linesize);
    //                              sws_scale(swsCtx_, pAVFrame->data, pAVFrame-
    >linesize,0, video_dec_ctx->height, outFrame->data,outFrame->linesize);
                               av_init_packet(&amp;outPacket);
                               outPacket.data = NULL;    // packet data will be
    allocated by the encoder
                               outPacket.size = 0;

                               avcodec_encode_video2(outAVCodecContext ,
    &amp;outPacket ,outFrame , &amp;got_picture);

                               if(got_picture)
                               {
                                       if(outPacket.pts != AV_NOPTS_VALUE)
                                               outPacket.pts =
    av_rescale_q(outPacket.pts, video_st->codec->time_base, video_st-
    >time_base);
                                       if(outPacket.dts != AV_NOPTS_VALUE)
                                               outPacket.dts =
    av_rescale_q(outPacket.dts, video_st->codec->time_base, video_st-
    >time_base);

                                       printf("Write frame %3d (size= %2d)\n",
    j++, outPacket.size/1000);
                                       if(av_write_frame(outAVFormatContext ,
    &amp;outPacket) != 0)
                                       {
                                               printf("\n\nError :
    av_write_frame()");
                                       }

                               av_packet_unref(&amp;outPacket);
                               } // got_picture

                       av_packet_unref(&amp;outPacket);
                       } // frameFinished

               }
       }// End of while-loop

       value = av_write_trailer(outAVFormatContext);
       if( value &lt; 0)
       {
               printf("\n\nError : av_write_trailer()");
       }


       //THIS WAS ADDED LATER
       av_free(video_outbuf);

    end:
       avcodec_free_context(&amp;video_dec_ctx);
       avcodec_free_context(&amp;audio_dec_ctx);
       avformat_close_input(&amp;fmt_ctx);
       if (video_dst_file)
           fclose(video_dst_file);
      if (audio_dst_file)
          fclose(audio_dst_file);
      //av_frame_free(&amp;frame);
      av_free(video_dst_data[0]);
      return ret &lt; 0;
    }

    Problem with above code is that it rotates a video to left by 90 degree.

    Snapshot of video given as input to above program

    Snapshot of output video. It is rotated by 90 degree to left.

    I compiled program using below command :

    g++ -D__STDC_CONSTANT_MACROS -Wall -g ScreenRecorder.cpp -I/home/harry/Documents/compressor/ffmpeg-3.3/ -I/root/android-ndk-r14b/platforms/android-21/arch-x86_64/usr/include/ -c -o ScreenRecorder.o -w

    And linked it using below command :

    g++ -Wall -g ScreenRecorder.o -I/home/harry/Documents/compressor/ffmpeg-3.3/ -I/root/android-ndk-r14b/platforms/android-21/arch-x86_64/usr/include/ -L/usr/lib64 -L/lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.7/ -L/home/harry/Documents/compressor/ffmpeg-3.3/ffmpeg-build -L/root/android-ndk-r14b/platforms/android-21/arch-x86_64/usr/lib64 -o ScreenRecorder.exe -lavformat -lavcodec -lavutil -lavdevice -lavfilter -lswscale -lx264 -lswresample -lm -lpthread -ldl -lstdc++ -lc -lrt

    Program is being run using below command :

    ./ScreenRecorder.exe vertical.MOV videoH.mp4 audioH.mp3

    Note :
    - Source video is taken from iphone and is of .mov format.
    - Output video is being stored in .mp4 file.

    Can anyone please tell me why it is rotating video by 90 degree ?

    One thing i noticed in dump is shown below :

     Duration: 00:00:06.04, start: 0.000000, bitrate: 17087 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1080, 17014 kb/s, 29.98 fps, 29.97 tbr, 600 tbn, 1200 tbc (default)
    Metadata:
     rotate          : 90
     creation_time   : 2017-07-09T10:56:42.000000Z
     handler_name    : Core Media Data Handler
     encoder         : H.264
    Side data:
     displaymatrix: rotation of -90.00 degrees

    it says displaymatrix: rotation of -90.00 degrees. Is it responsible for rotating video by 90 degree ?