Skip to content

Instantly share code, notes, and snippets.

@pauldotknopf
Created February 5, 2014 18:46
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 pauldotknopf/8830397 to your computer and use it in GitHub Desktop.
Save pauldotknopf/8830397 to your computer and use it in GitHub Desktop.
FFMpegHelper.cpp
#include "stdafx.h"
#include "FFMpegHelper.h"
#include "get_extradata.h"
#include <iostream>
FFMpegHelper::FFMpegHelper(void)
{
}
FFMpegHelper::~FFMpegHelper(void)
{
}
AVStream *FFMpegHelper::add_audio_stream (AVFormatContext *oc, int codec_id)
{
AVCodecContext * c;
AVStream * st;
st = av_new_stream (oc , 1);
if (! st) {
fprintf( stderr, "Could not alloc stream\n" );
exit(1);
}
c = st->codec;
c->codec_id = (AVCodecID)codec_id;
c->codec_type = AVMEDIA_TYPE_AUDIO ;
/* put sample parameters */
c->sample_fmt = AV_SAMPLE_FMT_S16;
c->sample_rate = 48000;
c->channels = 2;
c->bit_rate = 448000; //in bits/sec //@@@@@@@@@@@@@@@@@@@@ this can be customized @@@@@@@@@@@@@@@@@@@@
c->profile = FF_PROFILE_AAC_LOW; //@@@@@@@@@@@@@@@@@@@@ this can be customized @@@@@@@@@@@@@@@@@@@@
c->channel_layout = AV_CH_LAYOUT_STEREO;//?????? what is this?????
// some formats want stream headers to be separate
if(! strcmp( oc->oformat-> name, "mp4" ) || !strcmp (oc ->oformat ->name , "mov" ) || !strcmp (oc ->oformat ->name , "3gp" ))
c->flags |= CODEC_FLAG_GLOBAL_HEADER ;
return st;
}
void FFMpegHelper::open_audio (AVFormatContext *oc, AVStream *st)
{
AVCodecContext * c;
AVCodec * codec;
c = st-> codec;
/* find the audio encoder */
//codec = avcodec_find_encoder(c ->codec_id);
codec = avcodec_find_encoder_by_name("libfdk_aac");
if (! codec) {
fprintf( stderr, "codec not found\n" );
exit(1);
}
/* open it */
if ( avcodec_open2( c, codec, NULL) < 0) {
fprintf( stderr, "could not open audio codec\n" );
exit(1);
}
}
int FFMpegHelper::init_ffmpeg(mux_ctx_t *pMux_ctx, int VidWidth, int VidHeight, double frame_rate, int profile, int level, bool useAudio)
{
/* initialize libavcodec, and register all codecs and formats */
av_register_all();
/* auto detect the output format from the name. default is mpeg. */
pMux_ctx->fmt = av_guess_format (NULL , pMux_ctx->filename , NULL );
if (! pMux_ctx->fmt) {
printf( "Could not deduce output format from file extension: using MPEG.\n");
pMux_ctx->fmt = av_guess_format ("mpeg" , NULL , NULL );
}
if (! pMux_ctx->fmt) {
fprintf( stderr, "Could not find suitable output format\n" );
exit(1);
}
/* allocate the output media context */
pMux_ctx->oc = avformat_alloc_context ();
if (! pMux_ctx->oc) {
fprintf( stderr, "Memory error\n" );
exit(1);
}
pMux_ctx->oc->oformat = pMux_ctx->fmt;
printf("#####################################################\n");
printf("%s\n", avformat_license());
pMux_ctx->fmt->video_codec = AV_CODEC_ID_H264;
if(useAudio){
pMux_ctx->fmt->audio_codec = AV_CODEC_ID_AAC;
}else
{
pMux_ctx->fmt->audio_codec = AV_CODEC_ID_NONE;
}
_snprintf( pMux_ctx->oc->filename, sizeof( pMux_ctx->oc->filename), "%s" , pMux_ctx->filename );
/* add the audio and video streams using the default format codecs
and initialize the codecs */
pMux_ctx->video_st = NULL;
if ( pMux_ctx->fmt->video_codec != CODEC_ID_NONE )
{
AVCodecContext * c;
pMux_ctx->video_st = av_new_stream (pMux_ctx->oc , 0);
if (! pMux_ctx->video_st)
{
fprintf( stderr, "Could not alloc video_stream\n" );
exit(1);
}
c = pMux_ctx->video_st->codec;
c->codec_id = ( AVCodecID) pMux_ctx->fmt->video_codec;
c->codec_type = AVMEDIA_TYPE_VIDEO ;
c->me_range = 2048;
c->max_qdiff = 51;
/* resolution muvideo_st be a multiple of two */
c->width = VidWidth;
c->height = VidHeight;
c->time_base.num = 1000000;
c->time_base.den = 1000000*(int)frame_rate;
c->pix_fmt = AV_PIX_FMT_YUV420P ;
//#############################
c->extradata = (uint8_t*)av_mallocz(100);//100bytes must be plenty for extradata
encFrame_t encFrame;
encFrame.frame_height = VidHeight;
encFrame.frame_width = VidWidth;
encFrame.useHighProfile = profile == 2;
encFrame.level = level;
encFrame.PQIndex = 10;//junk start qp
get_extradata((char *)c->extradata, &c->extradata_size, &encFrame);
//#############################
if ( c->codec_id == CODEC_ID_MPEG2VIDEO ) {
/* juvideo_st for tevideo_sting, we also add B frames */
c->max_b_frames = 2;
}
if ( c->codec_id == CODEC_ID_MPEG1VIDEO ){
/* Needed to avoid using macroblocks in which some coeffs overflow.
This does not happen with normal video, it juvideo_st happens here as
the motion of the chroma plane does not match the luma plane. */
c->mb_decision =2;
}
// some formats want video_stream headers to be separate
if(! strcmp( pMux_ctx->oc->oformat-> name, "mp4" ) || !strcmp (pMux_ctx->oc ->oformat ->name , "mov" ) || !strcmp (pMux_ctx->oc ->oformat ->name , "3gp" ))
c->flags |= CODEC_FLAG_GLOBAL_HEADER ;
}
/* now that all the parameters are set, we can open the audio and
video codecs and allocate the necessary encode buffers */
//if ( pMux_ctx->video_st)
if(0)
{
AVCodec * codec;
/* find the video encoder */
codec = avcodec_find_encoder (pMux_ctx->video_st->codec->codec_id );
if (! codec) {
fprintf( stderr, "Video codec not found\n" );
exit(1);
}
/* open the codec */
if ( avcodec_open2( pMux_ctx->video_st->codec, codec, NULL) < 0) {
fprintf( stderr, "could not open video codec\n" );
exit(1);
}
}
/* open the output file */
if (!( pMux_ctx->fmt-> flags & AVFMT_NOFILE )) {
if ( avio_open(&pMux_ctx->oc->pb, pMux_ctx->filename, AVIO_FLAG_WRITE) < 0) {
fprintf( stderr, "Could not open '%s'\n" , pMux_ctx->filename );
exit(1);
}
}
if ( pMux_ctx->fmt->audio_codec != CODEC_ID_NONE )
{
pMux_ctx->audio_st = add_audio_stream (pMux_ctx->oc, pMux_ctx->fmt->audio_codec );
pMux_ctx->audio_outbuf_size = FF_MIN_BUFFER_SIZE * 10;
pMux_ctx->audio_outbuf = (uint8_t *)av_malloc(pMux_ctx->audio_outbuf_size);
}
if ( pMux_ctx->audio_st)
{
open_audio( pMux_ctx->oc, pMux_ctx->audio_st);
}
/* write the stream header, if any */
if( avformat_write_header (pMux_ctx->oc, NULL ) < 0)
{
fprintf( stderr, "Could not write header for output file\n" );
return -1;
}
return 0;
}
int FFMpegHelper::close_ffmpeg(mux_ctx_t *pMux_ctx)
{
int i;
/* close each codec */
if ( pMux_ctx->video_st)
{
avcodec_close( pMux_ctx->video_st->codec);
}
if ( pMux_ctx->audio_st)
{
avcodec_close( pMux_ctx->audio_st->codec);
av_free( pMux_ctx->audio_outbuf );
}
/* write the trailer, if any */
int res = av_write_trailer (pMux_ctx->oc );
/* free the streams */
for( i = 0; i < (int)pMux_ctx->oc->nb_streams; i++) {
av_freep(& pMux_ctx->oc->streams[ i]-> codec);
av_freep(& pMux_ctx->oc->streams[ i]);
}
if (!( pMux_ctx->fmt-> flags & AVFMT_NOFILE )) {
/* close the output file */
avio_close( pMux_ctx->oc->pb);
}
/* free the stream */
av_free( pMux_ctx->oc);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment