Skip to content

Instantly share code, notes, and snippets.

/fileout.cpp Secret

Created August 23, 2016 01:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/de262eba06458b7dbf6b601d16ac7316 to your computer and use it in GitHub Desktop.
Save anonymous/de262eba06458b7dbf6b601d16ac7316 to your computer and use it in GitHub Desktop.
FFmpeg file out
#include <iostream>
#include <string>
#include <queue>
#include <functional>
#include <cstdint>
extern "C"
{
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libavcodec/avcodec.h>
};
/**
* Put a description of the AVERROR code errnum in errbuf.
* In case of failure the global variable errno is set to indicate the
* error. Even in case of failure av_strerror() will print a generic
* error message indicating the errnum provided to errbuf.
*
* @param errnum error code to describe
* @param errbuf buffer to which description is written
* @param errbuf_size the size in bytes of errbuf
* @return 0 on success, a negative value if a description for errnum
* cannot be found
*
int av_strerror(int errnum, char *errbuf, size_t errbuf_size);
*/
#define STR(tok) #tok
#define ERRBUF_SIZE 256
static char g_errbuf[ERRBUF_SIZE];
#define PRINT_AV_ERROR(x) \
av_strerror( errno, g_errbuf, ERRBUF_SIZE ); \
if ( errno ) \
std::cerr << x << STR(:) << g_errbuf << std::endl; \
else \
std::cerr << x << STR(:UNKNOWN ERROR errno not set ) << std::endl;
int main( int argc, char* argv[] )
{
(void) argc;
(void) argv;
int rtn_val = 0;
std::string f( "enc.mp4" );
AVDictionary * av_dict_opts = NULL;
AVCodec * av_encode_codec;
AVCodecContext * av_encode_codec_ctx;
AVFormatContext * av_out_fmt_ctx;
AVStream * video_st;
av_register_all();
av_dict_set( &av_dict_opts, "b", "2.5M", 0);
av_dict_set( &av_dict_opts, "preset", "losslesshp", 0 );
av_dict_set( &av_dict_opts, "profile", "high", 0 );
av_dict_set( &av_dict_opts, "rc", "vbr_minqp", 0 );
av_dict_set( &av_dict_opts, "gpu", "1", 0 );
av_encode_codec = avcodec_find_encoder( AV_CODEC_ID_H264 );
if ( !av_encode_codec ){ PRINT_AV_ERROR( "ERROR:avcodec_find_encoder:" ); return -1; }
av_encode_codec_ctx = avcodec_alloc_context3( av_encode_codec );
if ( !av_encode_codec_ctx ) { PRINT_AV_ERROR( "ERROR:avcodec_alloc_context3:" ); return -1; }
/**
* Allocate an AVFormatContext for an output format.
* avformat_free_context() can be used to free the context and
* everything allocated by the framework within it.
*
* @param *ctx is set to the created format context, or to NULL in
* case of failure
* @param oformat format to use for allocating the context, if NULL
* format_name and filename are used instead
* @param format_name the name of output format to use for allocating the
* context, if NULL filename is used instead
* @param filename the name of the filename to use for allocating the
* context, may be NULL
* @return >= 0 in case of success, a negative AVERROR code in case of
* failure
*
* int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat,
* const char *format_name, const char *filename);
*/
avformat_alloc_output_context2( &av_out_fmt_ctx, NULL, (char*)"mp4", f.c_str() );
if ( !av_out_fmt_ctx ) { PRINT_AV_ERROR( "ERROR:avformat_alloc_output_context2:" ); return -1; }
//av_out_fmt_ctx->bit_rate = 500000;
/**
* Add a new stream to a media file.
*
* When demuxing, it is called by the demuxer in read_header(). If the
* flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also
* be called in read_packet().
*
* When muxing, should be called by the user before avformat_write_header().
*
* User is required to call avcodec_close() and avformat_free_context() to
* clean up the allocation by avformat_new_stream().
*
* @param s media file handle
* @param c If non-NULL, the AVCodecContext corresponding to the new stream
* will be initialized to use this codec. This is needed for e.g. codec-specific
* defaults to be set, so codec should be provided if it is known.
*
* @return newly created stream or NULL on error.
*
* AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c);
*/
video_st = avformat_new_stream( av_out_fmt_ctx, av_encode_codec );
if ( !video_st ) { PRINT_AV_ERROR( "ERROR:avformat_new_stream:" ); return -1; }
av_encode_codec_ctx->codec_id = AV_CODEC_ID_H264;
av_encode_codec_ctx->bit_rate = 5e6;
av_encode_codec_ctx->width = 1024; /// \note multiple of 2
av_encode_codec_ctx->height = 768; /// \note multiple of 2
av_encode_codec_ctx->time_base = (AVRational) { 1, 60 }; //* 2;
av_encode_codec_ctx->gop_size = 15; // Intra frames per x P frames
av_encode_codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P; // MUST DO NOT CHANGE nvenc required
video_st->id = av_out_fmt_ctx->nb_streams - 1;
video_st->time_base.den = 60; // * 2;
video_st->time_base.num = 1;
av_out_fmt_ctx->streams[ 0 ]->codecpar->format = AV_PIX_FMT_YUV420P;
av_out_fmt_ctx->streams[ 0 ]->codecpar->bit_rate = 5e6;
//av_out_fmt_ctx->streams[ 0 ]->codecpar->bits_per_coded_sample
//av_out_fmt_ctx->streams[ 0 ]->codecpar->bits_per_raw_sample
av_out_fmt_ctx->streams[ 0 ]->codecpar->width = 1024;
av_out_fmt_ctx->streams[ 0 ]->codecpar->height = 768;
//av_out_fmt_ctx->streams[ 0 ]->codecpar->time_base.den = 60;
//av_out_fmt_ctx->streams[ 0 ]->codecpar->time_base.num = 1;
//av_out_fmt_ctx->streams[ 0 ]->codecpar->gop_size = 15; // GOP 15/60 full frame 250 ms
//av_out_fmt_ctx->streams[ 0 ]->codecpar->keyint_min = 25;
//av_out_fmt_ctx->streams[ 0 ]->codecpar->max_b_frames
//av_out_fmt_ctx->streams[ 0 ]->codecpar->b_frame_strategy = 1; // best number of B-frames to use ???
//av_out_fmt_ctx->streams[ 0 ]->codecpar->scenechange_threshold
//av_out_fmt_ctx->streams[ 0 ]->codecpar->qmin = 1;
//av_out_fmt_ctx->streams[ 0 ]->codecpar->qmax = 25;;
//av_out_fmt_ctx->streams[ 0 ]->codecpar->qcompress = 0.6;
//av_out_fmt_ctx->streams[ 0 ]->codecpar->max_qdiff = 4;
//av_out_fmt_ctx->streams[ 0 ]->codecpar->i_quant_factor = 1.4;//0.71;
//av_out_fmt_ctx->streams[ 0 ]->codecpar->refs = 2;
/**
* Initialize the AVCodecContext to use the given AVCodec. Prior to using this
* function the context has to be allocated with avcodec_alloc_context3().
*
* The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(),
* avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for
* retrieving a codec.
*
* @warning This function is not thread safe!
*
* @note Always call this function before using decoding routines (such as
* @ref avcodec_receive_frame()).
*
* @code
* avcodec_register_all();
* av_dict_set(&opts, "b", "2.5M", 0);
* codec = avcodec_find_decoder(AV_CODEC_ID_H264);
* if (!codec)
* exit(1);
*
* context = avcodec_alloc_context3(codec);
*
* if (avcodec_open2(context, codec, opts) < 0)
* exit(1);
* @endcode
*
* @param avctx The context to initialize.
* @param codec The codec to open this context for. If a non-NULL codec has been
* previously passed to avcodec_alloc_context3() or
* for this context, then this parameter MUST be either NULL or
* equal to the previously passed codec.
* @param options A dictionary filled with AVCodecContext and codec-private options.
* On return this object will be filled with options that were not found.
*
* @return zero on success, a negative value on error
* @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(),
* av_dict_set(), av_opt_find().
*
* int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
*/
rtn_val = avcodec_open2( av_encode_codec_ctx, av_encode_codec, &av_dict_opts );
if ( rtn_val < 0 ) { PRINT_AV_ERROR( "ERROR:avcodec_open2:" ); return rtn_val; }
/**
* Fill the codec context based on the values from the supplied codec
* parameters. Any allocated fields in codec that have a corresponding field in
* par are freed and replaced with duplicates of the corresponding field in par.
* Fields in codec that do not have a counterpart in par are not touched.
*
* @return >= 0 on success, a negative AVERROR code on failure.
*
* int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par);
*/
if ( avcodec_parameters_to_context( av_encode_codec_ctx, av_out_fmt_ctx->streams[ 0 ]->codecpar ) < 0 ) { PRINT_AV_ERROR( "ERROR:avcodec_parameters_to_context:" ); return rtn_val; }
if ( av_out_fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER )
av_out_fmt_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
av_dump_format( av_out_fmt_ctx, 0, f.c_str(), 1);
if ( !( av_out_fmt_ctx->oformat->flags & AVFMT_NOFILE ) )
{
rtn_val = avio_open( &av_out_fmt_ctx->pb, f.c_str(), AVIO_FLAG_WRITE );
if ( rtn_val < 0 ) { PRINT_AV_ERROR( "ERROR:avio_open:" ); return rtn_val; }
}
rtn_val = avformat_write_header( av_out_fmt_ctx, NULL );
if ( rtn_val < 0 ) { PRINT_AV_ERROR( "ERROR:avformat_write_header:" ); return rtn_val; }
return rtn_val;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment