Пример #1
0
/* With LOCK */
static gboolean
gst_ffmpegauddec_close (GstFFMpegAudDec * ffmpegdec, gboolean reset)
{
  GstFFMpegAudDecClass *oclass;

  oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));

  GST_LOG_OBJECT (ffmpegdec, "closing libav codec");

  gst_caps_replace (&ffmpegdec->last_caps, NULL);
  gst_buffer_replace (&ffmpegdec->outbuf, NULL);

  gst_ffmpeg_avcodec_close (ffmpegdec->context);
  ffmpegdec->opened = FALSE;

  if (ffmpegdec->context->extradata) {
    av_free (ffmpegdec->context->extradata);
    ffmpegdec->context->extradata = NULL;
  }

  if (reset) {
    if (avcodec_get_context_defaults3 (ffmpegdec->context,
            oclass->in_plugin) < 0) {
      GST_DEBUG_OBJECT (ffmpegdec, "Failed to set context defaults");
      return FALSE;
    }
    ffmpegdec->context->opaque = ffmpegdec;
  }

  return TRUE;
}
Пример #2
0
/* Add a video output stream. */
static AVStream *add_video_stream(AVFormatContext *oc, enum CodecID codec_id)
{
    AVCodecContext *c;
    AVStream *st;
    AVCodec *codec;

    /* find the video encoder */
    codec = avcodec_find_encoder(codec_id);
    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }

    st = avformat_new_stream(oc, codec);
    if (!st) {
        fprintf(stderr, "Could not alloc stream\n");
        exit(1);
    }

    c = st->codec;

    /* find the video encoder */
    codec = avcodec_find_encoder(codec_id);
    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }
    avcodec_get_context_defaults3(c, codec);

    c->codec_id = codec_id;

    /* Put sample parameters. */
    c->bit_rate = 400000;
    /* Resolution must be a multiple of two. */
    c->width    = 352;
    c->height   = 288;
    /* timebase: This is the fundamental unit of time (in seconds) in terms
     * of which frame timestamps are represented. For fixed-fps content,
     * timebase should be 1/framerate and timestamp increments should be
     * identical to 1. */
    c->time_base.den = STREAM_FRAME_RATE;
    c->time_base.num = 1;
    c->gop_size      = 12; /* emit one intra frame every twelve frames at most */
    c->pix_fmt       = STREAM_PIX_FMT;
    if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
        /* just for testing, 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 just happens here as
         * the motion of the chroma plane does not match the luma plane. */
        c->mb_decision = 2;
    }
    /* Some formats want stream headers to be separate. */
    if (oc->oformat->flags & AVFMT_GLOBALHEADER)
        c->flags |= CODEC_FLAG_GLOBAL_HEADER;

    return st;
}
Пример #3
0
AVStream* Muxer::CreateStream(AVCodec* codec) {
	Q_ASSERT(!m_started);
	Q_ASSERT(m_format_context->nb_streams < MUXER_MAX_STREAMS);

	// create a new stream
#if SSR_USE_AVFORMAT_NEW_STREAM
	AVStream *stream = avformat_new_stream(m_format_context, codec);
#else
	AVStream *stream = av_new_stream(m_format_context, m_format_context->nb_streams);
#endif
	if(stream == NULL) {
		Logger::LogError("[Muxer::AddStream] " + QObject::tr("Error: Can't create new stream!"));
		throw LibavException();
	}

#if !SSR_USE_AVFORMAT_NEW_STREAM
	if(avcodec_get_context_defaults3(stream->codec, codec) < 0) {
		Logger::LogError("[Muxer::AddStream] " + QObject::tr("Error: Can't get codec context defaults!"));
		throw LibavException();
	}
	stream->codec->codec_id = codec->id;
	stream->codec->codec_type = codec->type;
#endif

	// not sure why this is needed, but it's in the example code and it doesn't work without this
	if(m_format_context->oformat->flags & AVFMT_GLOBALHEADER)
		stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;

	return stream;
}
Пример #4
0
AVCodecContext *avcodec_alloc_context3(AVCodec *codec)
{
/*
	参数:
		1、
		
	返回:
		1、
		
	说明:
		1、
*/
	AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));

	if(avctx==NULL)
		return NULL;

	if(avcodec_get_context_defaults3(avctx, codec) < 0)
	{
		av_free(avctx);
		return NULL;
	}

	return avctx;
}
Пример #5
0
AVStream* Muxer::AddStream(AVCodec* codec, AVCodecContext** codec_context) {
	assert(!m_started);
	assert(m_format_context->nb_streams < MUXER_MAX_STREAMS);

	Logger::LogInfo("[Muxer::AddStream] " + Logger::tr("Using codec %1 (%2).").arg(codec->name).arg(codec->long_name));

	// create a new stream
#if SSR_USE_AVSTREAM_CODECPAR
	AVStream *stream = avformat_new_stream(m_format_context, NULL);
#elif SSR_USE_AVFORMAT_NEW_STREAM
	AVStream *stream = avformat_new_stream(m_format_context, codec);
#else
	AVStream *stream = av_new_stream(m_format_context, m_format_context->nb_streams);
#endif
	if(stream == NULL) {
		Logger::LogError("[Muxer::AddStream] " + Logger::tr("Error: Can't create new stream!"));
		throw LibavException();
	}
	assert(stream->index == (int) m_format_context->nb_streams - 1);
#if SSR_USE_AVSTREAM_CODECPAR
	*codec_context = avcodec_alloc_context3(codec);
	if(*codec_context == NULL) {
		Logger::LogError("[Muxer::AddStream] " + Logger::tr("Error: Can't create new codec context!"));
		throw LibavException();
	}
#else
	assert(stream->codec != NULL);
	*codec_context = stream->codec;
#endif
	//stream->id = m_format_context->nb_streams - 1;

#if !SSR_USE_AVFORMAT_NEW_STREAM
	// initialize the codec context (only needed for old API)
	if(avcodec_get_context_defaults3(*codec_context, codec) < 0) {
		Logger::LogError("[Muxer::AddStream] " + Logger::tr("Error: Can't get codec context defaults!"));
		throw LibavException();
	}
	(*codec_context)->codec_id = codec->id;
	(*codec_context)->codec_type = codec->type;
#endif

	// not sure why this is needed, but it's in the example code and it doesn't work without this
	if(m_format_context->oformat->flags & AVFMT_GLOBALHEADER)
		(*codec_context)->flags |= CODEC_FLAG_GLOBAL_HEADER;

	// if the codec is experimental, allow it
	if(codec->capabilities & CODEC_CAP_EXPERIMENTAL) {
		Logger::LogWarning("[Muxer::AddStream] " + Logger::tr("Warning: This codec is considered experimental by libav/ffmpeg."));
		(*codec_context)->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
	}

#if SSR_USE_SIDE_DATA_ONLY_PACKETS && !SSR_USE_SIDE_DATA_ONLY_PACKETS_DEPRECATED
	// this option was added with the intent to deprecate it again in the next version,
	// because the ffmpeg/libav devs like deprecating things :)
	(*codec_context)->side_data_only_packets = 1;
#endif

	return stream;
}
Пример #6
0
static void AddAudioStream()
{
    g_pAStream = avformat_new_stream(g_pContainer, g_pACodec);
    if(!g_pAStream)
    {
        Log("Could not allocate audio stream\n");
        return;
    }
    g_pAStream->id = 1;

    g_pAudio = g_pAStream->codec;

    avcodec_get_context_defaults3(g_pAudio, g_pACodec);
    g_pAudio->codec_id = g_pACodec->id;

    // put parameters
    g_pAudio->sample_fmt = AV_SAMPLE_FMT_S16;
    g_pAudio->sample_rate = g_Frequency;
    g_pAudio->channels = g_Channels;

    // set time base as invers of sample rate
    g_pAudio->time_base.den = g_pAStream->time_base.den = g_Frequency;
    g_pAudio->time_base.num = g_pAStream->time_base.num = 1;

    // set quality
    g_pAudio->bit_rate = 160000;

    // for codecs that support variable bitrate use it, it should be better
    g_pAudio->flags |= AV_CODEC_FLAG_QSCALE;
    g_pAudio->global_quality = 1*FF_QP2LAMBDA;

    // some formats want stream headers to be separate
    if (g_pFormat->flags & AVFMT_GLOBALHEADER)
        g_pAudio->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

    // open it
    if (avcodec_open2(g_pAudio, g_pACodec, NULL) < 0)
    {
        Log("Could not open audio codec %s\n", g_pACodec->long_name);
        return;
    }

#if LIBAVCODEC_VERSION_MAJOR >= 54
    if (g_pACodec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)
#else
    if (g_pAudio->frame_size == 0)
#endif
        g_NumSamples = 4096;
    else
        g_NumSamples = g_pAudio->frame_size;
    g_pSamples = (int16_t*)av_malloc(g_NumSamples*g_Channels*sizeof(int16_t));
    g_pAFrame = av_frame_alloc();
    if (!g_pAFrame)
    {
        Log("Could not allocate frame\n");
        return;
    }
}
/* Add an output stream. */
static AVStream *add_stream(AVFormatContext *oc, AVCodec **codec, enum AVCodecID codec_id, StreamInfo *sInfo) {
	AVCodecContext *c;
	AVStream *st;
	/* find the encoder */
	*codec = avcodec_find_encoder(codec_id);
	if (!(*codec)) {
		fprintf(stderr, "Could not find encoder for '%s'\n", avcodec_get_name(codec_id));
		exit(1);
	}
	st = avformat_new_stream(oc, *codec);
	if (!st) {
		fprintf(stderr, "Could not allocate stream\n");
		exit(1);
	}
	st->id = oc->nb_streams - 1;
	c = st->codec;
	switch ((*codec)->type) {
	case AVMEDIA_TYPE_VIDEO:
		avcodec_get_context_defaults3(c, *codec);
		c->codec_id = codec_id;
		c->bit_rate = sInfo->bitrate;
		
		/* Resolution must be a multiple of two. */
		c->width = sInfo->width;
		c->height = sInfo->height;
		
		/* timebase: This is the fundamental unit of time (in seconds) in terms
		 * of which frame timestamps are represented. For fixed-fps content,
		 * timebase should be 1/framerate and timestamp increments should be
		 * identical to 1. */
		c->time_base.den = sInfo->frame_rate;
		c->time_base.num = 1;
		c->gop_size = 12; /* emit one intra frame every twelve frames at most */
		c->pix_fmt = sInfo->pix_fmt;
		c->rc_min_rate = sInfo->bitrate-50;
		c->rc_max_rate = sInfo->bitrate+50;
		c->rc_buffer_size = sInfo->bitrate+60;

		if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
			/* just for testing, we also add B frames */
			//c->max_b_frames = 2;
		}
		if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
			/* Needed to avoid using macroblocks in which some coeffs overflow.
			 * This does not happen with normal video, it just happens here as
			 * the motion of the chroma plane does not match the luma plane. */
			c->mb_decision = 2;
		}
		break;
	default:
		break;
	}
	/* Some formats want stream headers to be separate. */
	if (oc->oformat->flags & AVFMT_GLOBALHEADER)
		c->flags |= CODEC_FLAG_GLOBAL_HEADER;
	return st;
}
Пример #8
0
int janus_pp_h264_create(char *destination) {
	if(destination == NULL)
		return -1;
	/* Setup FFmpeg */
	av_register_all();
	/* Adjust logging to match the postprocessor's */
	av_log_set_level(janus_log_level <= LOG_NONE ? AV_LOG_QUIET :
		(janus_log_level == LOG_FATAL ? AV_LOG_FATAL :
			(janus_log_level == LOG_ERR ? AV_LOG_ERROR :
				(janus_log_level == LOG_WARN ? AV_LOG_WARNING :
					(janus_log_level == LOG_INFO ? AV_LOG_INFO :
						(janus_log_level == LOG_VERB ? AV_LOG_VERBOSE : AV_LOG_DEBUG))))));
	/* MP4 output */
	fctx = avformat_alloc_context();
	if(fctx == NULL) {
		JANUS_LOG(LOG_ERR, "Error allocating context\n");
		return -1;
	}
	fctx->oformat = av_guess_format("mp4", NULL, NULL);
	if(fctx->oformat == NULL) {
		JANUS_LOG(LOG_ERR, "Error guessing format\n");
		return -1;
	}
	snprintf(fctx->filename, sizeof(fctx->filename), "%s", destination);
	vStream = avformat_new_stream(fctx, 0);
	if(vStream == NULL) {
		JANUS_LOG(LOG_ERR, "Error adding stream\n");
		return -1;
	}
#if LIBAVCODEC_VER_AT_LEAST(53, 21)
	avcodec_get_context_defaults3(vStream->codec, AVMEDIA_TYPE_VIDEO);
#else
	avcodec_get_context_defaults2(vStream->codec, AVMEDIA_TYPE_VIDEO);
#endif
#if LIBAVCODEC_VER_AT_LEAST(54, 25)
	vStream->codec->codec_id = AV_CODEC_ID_H264;
#else
	vStream->codec->codec_id = CODEC_ID_H264;
#endif
	vStream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
	vStream->codec->time_base = (AVRational){1, fps};
	vStream->time_base = (AVRational){1, 90000};
	vStream->codec->width = max_width;
	vStream->codec->height = max_height;
	vStream->codec->pix_fmt = PIX_FMT_YUV420P;
	//~ if (fctx->flags & AVFMT_GLOBALHEADER)
		vStream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
	if(avio_open(&fctx->pb, fctx->filename, AVIO_FLAG_WRITE) < 0) {
		JANUS_LOG(LOG_ERR, "Error opening file for output\n");
		return -1;
	}
	if(avformat_write_header(fctx, NULL) < 0) {
		JANUS_LOG(LOG_ERR, "Error writing header\n");
		return -1;
	}
	return 0;
}
Пример #9
0
void addVideoStream(AVFormatContext *dest){
	AVCodecContext *c;
	AVStream *st;
	AVCodec *codec;

	/* find the video encoder */
	codec = avcodec_find_encoder(VIDEO_CODEC_ID);
	if (!codec) {
		LOGI("add_video_stream codec not found, as expected. No encoding necessary");
	}

	st = avformat_new_stream(dest, codec);
	if (!st) {
		LOGE("add_video_stream could not alloc stream");
	}

	videoStreamIndex = st->index;
	LOGI("addVideoStream at index %d", videoStreamIndex);
	c = st->codec;

	avcodec_get_context_defaults3(c, codec);

	c->codec_id = VIDEO_CODEC_ID;

	/* Put sample parameters. */
	// c->bit_rate = 400000;
	/* Resolution must be a multiple of two. */
	c->width    = VIDEO_WIDTH;
	c->height   = VIDEO_HEIGHT;

	/* timebase: This is the fundamental unit of time (in seconds) in terms
	 * of which frame timestamps are represented. For fixed-fps content,
	 * timebase should be 1/framerate and timestamp increments should be
	 * identical to 1. */
	c->time_base.den = 30;
	c->time_base.num = 1;
	/*
	c->gop_size      = 12; // emit one intra frame every twelve frames at most
	*/
	c->pix_fmt       = VIDEO_PIX_FMT;

	/* Not encoding
	if(codec_id == CODEC_ID_H264){
			av_opt_set(c->priv_data, "preset", "ultrafast", 0);
			if(crf)
					av_opt_set_double(c->priv_data, "crf", crf, 0);
			else
					av_opt_set_double(c->priv_data, "crf", 24.0, 0);
	}
	*/

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

}
Пример #10
0
static void output_init()
{
	int i, err;

	AVCodec *c[2];
	char *guess_fp = "a.flv";

//	AVStream *st = ;
	ofc = avformat_alloc_context();
	AVOutputFormat *ofmt = av_guess_format(NULL, guess_fp, NULL);
	ofc->oformat = ofmt;
	strcpy(ofc->filename, guess_fp);
	printf("ofc ok\n");

	AVStream *ost[2];
	ost[0] = avformat_new_stream(ofc, NULL);
	//ost[0]->codec->codec_id = ist[0]->codec->codec_id;
	AVCodecContext *codec[2];
	codec[0] = ost[0]->codec;
	avcodec_get_context_defaults3(codec[0], NULL);
	codec[0]->codec_id = AV_CODEC_ID_H264;
	codec[0]->codec_type = AVMEDIA_TYPE_VIDEO;
	codec[0]->time_base.num = 1;
	codec[0]->time_base.den = 25;
	codec[0]->width = 720;
	codec[0]->height = 360;
	codec[0]->codec_tag = av_codec_get_tag(ofmt->codec_tag, AV_CODEC_ID_H264);
	printf("ofc->codec codec[0]=%p ofc->st[0]->codec=%p\n", codec[0], ofc->streams[0]->codec);
	printf("codec[0].tag=%d\n", codec[0]->codec_tag);

	err = avio_open2(&ofc->pb, output_filename, AVIO_FLAG_WRITE, NULL, NULL);
	printf("open2=%d\n", err);

	printf("write header\n");
	printf("ofc.nb_streams=%d\n", ofc->nb_streams);
	printf("ofc.st[0]=%p\n", ofc->streams[0]);
	printf("ofc.st[0].codec=%p\n", ofc->streams[0]->codec);
	printf("ofc.oformat=%p\n", ofc->oformat);
	printf("ofc.oformat.write_header=%p\n", ofc->oformat->write_header);
	printf("ofc.oformat.name=%s\n", ofc->oformat->name);
	printf("ofc.pb=%p\n", ofc->pb);
	printf("ofc.st[0].avg_frame_rate={%d,%d}\n", 
			ofc->streams[0]->avg_frame_rate.num,
			ofc->streams[0]->avg_frame_rate.den
			);
	printf("ofc.st[0].codec.timebase={%d,%d}\n", 
			ofc->streams[0]->codec->time_base.num,
			ofc->streams[0]->codec->time_base.den
			);
	printf("ofc.priv=%p\n", ofc->priv_data);

	//err = ofc->oformat->write_header(ofc);
	err = avformat_write_header(ofc, NULL);
	printf("write_header=%d\n", err);
	avio_flush(ofc->pb);
}
Пример #11
0
static void dec_open(DecData *d){
	AVCodec *codec;
	int error;
	codec=avcodec_find_decoder(CODEC_ID_H264);
	if (codec==NULL) ms_fatal("Could not find H264 decoder in ffmpeg.");
	avcodec_get_context_defaults3(&d->av_context, NULL);
	error=avcodec_open2(&d->av_context,codec, NULL);
	if (error!=0){
		ms_fatal("avcodec_open() failed.");
	}
}
Пример #12
0
AVCodecContext *avcodec_alloc_context3(const AVCodec *codec)
{
    AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));

    if (!avctx)
        return NULL;

    if(avcodec_get_context_defaults3(avctx, codec) < 0){
        av_free(avctx);
        return NULL;
    }

    return avctx;
}
Пример #13
0
int CamReadThread::EncodeInit()
{
	c= NULL;
	int yuv420_bytes = 0;
	m_pRGBFrame =  new AVFrame[1];  //RGB帧数据
	m_pYUVFrame =  new AVFrame[1];  //YUV帧数据

	av_register_all();
	avcodec_register_all();
	avformat_network_init();

	fmtctx = avformat_alloc_context();

  codec = avcodec_find_encoder(AV_CODEC_ID_H264);
  if (!codec) {
      dbgprint("%s(%d),%d CAM Codec not found!\n",DEBUGARGS,CameraID);
  		return -1;
  }

	video_st = avformat_new_stream(fmtctx, codec);
	c = video_st->codec;
	avcodec_get_context_defaults3(c, codec);
  if (!c) {
    dbgprint("%s(%d),%d CAM Could not allocate video codec context!\n",DEBUGARGS,CameraID);
    return -1;
  }
	c->codec_id = AV_CODEC_ID_H264;
	c->width  = m_cols;
	c->height = m_rows;
	c->time_base = (AVRational){1,m_fps};
	c->gop_size = 10;
	c->max_b_frames = 1;
	c->pix_fmt = AV_PIX_FMT_YUV420P;

	if (avcodec_open2(c, codec, NULL) < 0) {
      dbgprint("%s(%d),%d CAM Could not open codec!\n",DEBUGARGS,CameraID);
      return -1;
	}

	m_pYUVFrame = av_frame_alloc();
	yuv420_bytes = avpicture_get_size( AV_PIX_FMT_YUV420P, m_cols, m_rows);
	pYUV_buffer = (uint8_t *)av_malloc(yuv420_bytes*sizeof(uint8_t));
	m_pYUVFrame->format = c->pix_fmt;
	m_pYUVFrame->width  = c->width;
	m_pYUVFrame->height = c->height;
	avpicture_fill((AVPicture*)m_pYUVFrame, pYUV_buffer, AV_PIX_FMT_YUV420P, m_cols, m_rows);
	scxt = sws_getContext(m_cols, m_rows,AV_PIX_FMT_RGB24, m_cols, m_rows,AV_PIX_FMT_YUV420P, 0, 0, 0, 0);
	return 0;
}
Пример #14
0
static gboolean
gst_ffmpegvidenc_start (GstVideoEncoder * encoder)
{
  GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
  GstFFMpegVidEncClass *oclass =
      (GstFFMpegVidEncClass *) G_OBJECT_GET_CLASS (ffmpegenc);

  /* close old session */
  if (avcodec_get_context_defaults3 (ffmpegenc->context, oclass->in_plugin) < 0) {
    GST_DEBUG_OBJECT (ffmpegenc, "Failed to set context defaults");
    return FALSE;
  }

  return TRUE;
}
Пример #15
0
static gboolean
gst_ffmpegaudenc_start (GstAudioEncoder * encoder)
{
  GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
  GstFFMpegAudEncClass *oclass =
      (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);

  gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
  if (avcodec_get_context_defaults3 (ffmpegaudenc->context,
          oclass->in_plugin) < 0) {
    GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
    return FALSE;
  }

  return TRUE;
}
Пример #16
0
AVStream* Muxer::AddStream(AVCodec* codec) {
	assert(!m_started);
	assert(m_format_context->nb_streams < MUXER_MAX_STREAMS);

	Logger::LogInfo("[Muxer::AddStream] " + Logger::tr("Using codec %1 (%2).").arg(codec->name).arg(codec->long_name));

	// create a new stream
#if SSR_USE_AVFORMAT_NEW_STREAM
	AVStream *stream = avformat_new_stream(m_format_context, codec);
#else
	AVStream *stream = av_new_stream(m_format_context, m_format_context->nb_streams);
#endif
	if(stream == NULL) {
		Logger::LogError("[Muxer::AddStream] " + Logger::tr("Error: Can't create new stream!"));
		throw LibavException();
	}
	assert(stream->index == (int) m_format_context->nb_streams - 1);
	assert(stream->codec != NULL);
	//stream->id = m_format_context->nb_streams - 1;

#if !SSR_USE_AVFORMAT_NEW_STREAM
	// initialize the codec context (only needed for old API)
	if(avcodec_get_context_defaults3(stream->codec, codec) < 0) {
		Logger::LogError("[Muxer::AddStream] " + Logger::tr("Error: Can't get codec context defaults!"));
		throw LibavException();
	}
	stream->codec->codec_id = codec->id;
	stream->codec->codec_type = codec->type;
#else
	//assert(stream->codec->codec_id == codec->id);
	//assert(stream->codec->codec_type == codec->type);
#endif

	// not sure why this is needed, but it's in the example code and it doesn't work without this
	if(m_format_context->oformat->flags & AVFMT_GLOBALHEADER)
		stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;

	// if the codec is experimental, allow it
	if(codec->capabilities & CODEC_CAP_EXPERIMENTAL) {
		Logger::LogWarning("[Muxer::AddStream] " + Logger::tr("Warning: This codec is considered experimental by libav/ffmpeg."));
		stream->codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
	}

	return stream;
}
Пример #17
0
	std::shared_ptr<AVStream> add_audio_stream(std::vector<option>& options)
	{
		if(output_format_.acodec == CODEC_ID_NONE)
			return nullptr;

		auto st = av_new_stream(oc_.get(), 1);
		if(!st)
			BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Could not allocate audio-stream") << boost::errinfo_api_function("av_new_stream"));		
		
		auto encoder = avcodec_find_encoder(output_format_.acodec);
		if (!encoder)
			BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("codec not found"));
		
		auto c = st->codec;

		avcodec_get_context_defaults3(c, encoder);

		c->codec_id			= output_format_.acodec;
		c->codec_type		= AVMEDIA_TYPE_AUDIO;
		c->sample_rate		= 48000;
		c->channels			= channel_layout_.num_channels;
		c->sample_fmt		= SAMPLE_FMT_S16;

		if(output_format_.vcodec == CODEC_ID_FLV1)		
			c->sample_rate	= 44100;		

		if(output_format_.format->flags & AVFMT_GLOBALHEADER)
			c->flags |= CODEC_FLAG_GLOBAL_HEADER;
				
		boost::range::remove_erase_if(options, [&](const option& o)
		{
			return ffmpeg::av_opt_set(c, o.name.c_str(), o.value.c_str(), AV_OPT_SEARCH_CHILDREN) > -1;
		});

		THROW_ON_ERROR2(avcodec_open(c, encoder), "[ffmpeg_consumer]");

		return std::shared_ptr<AVStream>(st, [](AVStream* st)
		{
			LOG_ON_ERROR2(avcodec_close(st->codec), "[ffmpeg_consumer]");;
			av_freep(&st->codec);
			av_freep(&st);
		});
	}
Пример #18
0
static gboolean
gst_ffmpegauddec_start (GstAudioDecoder * decoder)
{
  GstFFMpegAudDec *ffmpegdec = (GstFFMpegAudDec *) decoder;
  GstFFMpegAudDecClass *oclass;

  oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));

  GST_OBJECT_LOCK (ffmpegdec);
  gst_ffmpeg_avcodec_close (ffmpegdec->context);
  if (avcodec_get_context_defaults3 (ffmpegdec->context, oclass->in_plugin) < 0) {
    GST_DEBUG_OBJECT (ffmpegdec, "Failed to set context defaults");
    GST_OBJECT_UNLOCK (ffmpegdec);
    return FALSE;
  }
  ffmpegdec->context->opaque = ffmpegdec;
  GST_OBJECT_UNLOCK (ffmpegdec);

  return TRUE;
}
Пример #19
0
void addAudioStream(AVFormatContext *formatContext){
	AVCodecContext *codecContext;
	AVStream *st;
	AVCodec *codec;

	/* find the audio encoder */
	codec = avcodec_find_encoder(AUDIO_CODEC_ID);
	if (!codec) {
		LOGE("add_audio_stream codec not found");
	}
	//LOGI("add_audio_stream found codec_id: %d",codec_id);
	st = avformat_new_stream(formatContext, codec);
	if (!st) {
		LOGE("add_audio_stream could not alloc stream");
	}

	audioStreamIndex = st->index;

	//st->id = 1;
	codecContext = st->codec;
	avcodec_get_context_defaults3(codecContext, codec);
	codecContext->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL; // for native aac support
	/* put sample parameters */
	//codecContext->sample_fmt  = AV_SAMPLE_FMT_FLT;
	codecContext->sample_fmt  = AUDIO_SAMPLE_FMT;
	codecContext->time_base.den = 44100;
	codecContext->time_base.num = 1;
	//c->bit_rate    = bit_rate;
	codecContext->sample_rate = AUDIO_SAMPLE_RATE;
	codecContext->channels    = AUDIO_CHANNELS;
	LOGI("addAudioStream sample_rate %d index %d", codecContext->sample_rate, st->index);
	//LOGI("add_audio_stream parameters: sample_fmt: %d bit_rate: %d sample_rate: %d", codec_audio_sample_fmt, bit_rate, audio_sample_rate);
	// some formats want stream headers to be separate
	if (formatContext->oformat->flags & AVFMT_GLOBALHEADER)
		codecContext->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
Пример #20
0
static int ffserver_set_codec(AVCodecContext *ctx, const char *codec_name,
                              FFServerConfig *config)
{
    int ret;
    AVCodec *codec = avcodec_find_encoder_by_name(codec_name);
    if (!codec || codec->type != ctx->codec_type) {
        report_config_error(config->filename, config->line_num, AV_LOG_ERROR,
                            &config->errors,
                            "Invalid codec name: '%s'\n", codec_name);
        return 0;
    }
    if (ctx->codec_id == AV_CODEC_ID_NONE && !ctx->priv_data) {
        if ((ret = avcodec_get_context_defaults3(ctx, codec)) < 0)
            return ret;
        ctx->codec = codec;
    }
    if (ctx->codec_id != codec->id)
        report_config_error(config->filename, config->line_num, AV_LOG_ERROR,
                            &config->errors,
                            "Inconsistent configuration: trying to set '%s' "
                            "codec option, but '%s' codec is used previously\n",
                            codec_name, avcodec_get_name(ctx->codec_id));
    return 0;
}
Пример #21
0
static int
bt_play_open(struct voss_backend *pbe, const char *devname, int samplerate,
    int bufsize, int *pchannels, int *pformat)
{
	struct bt_config *cfg = pbe->arg;
	int retval;

	bt_init_cfg(cfg);

	retval = bt_open(pbe, devname, samplerate, bufsize, pchannels, pformat,
	    cfg, SDP_SERVICE_CLASS_AUDIO_SINK, 1);
	if (retval != 0)
		return (retval);

	/* setup codec */
	switch (cfg->codec) {
	case CODEC_SBC:
		cfg->handle.sbc_enc =
		    malloc(sizeof(*cfg->handle.sbc_enc));
		if (cfg->handle.sbc_enc == NULL)
			return (-1);
		memset(cfg->handle.sbc_enc, 0, sizeof(*cfg->handle.sbc_enc));
		break;
#ifdef HAVE_FFMPEG
	case CODEC_AAC:
		av_register_all();

		cfg->handle.av.codec = avcodec_find_encoder_by_name("aac");
		if (cfg->handle.av.codec == NULL) {
			DPRINTF("Codec AAC encoder not found\n");
			goto av_error_0;
		}
		cfg->handle.av.format = avformat_alloc_context();
		if (cfg->handle.av.format == NULL) {
			DPRINTF("Could not allocate format context\n");
			goto av_error_0;
		}
		cfg->handle.av.format->oformat =
		    av_guess_format("latm", NULL, NULL);
		if (cfg->handle.av.format->oformat == NULL) {
			DPRINTF("Could not guess output format\n");
			goto av_error_1;
		}
		cfg->handle.av.stream = avformat_new_stream(
		    cfg->handle.av.format, cfg->handle.av.codec);

		if (cfg->handle.av.stream == NULL) {
			DPRINTF("Could not create new stream\n");
			goto av_error_1;
		}
		cfg->handle.av.context = cfg->handle.av.stream->codec;
		if (cfg->handle.av.context == NULL) {
			DPRINTF("Could not allocate audio context\n");
			goto av_error_1;
		}
		avcodec_get_context_defaults3(cfg->handle.av.context,
		    cfg->handle.av.codec);

		cfg->handle.av.context->bit_rate = 128000;
		cfg->handle.av.context->sample_fmt = AV_SAMPLE_FMT_FLTP;
		cfg->handle.av.context->sample_rate = samplerate;
		switch (*pchannels) {
		case 1:
			cfg->handle.av.context->channel_layout = AV_CH_LAYOUT_MONO;
			cfg->handle.av.context->channels = 1;
			break;
		default:
			cfg->handle.av.context->channel_layout = AV_CH_LAYOUT_STEREO;
			cfg->handle.av.context->channels = 2;
			break;
		}

		cfg->handle.av.context->profile = FF_PROFILE_AAC_LOW;
		if (1) {
			AVDictionary *opts = NULL;

			av_dict_set(&opts, "strict", "-2", 0);
			av_dict_set_int(&opts, "latm", 1, 0);

			if (avcodec_open2(cfg->handle.av.context,
			    cfg->handle.av.codec, &opts) < 0) {
				av_dict_free(&opts);

				DPRINTF("Could not open codec\n");
				goto av_error_1;
			}
			av_dict_free(&opts);
		}
		cfg->handle.av.frame = av_frame_alloc();
		if (cfg->handle.av.frame == NULL) {
			DPRINTF("Could not allocate audio frame\n");
			goto av_error_2;
		}
		cfg->handle.av.frame->nb_samples = cfg->handle.av.context->frame_size;
		cfg->handle.av.frame->format = cfg->handle.av.context->sample_fmt;
		cfg->handle.av.frame->channel_layout = cfg->handle.av.context->channel_layout;
		cfg->rem_in_size = av_samples_get_buffer_size(NULL,
		    cfg->handle.av.context->channels,
		    cfg->handle.av.context->frame_size,
		    cfg->handle.av.context->sample_fmt, 0);

		cfg->rem_in_data = av_malloc(cfg->rem_in_size);
		if (cfg->rem_in_data == NULL) {
			DPRINTF("Could not allocate %u bytes sample buffer\n",
			    (unsigned)cfg->rem_in_size);
			goto av_error_3;
		}
		retval = avcodec_fill_audio_frame(cfg->handle.av.frame,
		    cfg->handle.av.context->channels,
		    cfg->handle.av.context->sample_fmt,
		    cfg->rem_in_data, cfg->rem_in_size, 0);
		if (retval < 0) {
			DPRINTF("Could not setup audio frame\n");
			goto av_error_4;
		}
		break;
av_error_4:
		av_free(cfg->rem_in_data);
av_error_3:
		av_frame_free(&cfg->handle.av.frame);
av_error_2:
		avcodec_close(cfg->handle.av.context);
av_error_1:
		avformat_free_context(cfg->handle.av.format);
		cfg->handle.av.context = NULL;
av_error_0:
		bt_close(pbe);
		return (-1);
#endif
	default:
		bt_close(pbe);
		return (-1);
	}
	return (0);
}
Пример #22
0
AVStream* AVFormatWriter::AddVideoStream(void)
{
    AVCodecContext *c;
    AVStream *st;
    AVCodec *codec;

    st = avformat_new_stream(m_ctx, NULL);
    if (!st)
    {
        LOG(VB_RECORD, LOG_ERR,
            LOC + "AddVideoStream(): avformat_new_stream() failed");
        return NULL;
    }
    st->id = 0;

    c = st->codec;

    codec = avcodec_find_encoder(m_ctx->oformat->video_codec);
    if (!codec)
    {
        LOG(VB_RECORD, LOG_ERR,
            LOC + "AddVideoStream(): avcodec_find_encoder() failed");
        return NULL;
    }

    avcodec_get_context_defaults3(c, codec);

    c->codec                      = codec;
    c->codec_id                   = m_ctx->oformat->video_codec;
    c->codec_type                 = AVMEDIA_TYPE_VIDEO;

    c->bit_rate                   = m_videoBitrate;
    c->width                      = m_width;
    c->height                     = m_height;

    // c->sample_aspect_ratio.num    = (int)floor(m_aspect * 10000);
    // c->sample_aspect_ratio.den    = 10000;

    c->time_base                  = GetCodecTimeBase();

    st->time_base.den             = 90000;
    st->time_base.num             = 1;
    st->r_frame_rate.num          = 0;
    st->r_frame_rate.den          = 0;

    c->gop_size                   = m_keyFrameDist;
    c->pix_fmt                    = AV_PIX_FMT_YUV420P;
    c->thread_count               = m_encodingThreadCount;
    c->thread_type                = FF_THREAD_SLICE;

    if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
        c->max_b_frames          = 2;
    }
    else if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
    {
        c->mb_decision           = 2;
    }
    else if (c->codec_id == AV_CODEC_ID_H264)
    {

        // Try to provide the widest software/device support by automatically using
        // the Baseline profile where the given bitrate and resolution permits

        if ((c->height > 720) || // Approximate highest resolution supported by Baseline 3.1
            (c->bit_rate > 1000000)) // 14,000 Kbps aka 14Mbps maximum permissable rate for Baseline 3.1
        {
            c->level = 40;
            av_opt_set(c->priv_data, "profile", "main", 0);
        }
        else if ((c->height > 576) || // Approximate highest resolution supported by Baseline 3.0
            (c->bit_rate > 1000000))  // 10,000 Kbps aka 10Mbps maximum permissable rate for Baseline 3.0
        {
            c->level = 31;
            av_opt_set(c->priv_data, "profile", "baseline", 0);
        }
        else
        {
            c->level = 30; // Baseline 3.0 is the most widely supported, but it's limited to SD
            av_opt_set(c->priv_data, "profile", "baseline", 0);
        }

        c->coder_type            = 0;
        c->max_b_frames          = 0;
        c->slices                = 8;

        c->flags                |= CODEC_FLAG_LOOP_FILTER;
        c->me_cmp               |= 1;
        c->me_method             = ME_HEX;
        c->me_subpel_quality     = 6;
        c->me_range              = 16;
        c->keyint_min            = 25;
        c->scenechange_threshold = 40;
        c->i_quant_factor        = 0.71;
        c->b_frame_strategy      = 1;
        c->qcompress             = 0.6;
        c->qmin                  = 10;
        c->qmax                  = 51;
        c->max_qdiff             = 4;
        c->refs                  = 3;
        c->trellis               = 0;

        av_opt_set(c, "partitions", "i8x8,i4x4,p8x8,b8x8", 0);
        av_opt_set_int(c, "direct-pred", 1, 0);
        av_opt_set_int(c, "rc-lookahead", 0, 0);
        av_opt_set_int(c, "fast-pskip", 1, 0);
        av_opt_set_int(c, "mixed-refs", 1, 0);
        av_opt_set_int(c, "8x8dct", 0, 0);
        av_opt_set_int(c, "weightb", 0, 0);

        av_opt_set(c->priv_data, "preset",
                   m_encodingPreset.toLatin1().constData(), 0);
        av_opt_set(c->priv_data, "tune",
                   m_encodingTune.toLatin1().constData(), 0);
    }

    if(m_ctx->oformat->flags & AVFMT_GLOBALHEADER)
        c->flags |= CODEC_FLAG_GLOBAL_HEADER;

    return st;
}
/* add a video output stream */
AVStream* CEncoder::add_video_stream(enum AVCodecID codec_id, char *name)
{
	AVCodec *codec;
	AVStream *st;
	AVCodecContext *video_enc;

	/* find the video encoder */
	if (name)
	{
		codec = avcodec_find_encoder_by_name(name);
		if (!codec)
		{
			av_log(NULL, AV_LOG_ERROR, "codec not found video encoder:%s\n", name);
			return NULL;
		}
	}
	else
	{
		codec = avcodec_find_encoder(codec_id);
		if (!codec)
		{
			av_log(NULL, AV_LOG_ERROR, "codec not found video by ID=%d\n", codec_id);
			return NULL;
		}
	}
	if(codec->type != AVMEDIA_TYPE_VIDEO)
	{
		av_log(NULL, AV_LOG_ERROR, "Invalid video encoder type '%s'\n", name);
		return NULL;
	}

	if (frame_pix_fmt == AV_PIX_FMT_NONE)
	{
		frame_pix_fmt = find_pixel_format(codec->pix_fmts);
		if (frame_pix_fmt == AV_PIX_FMT_NONE) frame_pix_fmt = codec->pix_fmts[0];
	}

	st = avformat_new_stream(oc, NULL);
	if (!st)
	{
		av_log(NULL, AV_LOG_ERROR, "Could not alloc stream\n");
		return NULL;
	}
	st->id = 0;

	video_enc = st->codec;
	video_enc->codec_type = AVMEDIA_TYPE_VIDEO;
	if (codec_id) video_enc->codec_id = codec_id;
	else video_enc->codec_id = codec->id;
	avcodec_get_context_defaults3(video_enc, codec);

	if (video_rc_max_rate != NO_VALUE)
		if (video_bit_rate > video_rc_max_rate)
			video_bit_rate = video_rc_max_rate;

	if ((sample_aspect_ratio.num != 1) && (sample_aspect_ratio.den != 1))
	{
		sample_aspect_ratio = av_d2q((double)sample_aspect_ratio.num / (double)sample_aspect_ratio.den * (double)video_height/(double)video_width, 255);
	}

	if ((video_bit_rate == 0) && (video_qscale == 0)) video_qscale = 4;
	st->sample_aspect_ratio = sample_aspect_ratio;
	if (video_bit_rate) video_enc->bit_rate = video_bit_rate;
	video_enc->width = video_width;
	video_enc->height = video_height;
	video_enc->time_base.num = g_enc_opt.m_FrameNum;
	video_enc->time_base.den = g_enc_opt.m_FrameDen;
	if (video_gop_size) video_enc->gop_size = video_gop_size; /* emit one intra frame every twelve frames at most */
	video_enc->pix_fmt = frame_pix_fmt;
	video_enc->sample_aspect_ratio = sample_aspect_ratio;
	if (video_codec_tag) video_enc->codec_tag = video_codec_tag;
	if (video_qscale)
	{
		video_enc->flags |= CODEC_FLAG_QSCALE;
		video_enc->global_quality = FF_QP2LAMBDA * video_qscale;
	}

	if (video_rc_max_rate != NO_VALUE) video_enc->rc_max_rate = video_rc_max_rate;
	if (video_rc_min_rate != NO_VALUE) video_enc->rc_min_rate = video_rc_min_rate;
	if (video_rc_buffer_size != NO_VALUE) video_enc->rc_buffer_size = video_rc_buffer_size;
	if (video_coder_type != NO_VALUE) video_enc->coder_type = video_coder_type;
	if (video_max_b_frames != NO_VALUE) video_enc->max_b_frames = video_max_b_frames;

	if (video_level != NO_VALUE) video_enc->level = video_level;
	if (video_sc_threshold != NO_VALUE) video_enc->scenechange_threshold = video_sc_threshold;
	if (video_qmin != NO_VALUE) video_enc->qmin = video_qmin;
	if (video_qmax != NO_VALUE) video_enc->qmax = video_qmax;
	if (video_qdiff != NO_VALUE) video_enc->max_qdiff = video_qdiff;
	if (video_i_qfactor != NO_VALUE) video_enc->b_quant_factor = video_i_qfactor;
	if (video_rc_eq) video_enc->rc_eq = av_strdup(video_rc_eq);
	if (video_qcomp != NO_VALUE) video_enc->qcompress = video_qcomp;
	if (video_me_range != NO_VALUE) video_enc->me_range = video_me_range;
	if (thread_count) video_enc->thread_count = thread_count;

	switch(video_enc->codec_id)
	{
	case CODEC_ID_MPEG2VIDEO:
		video_enc->max_b_frames = 2;
		break;

	case CODEC_ID_MPEG1VIDEO:
		video_enc->mb_decision = 2;
		break;
			
	default:
		break;
	}

	// some formats want stream headers to be separate
	if(oc->oformat->flags & AVFMT_GLOBALHEADER)
		video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;

	/* open the codec */
	if (avcodec_open2(video_enc, codec, &video_options) < 0)
	{
		av_log(NULL, AV_LOG_ERROR, "could not open video codec\n");
		return NULL;
	}

	if (oc->oformat->flags & AVFMT_RAWPICTURE)
	{
		av_log(NULL, AV_LOG_ERROR, "Raw Picture ?\n");
		return NULL;
	}

	video_outbuf_size = video_width * video_height * 16;
	if (video_outbuf_size < FF_MIN_BUFFER_SIZE) video_outbuf_size = FF_MIN_BUFFER_SIZE;
	video_outbuf = (uint8_t *)av_malloc(video_outbuf_size);

	return st;
}
Пример #24
0
int FFMPEG_Wrapper::init(int input_width,
                          int input_height,
                          const ServerConfiguration& config)
{
  boost::mutex::scoped_lock lock(frame_mutex_);

  time_started_ = boost::posix_time::microsec_clock::local_time();

  config_  = config;

  input_width_ = input_width;
  input_height_ = input_height;

  output_width_ = config.frame_width_;
  output_height_ = config.frame_height_;

  if (output_width_<0)
    output_width_ = input_width_;

  if (output_height_<0)
    output_height_ = input_height_;

  av_lockmgr_register(&ff_lockmgr);

  /* register all the codecs */
  avcodec_register_all();
  av_register_all();

  // lookup webm codec
  avformat_alloc_output_context2(&ffmpeg_format_context_, NULL, config_.codec_.c_str(), NULL);
  if (!ffmpeg_format_context_) {
    return -1;
  }

  ffmpeg_output_format_ = ffmpeg_format_context_->oformat;

  /* Add the audio and video streams using the default format codecs
   * and initialize the codecs. */
  ffmpeg_video_st_ = NULL;
  if (ffmpeg_output_format_->video_codec != AV_CODEC_ID_NONE)
  {

    /* find the video encoder */
    ffmpeg_codec_ = avcodec_find_encoder(ffmpeg_output_format_->video_codec);
    if (!(ffmpeg_codec_))
    {
      fprintf(stderr, "Codec not found (%s)\n",config_.codec_.c_str());
      return -1;
    }

    ffmpeg_video_st_ = avformat_new_stream(ffmpeg_format_context_, ffmpeg_codec_);
    if (!ffmpeg_video_st_)
    {
      fprintf(stderr, "Could not alloc stream\n");
      return -1;
    }

    ffmpeg_codec_context_ = ffmpeg_video_st_->codec;



    avcodec_get_context_defaults3(ffmpeg_codec_context_, ffmpeg_codec_);

    //////////////////////////////////////////////
    // ffmpeg codec configuration
    //////////////////////////////////////////////

    ffmpeg_codec_context_->codec_id = ffmpeg_output_format_->video_codec;
    ffmpeg_codec_context_->bit_rate = config_.bitrate_;

    ffmpeg_codec_context_->width = output_width_;
    ffmpeg_codec_context_->height = output_height_;
    ffmpeg_codec_context_->delay = 0;

    ffmpeg_codec_context_->time_base.den = config_.framerate_+3; //increased framerate to compensate playback delay
    ffmpeg_codec_context_->time_base.num = 1;
    ffmpeg_codec_context_->gop_size = config_.gop_; /* emit one intra ffmpeg_frame_ every twelve frames at most */
    ffmpeg_codec_context_->pix_fmt = PIX_FMT_YUV420P;
    ffmpeg_codec_context_->max_b_frames = 0;

    av_opt_set(ffmpeg_codec_context_->priv_data, "quality", config_.profile_.c_str(), 0);

    av_opt_set(ffmpeg_codec_context_->priv_data, "deadline", "1", 0);
    av_opt_set(ffmpeg_codec_context_->priv_data, "auto-alt-ref", "0", 0);

    // lag in frames
    av_opt_set(ffmpeg_codec_context_->priv_data, "lag-in-frames", "1", 0);
    av_opt_set(ffmpeg_codec_context_->priv_data, "rc_lookahead", "1", 0);

    av_opt_set(ffmpeg_codec_context_->priv_data, "drop_frame", "1", 0);

    // enable error-resilient coding
    av_opt_set(ffmpeg_codec_context_->priv_data, "error-resilient", "1", 0);

    // buffer size of rate controller (length: rc_buffer_size/bitrate * 1000) ms
    int bufsize = 10;//ffmpeg_codec_context_->bit_rate/10;
    ffmpeg_codec_context_->rc_buffer_size = bufsize;
    // prebuffering at decoder
    ffmpeg_codec_context_->rc_initial_buffer_occupancy = bufsize ;//bitrate/3;  

    av_opt_set_int(ffmpeg_codec_context_->priv_data, "bufsize", bufsize, 0);
    av_opt_set_int(ffmpeg_codec_context_->priv_data, "buf-initial", bufsize, 0);
    av_opt_set_int(ffmpeg_codec_context_->priv_data, "buf-optimal", bufsize, 0);

    // buffer agressivity
    ffmpeg_codec_context_->rc_buffer_aggressivity = 0.5;

    // Quality settings
    //ffmpeg_codec_context_->qmin = 50;
    //ffmpeg_codec_context_->qmax = 62;
    if (config_.quality_>0)
      ffmpeg_codec_context_->qmin = config_.quality_;

     //ffmpeg_codec_context_->frame_skip_threshold = 100;

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

  if (ffmpeg_video_st_)
  {
    int ret;

    /* open the codec */
      {
         boost::mutex::scoped_lock lock(codec_mutex_);
         if (avcodec_open2(ffmpeg_codec_context_, ffmpeg_codec_, NULL) < 0) {
             fprintf(stderr, "Could not open video codec\n");
             return -1;
         }
      }  

      /* allocate and init a re-usable ffmpeg_frame_ */
      ffmpeg_frame_ = avcodec_alloc_frame();
      if (!ffmpeg_frame_) {
          fprintf(stderr, "Could not allocate video ffmpeg_frame_\n");
          return -1;
      }

      /* Allocate the encoded raw picture. */
      ret = avpicture_alloc(ffmpeg_dst_picture_, ffmpeg_codec_context_->pix_fmt, output_width_, output_height_);
      if (ret < 0) {
          fprintf(stderr, "Could not allocate picture\n");
          return -1;
      }

      /* If the output format is not YUV420P, then a temporary YUV420P
       * picture is needed too. It is then converted to the required
       * output format. */
          ret = avpicture_alloc(ffmpeg_src_picture_, AV_PIX_FMT_RGB24, input_width_, input_height_);
          if (ret < 0) {
              fprintf(stderr, "Could not allocate temporary picture\n");
              return -1;
          }

      /* copy data and linesize picture pointers to ffmpeg_frame_ */
      *((AVPicture *)ffmpeg_frame_) = *ffmpeg_dst_picture_;

      av_dump_format(ffmpeg_format_context_, 0, "", 1);

      ffmpeg_output_format_->flags |= AVFMT_NOFILE;

      if (ffmpeg_frame_)
          ffmpeg_frame_->pts = 0;
  }

  init_ = true;

  return 0;
}
Пример #25
0
MediaRecorder::MediaRecorder(const char * outfile,int width, int height)
{
    audiofailed = false;
    /* INIT SOUND RECORDING */

    debug_samples_out = fopen("audiosamples.s16","wb");
    audio_samples_written = 0;
    pa_context* pactx;
    pa_mainloop * m = pa_mainloop_new();
    m_api = pa_mainloop_get_api(m);
    pactx = pa_context_new(m_api,"Rec1");
    if ( pa_context_connect(pactx,NULL,(pa_context_flags_t)0,NULL) < 0 )
        printf("Cannot connect to pulseaudio\n");
    int ret;
    pa_context_set_state_callback(pactx, context_state_callback, this);
    pa_mainloop_run(m,&ret);
    std::cout << "Use source: " << monitorsources[defaultsink] << std::endl;

    static const pa_sample_spec ss = {
        .format = PA_SAMPLE_S16LE,
        .rate = 44100,
        .channels = 2
    };
    pa_context_disconnect(pactx);

    int error;
    s = pa_simple_new(NULL,"GLCAP Record",PA_STREAM_RECORD,monitorsources[defaultsink].c_str(), "record", &ss, NULL,NULL , &error);
    if ( !s )
    {
        printf("Cannot create pa_simple\n");
    }

    run = true;
    ready = false;
    firstframe = true;
    this->width = width;
    this->height = height;
    pthread_mutex_init(&encode_mutex,NULL);
    pthread_mutex_init(&sound_buffer_lock,NULL);
    pthread_cond_init(&encode_cond,NULL);
    pthread_create(&encode_thread,NULL,(void*(*)(void*))&MediaRecorder::EncodingThread,this);


    av_log_set_level(AV_LOG_DEBUG);
    outCtx = avformat_alloc_context();

    outCtx->oformat = av_guess_format(NULL, outfile, NULL);
    snprintf(outCtx->filename, sizeof(outCtx->filename), "%s", outfile);
    codec = avcodec_find_encoder(AV_CODEC_ID_MPEG4);
    acodec = avcodec_find_encoder(AV_CODEC_ID_MP2);
    ctx = avcodec_alloc_context3(codec);
    actx = avcodec_alloc_context3(acodec);
    avcodec_get_context_defaults3(actx,acodec);
    avcodec_get_context_defaults3(ctx,codec);
    ctx->width = width;
    ctx->height = height;
    ctx->bit_rate = 6000*1000;
    
    std::cout << ctx->time_base.den << " " << ctx->time_base.num << std::endl;
    
    ctx->time_base.den = TIMEBASE;
    ctx->time_base.num = 1;

    ctx->thread_count = 4;
    ctx->qmin = 2;
    ctx->qmax = 31;
    ctx->b_sensitivity = 100;
    ctx->gop_size = 1;
    ctx->me_method = 1;
    ctx->global_quality = 100;
    ctx->lowres = 0;
    
    ctx->bit_rate_tolerance = 200000;
    actx->sample_fmt = AV_SAMPLE_FMT_S16;
    actx->sample_rate = 44100;
    actx->channels = 2;
    actx->time_base.den = 44100;
    actx->time_base.num = 1;
    actx->bit_rate = 128000;
    actx->frame_size = 8192;
    actx->channel_layout = 3;
    /* ctx->compression_level = 0;
     ctx->trellis = 0;
     ctx->gop_size = 1; /* emit one intra frame every ten frames */
    /*ctx->me_pre_cmp = 0;
    ctx->me_cmp = 0;
    ctx->me_sub_cmp = 0;
    ctx->mb_cmp = 2;
    ctx->pre_dia_size = 0;
    ctx->dia_size = 1;

    ctx->quantizer_noise_shaping = 0; // qns=0
    ctx->noise_reduction = 0; // nr=0
    ctx->mb_decision = 0; // mbd=0 ("realtime" encoding)

    ctx->flags &= ~CODEC_FLAG_QPEL;
    ctx->flags &= ~CODEC_FLAG_4MV;
    ctx->trellis = 0;
    ctx->flags &= ~CODEC_FLAG_CBP_RD;
    ctx->flags &= ~CODEC_FLAG_QP_RD;
    ctx->flags &= ~CODEC_FLAG_MV0;*/
    //ctx->s
    ctx->pix_fmt = PIX_FMT_YUV420P;



    if (avcodec_open2(ctx, codec, NULL) < 0) {
        fprintf(stderr, "Could not open codec\n");
    }
    if (avcodec_open2(actx, acodec, NULL) < 0) {
        fprintf(stderr, "Could not open audio codec\n");
        audiofailed = true;
    }
    printf("frame_size: %d\n",actx->frame_size);
    pthread_create(&record_sound_thread,NULL,(void*(*)(void*))&MediaRecorder::RecordingThread,this);
    AVStream* s = av_new_stream(outCtx,0);
    s->codec = ctx;
    s->r_frame_rate.den = TIMEBASE;
    s->r_frame_rate.num = 1;
    if (!audiofailed )
    {
    AVStream* as = av_new_stream(outCtx,1);
    as->codec = actx;
    as->r_frame_rate.den = 44100;
    as->r_frame_rate.num = 1;
    
    }
    picture = alloc_picture(PIX_FMT_YUV420P, ctx->width, ctx->height);
    if (!picture) {
        fprintf(stderr, "Could not allocate picture\n");
        exit(1);
    }
    tmp_picture = NULL;

    tmp_picture = alloc_picture(PIX_FMT_RGBA, ctx->width, ctx->height);
    if (!tmp_picture) {
        fprintf(stderr, "Could not allocate temporary picture\n");
        exit(1);
    }

    img_convert_ctx = sws_getContext(ctx->width, ctx->height,
                                     PIX_FMT_RGBA,
                                     ctx->width, ctx->height,
                                     PIX_FMT_YUV420P,
                                     SWS_FAST_BILINEAR , NULL, NULL, NULL);
    if (img_convert_ctx == NULL) {
        fprintf(stderr,
                "Cannot initialize the conversion context\n");
        exit(1);
    }
    av_dump_format(outCtx, 0, outfile, 1);
    avio_open2(&outCtx->pb, outfile, AVIO_FLAG_WRITE,NULL,NULL);
    avformat_write_header(outCtx,NULL);
}

MediaRecorder::~MediaRecorder()
{
    run = false;
    ready = false;
    pthread_cond_broadcast(&encode_cond);
    printf("Joining thread..\n");
    pthread_join(encode_thread,NULL);
    printf("Joining recording thread..\n");
    pthread_join(record_sound_thread,NULL);
    printf("Done\n");
    av_write_trailer(outCtx);
    av_free(picture);
    avformat_free_context(outCtx);
    pa_simple_free(s);
    fclose(debug_samples_out);
}
int fcount = 0;
void MediaRecorder::AppendFrame(float time, int width, int height, char* data)
{
    if ( !ready )
        return ;
    printf("AppendFrame\n");
    this->time = getcurrenttime2();
    if ( firstframe )
    {
        starttime = getcurrenttime2();
        firstframe = false;
    }
    this->height = height;
    this->width = width;
    m_data = data;
    ready = false;
    pthread_cond_broadcast(&encode_cond);
    
    /*int i = 0;
     unsigned int numpixels = width * height;
     unsigned int ui = numpixels;
     unsigned int vi = numpixels + numpixels / 4;
     for ( int j = 0; j < height; j++ )
     {
         for ( int k = 0; k < width; k++ )
         {
             int sR = data[i*4+0];
             int sG = data[i*4+1];
             int sB = data[i*4+2];
             picture->data[0][i] = ( (66*sR + 129*sG + 25*sB + 128) >> 8) + 16;
             if (0 == j%2 && 0 == k%2)
             {
                 picture->data[0][ui++] = ( (-38*sR - 74*sG + 112*sB + 128) >> 8) + 128;
                 picture->data[0][vi++] = ( (112*sR - 94*sG - 18*sB + 128) >> 8) + 128;
             }
             i++;

         }
     }*/


    // printf("End flip %f\n",(float)getcurrenttime2());

    //memcpy(tmp_picture->data[0],data,width*height*4);

}

void MediaRecorder::EncodingThread()
{
    while ( run )
    {
        printf("Encode thread ready\n");
        ready = true;
        pthread_cond_wait(&encode_cond,&encode_mutex);
        
        if (!run)
        {
            printf("Encoding finished\n");
            break;
        }
        for ( int y = 0; y < height; y++ )
        {
            /*for ( int x = 0; x < width; x++ )
            {*/
            char r,g,b;
            int oldindex = (y*width);
            int newindex = ((height-1-y)*width);
            memcpy(&tmp_picture->data[0][(newindex)*4],&m_data[oldindex*4],width*4);
            /* r = data[oldindex*4+0];
            g = data[oldindex*4+1];
            b = data[oldindex*4+2];
            tmp_picture->data[0][(newindex)*4+0] = r;
            tmp_picture->data[0][(newindex)*4+1] = g;
            tmp_picture->data[0][(newindex)*4+2] = b; */
            // }

        }
        sws_scale(img_convert_ctx,tmp_picture->data,tmp_picture->linesize,0,height,picture->data,picture->linesize);


        AVPacket p;

        av_init_packet(&p);
        p.data = NULL;
        p.size = 0;
        picture->pts = int64_t((time-starttime)*TIMEBASE);
        
        uint64_t vpts = picture->pts;
     
        // picture->pts = time*30.0;
        int got_frame;
        printf("%p %p\n",ctx, picture);
        if(avcodec_encode_video2(ctx, &p, picture, &got_frame) < 0) return;
        if(got_frame)
        {

            // outContainer is "mp4"

            p.pts = vpts;
            p.dts = AV_NOPTS_VALUE;
            av_write_frame(outCtx, &p);

            av_free_packet(&p);
        }
        //sleep(1);
        printf("End enc frame %f, pts %lld\n",(float)getcurrenttime2(),picture->pts);
        
       
        AVFrame * aframe = avcodec_alloc_frame();

        
        bool unlocked = false;
        
        while ( sound_buffers.size() > 0 )
        {
            uint64_t apts = audio_samples_written;
           /* if ( apts > vpts )
                break;*/
            pthread_mutex_lock(&sound_buffer_lock);
            short * buf = sound_buffers.front();
            sound_buffers.pop_front();
            pthread_mutex_unlock(&sound_buffer_lock);
             if (!audiofailed )
            {
                
                
                unlocked = true;
                aframe->nb_samples = actx->frame_size;
                aframe->channel_layout = actx->channel_layout;
                aframe->format = AV_SAMPLE_FMT_S16;
                aframe->channels = actx->channels;
                avcodec_fill_audio_frame(aframe,actx->channels,AV_SAMPLE_FMT_S16,(char*)buf,actx->frame_size*2*2,0);
              //  avcodec_fill_audio_frame(aframe,actx->channels,actx->sample_fmt,(char*)buf,actx->frame_size*2,0);
    
                printf("sound_buffers.size() = %d\n",sound_buffers.size());
                av_init_packet(&p);
                p.data = NULL;
                p.size = 0;

                
                avcodec_encode_audio2(actx,&p,aframe,&got_frame);
                if ( got_frame )
                {
                    p.stream_index = 1;
                    p.flags |= AV_PKT_FLAG_KEY;
                    
                    

                    av_write_frame(outCtx,&p);
                    av_free_packet(&p);
                }
                audio_samples_written += actx->frame_size;//samples/2 each channel
            }
            //printf("Consumed 1024 samples\n");
            delete[] buf;
            
        }
/*        if ( !unlocked )
            pthread_mutex_unlock(&sound_buffer_lock);*/
        avcodec_free_frame(&aframe);
        
    }
}

bool MediaRecorder::isReady()
{
    return ready;
}
Пример #26
0
// add a video output stream
static int AddVideoStream()
{
    g_pVStream = avformat_new_stream(g_pContainer, g_pVCodec);
    if (!g_pVStream)
        return FatalError("Could not allocate video stream");

    g_pVideo = g_pVStream->codec;

    avcodec_get_context_defaults3(g_pVideo, g_pVCodec);
    g_pVideo->codec_id = g_pVCodec->id;

    // put parameters
    // resolution must be a multiple of two
    g_pVideo->width  = g_Width  & ~1; // make even (dimensions should be even)
    g_pVideo->height = g_Height & ~1; // make even
    /* time base: this is the fundamental unit of time (in seconds) in terms
       of which frame timestamps are represented. for fixed-fps content,
       timebase should be 1/framerate and timestamp increments should be
       identically 1. */
    g_pVideo->time_base.den = g_pVStream->time_base.den = g_Framerate.num;
    g_pVideo->time_base.num = g_pVStream->time_base.num = g_Framerate.den;

    g_pVideo->pix_fmt = AV_PIX_FMT_YUV420P;

    // set quality
    if (g_VQuality > 100)
        g_pVideo->bit_rate = g_VQuality;
    else
    {
        g_pVideo->flags |= AV_CODEC_FLAG_QSCALE;
        g_pVideo->global_quality = g_VQuality*FF_QP2LAMBDA;
    }

    // some formats want stream headers to be separate
    if (g_pFormat->flags & AVFMT_GLOBALHEADER)
        g_pVideo->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

#if LIBAVCODEC_VERSION_MAJOR < 53
    // for some versions of ffmpeg x264 options must be set explicitly
    if (strcmp(g_pVCodec->name, "libx264") == 0)
    {
        g_pVideo->coder_type = FF_CODER_TYPE_AC;
        g_pVideo->flags |= CODEC_FLAG_LOOP_FILTER;
        g_pVideo->crf = 23;
        g_pVideo->thread_count = 3;
        g_pVideo->me_cmp = FF_CMP_CHROMA;
        g_pVideo->partitions = X264_PART_I8X8 | X264_PART_I4X4 | X264_PART_P8X8 | X264_PART_B8X8;
        g_pVideo->me_method = ME_HEX;
        g_pVideo->me_subpel_quality = 7;
        g_pVideo->me_range = 16;
        g_pVideo->gop_size = 250;
        g_pVideo->keyint_min = 25;
        g_pVideo->scenechange_threshold = 40;
        g_pVideo->i_quant_factor = 0.71;
        g_pVideo->b_frame_strategy = 1;
        g_pVideo->qcompress = 0.6;
        g_pVideo->qmin = 10;
        g_pVideo->qmax = 51;
        g_pVideo->max_qdiff = 4;
        g_pVideo->max_b_frames = 3;
        g_pVideo->refs = 3;
        g_pVideo->directpred = 1;
        g_pVideo->trellis = 1;
        g_pVideo->flags2 = CODEC_FLAG2_BPYRAMID | CODEC_FLAG2_MIXED_REFS | CODEC_FLAG2_WPRED | CODEC_FLAG2_8X8DCT | CODEC_FLAG2_FASTPSKIP;
        g_pVideo->weighted_p_pred = 2;
    }
#endif

    // open the codec
    if (avcodec_open2(g_pVideo, g_pVCodec, NULL) < 0)
        return FatalError("Could not open video codec %s", g_pVCodec->long_name);

    g_pVFrame = av_frame_alloc();
    if (!g_pVFrame)
        return FatalError("Could not allocate frame");

    g_pVFrame->width = g_Width;
    g_pVFrame->height = g_Height;
    g_pVFrame->format = AV_PIX_FMT_YUV420P;
    g_pVFrame->linesize[0] = g_Width;
    g_pVFrame->linesize[1] = g_Width/2;
    g_pVFrame->linesize[2] = g_Width/2;
    g_pVFrame->linesize[3] = 0;
    return 0;
}
Пример #27
0
void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType codec_type){
  AVCodec c= {0};
  c.type= codec_type;
  avcodec_get_context_defaults3(s, &c);
}
Пример #28
0
/**********************************************************************
 * avformatInit
 **********************************************************************
 * Allocates hb_mux_data_t structures, create file and write headers
 *********************************************************************/
static int avformatInit( hb_mux_object_t * m )
{
    hb_job_t   * job   = m->job;
    hb_audio_t    * audio;
    hb_mux_data_t * track;
    int meta_mux;
    int max_tracks;
    int ii, ret;

    const char *muxer_name = NULL;

    uint8_t         default_track_flag = 1;
    uint8_t         need_fonts = 0;
    char *lang;


    m->delay = -1;
    max_tracks = 1 + hb_list_count( job->list_audio ) +
                     hb_list_count( job->list_subtitle );

    m->tracks = calloc(max_tracks, sizeof(hb_mux_data_t*));

    m->oc = avformat_alloc_context();
    if (m->oc == NULL)
    {
        hb_error( "Could not initialize avformat context." );
        goto error;
    }

    switch (job->mux)
    {
        case HB_MUX_AV_MP4:
            m->time_base.num = 1;
            m->time_base.den = 90000;
            if( job->ipod_atom )
                muxer_name = "ipod";
            else
                muxer_name = "mp4";
            meta_mux = META_MUX_MP4;
            break;

        case HB_MUX_AV_MKV:
            // libavformat is essentially hard coded such that it only
            // works with a timebase of 1/1000
            m->time_base.num = 1;
            m->time_base.den = 1000;
            muxer_name = "matroska";
            meta_mux = META_MUX_MKV;
            break;

        default:
        {
            hb_error("Invalid Mux %x", job->mux);
            goto error;
        }
    }
    m->oc->oformat = av_guess_format(muxer_name, NULL, NULL);
    if(m->oc->oformat == NULL)
    {
        hb_error("Could not guess output format %s", muxer_name);
        goto error;
    }
    av_strlcpy(m->oc->filename, job->file, sizeof(m->oc->filename));
    ret = avio_open2(&m->oc->pb, job->file, AVIO_FLAG_WRITE,
                     &m->oc->interrupt_callback, NULL);
    if( ret < 0 )
    {
        hb_error( "avio_open2 failed, errno %d", ret);
        goto error;
    }

    /* Video track */
    track = m->tracks[m->ntracks++] = calloc(1, sizeof( hb_mux_data_t ) );
    job->mux_data = track;

    track->type = MUX_TYPE_VIDEO;
    track->st = avformat_new_stream(m->oc, NULL);
    if (track->st == NULL)
    {
        hb_error("Could not initialize video stream");
        goto error;
    }
    track->st->time_base = m->time_base;
    avcodec_get_context_defaults3(track->st->codec, NULL);

    track->st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
    track->st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;

    uint8_t *priv_data = NULL;
    int priv_size = 0;
    switch (job->vcodec)
    {
        case HB_VCODEC_X264:
        case HB_VCODEC_QSV_H264:
            track->st->codec->codec_id = AV_CODEC_ID_H264;

            /* Taken from x264 muxers.c */
            priv_size = 5 + 1 + 2 + job->config.h264.sps_length + 1 + 2 +
                        job->config.h264.pps_length;
            priv_data = av_malloc(priv_size);
            if (priv_data == NULL)
            {
                hb_error("malloc failure");
                goto error;
            }

            priv_data[0] = 1;
            priv_data[1] = job->config.h264.sps[1]; /* AVCProfileIndication */
            priv_data[2] = job->config.h264.sps[2]; /* profile_compat */
            priv_data[3] = job->config.h264.sps[3]; /* AVCLevelIndication */
            priv_data[4] = 0xff; // nalu size length is four bytes
            priv_data[5] = 0xe1; // one sps

            priv_data[6] = job->config.h264.sps_length >> 8;
            priv_data[7] = job->config.h264.sps_length;

            memcpy(priv_data+8, job->config.h264.sps,
                   job->config.h264.sps_length);

            priv_data[8+job->config.h264.sps_length] = 1; // one pps
            priv_data[9+job->config.h264.sps_length] =
                                        job->config.h264.pps_length >> 8;
            priv_data[10+job->config.h264.sps_length] =
                                        job->config.h264.pps_length;

            memcpy(priv_data+11+job->config.h264.sps_length,
                   job->config.h264.pps, job->config.h264.pps_length );
            break;

        case HB_VCODEC_FFMPEG_MPEG4:
            track->st->codec->codec_id = AV_CODEC_ID_MPEG4;

            if (job->config.mpeg4.length != 0)
            {
                priv_size = job->config.mpeg4.length;
                priv_data = av_malloc(priv_size);
                if (priv_data == NULL)
                {
                    hb_error("malloc failure");
                    goto error;
                }
                memcpy(priv_data, job->config.mpeg4.bytes, priv_size);
            }
            break;

        case HB_VCODEC_FFMPEG_MPEG2:
            track->st->codec->codec_id = AV_CODEC_ID_MPEG2VIDEO;

            if (job->config.mpeg4.length != 0)
            {
                priv_size = job->config.mpeg4.length;
                priv_data = av_malloc(priv_size);
                if (priv_data == NULL)
                {
                    hb_error("malloc failure");
                    goto error;
                }
                memcpy(priv_data, job->config.mpeg4.bytes, priv_size);
            }
            break;

        case HB_VCODEC_THEORA:
        {
            track->st->codec->codec_id = AV_CODEC_ID_THEORA;

            int size = 0;
            ogg_packet *ogg_headers[3];

            for (ii = 0; ii < 3; ii++)
            {
                ogg_headers[ii] = (ogg_packet *)job->config.theora.headers[ii];
                size += ogg_headers[ii]->bytes + 2;
            }

            priv_size = size;
            priv_data = av_malloc(priv_size);
            if (priv_data == NULL)
            {
                hb_error("malloc failure");
                goto error;
            }

            size = 0;
            for(ii = 0; ii < 3; ii++)
            {
                AV_WB16(priv_data + size, ogg_headers[ii]->bytes);
                size += 2;
                memcpy(priv_data+size, ogg_headers[ii]->packet,
                                       ogg_headers[ii]->bytes);
                size += ogg_headers[ii]->bytes;
            }
        } break;

        default:
            hb_error("muxavformat: Unknown video codec: %x", job->vcodec);
            goto error;
    }
    track->st->codec->extradata = priv_data;
    track->st->codec->extradata_size = priv_size;

    if (job->anamorphic.mode > 0)
    {
        track->st->sample_aspect_ratio.num        = job->anamorphic.par_width;
        track->st->sample_aspect_ratio.den        = job->anamorphic.par_height;
        track->st->codec->sample_aspect_ratio.num = job->anamorphic.par_width;
        track->st->codec->sample_aspect_ratio.den = job->anamorphic.par_height;
    }
    else
    {
        track->st->sample_aspect_ratio.num        = 1;
        track->st->sample_aspect_ratio.den        = 1;
        track->st->codec->sample_aspect_ratio.num = 1;
        track->st->codec->sample_aspect_ratio.den = 1;
    }
    track->st->codec->width = job->width;
    track->st->codec->height = job->height;
    track->st->disposition |= AV_DISPOSITION_DEFAULT;

    int vrate_base, vrate;
    if( job->pass == 2 )
    {
        hb_interjob_t * interjob = hb_interjob_get( job->h );
        vrate_base = interjob->vrate_base;
        vrate = interjob->vrate;
    }
    else
    {
        vrate_base = job->vrate_base;
        vrate = job->vrate;
    }

    // If the vrate is 27000000, there's a good chance this is
    // a standard rate that we have in our hb_video_rates table.
    // Because of rounding errors and approximations made while
    // measuring framerate, the actual value may not be exact.  So
    // we look for rates that are "close" and make an adjustment
    // to fps.den.
    if (vrate == 27000000)
    {
        const hb_rate_t *video_framerate = NULL;
        while ((video_framerate = hb_video_framerate_get_next(video_framerate)) != NULL)
        {
            if (abs(vrate_base - video_framerate->rate) < 10)
            {
                vrate_base = video_framerate->rate;
                break;
            }
        }
    }
    hb_reduce(&vrate_base, &vrate, vrate_base, vrate);
    if (job->mux == HB_MUX_AV_MP4)
    {
        // libavformat mp4 muxer requires that the codec time_base have the
        // same denominator as the stream time_base, it uses it for the
        // mdhd timescale.
        double scale = (double)track->st->time_base.den / vrate;
        track->st->codec->time_base.den = track->st->time_base.den;
        track->st->codec->time_base.num = vrate_base * scale;
    }
    else
    {
        track->st->codec->time_base.num = vrate_base;
        track->st->codec->time_base.den = vrate;
    }

    /* add the audio tracks */
    for(ii = 0; ii < hb_list_count( job->list_audio ); ii++ )
    {
        audio = hb_list_item( job->list_audio, ii );
        track = m->tracks[m->ntracks++] = calloc(1, sizeof( hb_mux_data_t ) );
        audio->priv.mux_data = track;

        track->type = MUX_TYPE_AUDIO;

        track->st = avformat_new_stream(m->oc, NULL);
        if (track->st == NULL)
        {
            hb_error("Could not initialize audio stream");
            goto error;
        }
        avcodec_get_context_defaults3(track->st->codec, NULL);

        track->st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
        track->st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
        if (job->mux == HB_MUX_AV_MP4)
        {
            track->st->codec->time_base.num = audio->config.out.samples_per_frame;
            track->st->codec->time_base.den = audio->config.out.samplerate;
            track->st->time_base.num = 1;
            track->st->time_base.den = audio->config.out.samplerate;
        }
        else
        {
            track->st->codec->time_base = m->time_base;
        }

        priv_data = NULL;
        priv_size = 0;
        switch (audio->config.out.codec & HB_ACODEC_MASK)
        {
            case HB_ACODEC_DCA:
            case HB_ACODEC_DCA_HD:
                track->st->codec->codec_id = AV_CODEC_ID_DTS;
                break;
            case HB_ACODEC_AC3:
                track->st->codec->codec_id = AV_CODEC_ID_AC3;
                break;
            case HB_ACODEC_LAME:
            case HB_ACODEC_MP3:
                track->st->codec->codec_id = AV_CODEC_ID_MP3;
                break;
            case HB_ACODEC_VORBIS:
            {
                track->st->codec->codec_id = AV_CODEC_ID_VORBIS;

                int jj, size = 0;
                ogg_packet *ogg_headers[3];

                for (jj = 0; jj < 3; jj++)
                {
                    ogg_headers[jj] = (ogg_packet *)audio->priv.config.vorbis.headers[jj];
                    size += ogg_headers[jj]->bytes + 2;
                }

                priv_size = size;
                priv_data = av_malloc(priv_size);
                if (priv_data == NULL)
                {
                    hb_error("malloc failure");
                    goto error;
                }

                size = 0;
                for(jj = 0; jj < 3; jj++)
                {
                    AV_WB16(priv_data + size, ogg_headers[jj]->bytes);
                    size += 2;
                    memcpy(priv_data+size, ogg_headers[jj]->packet,
                                           ogg_headers[jj]->bytes);
                    size += ogg_headers[jj]->bytes;
                }
            } break;
            case HB_ACODEC_FFFLAC:
            case HB_ACODEC_FFFLAC24:
                track->st->codec->codec_id = AV_CODEC_ID_FLAC;

                if (audio->priv.config.extradata.bytes)
                {
                    priv_size = audio->priv.config.extradata.length;
                    priv_data = av_malloc(priv_size);
                    if (priv_data == NULL)
                    {
                        hb_error("malloc failure");
                        goto error;
                    }
                    memcpy(priv_data,
                           audio->priv.config.extradata.bytes,
                           audio->priv.config.extradata.length);
                }
                break;
            case HB_ACODEC_FAAC:
            case HB_ACODEC_FFAAC:
            case HB_ACODEC_CA_AAC:
            case HB_ACODEC_CA_HAAC:
            case HB_ACODEC_FDK_AAC:
            case HB_ACODEC_FDK_HAAC:
                track->st->codec->codec_id = AV_CODEC_ID_AAC;

                if (audio->priv.config.extradata.bytes)
                {
                    priv_size = audio->priv.config.extradata.length;
                    priv_data = av_malloc(priv_size);
                    if (priv_data == NULL)
                    {
                        hb_error("malloc failure");
                        goto error;
                    }
                    memcpy(priv_data,
                           audio->priv.config.extradata.bytes,
                           audio->priv.config.extradata.length);
                }
                break;
            default:
                hb_error("muxavformat: Unknown audio codec: %x",
                         audio->config.out.codec);
                goto error;
        }
        track->st->codec->extradata = priv_data;
        track->st->codec->extradata_size = priv_size;

        if( default_track_flag )
        {
            track->st->disposition |= AV_DISPOSITION_DEFAULT;
            default_track_flag = 0;
        }

        lang = lookup_lang_code(job->mux, audio->config.lang.iso639_2 );
        if (lang != NULL)
        {
            av_dict_set(&track->st->metadata, "language", lang, 0);
        }
        track->st->codec->sample_rate = audio->config.out.samplerate;
        if (audio->config.out.codec & HB_ACODEC_PASS_FLAG)
        {
            track->st->codec->channels = av_get_channel_layout_nb_channels(audio->config.in.channel_layout);
            track->st->codec->channel_layout = audio->config.in.channel_layout;
        }
        else
        {
            track->st->codec->channels = hb_mixdown_get_discrete_channel_count(audio->config.out.mixdown);
            track->st->codec->channel_layout = hb_ff_mixdown_xlat(audio->config.out.mixdown, NULL);
        }

        char *name;
        if (audio->config.out.name == NULL)
        {
            switch (track->st->codec->channels)
            {
                case 1:
                    name = "Mono";
                    break;

                case 2:
                    name = "Stereo";
                    break;

                default:
                    name = "Surround";
                    break;
            }
        }
        else
        {
            name = audio->config.out.name;
        }
        av_dict_set(&track->st->metadata, "title", name, 0);
    }

    char * subidx_fmt =
        "size: %dx%d\n"
        "org: %d, %d\n"
        "scale: 100%%, 100%%\n"
        "alpha: 100%%\n"
        "smooth: OFF\n"
        "fadein/out: 50, 50\n"
        "align: OFF at LEFT TOP\n"
        "time offset: 0\n"
        "forced subs: %s\n"
        "palette: %06x, %06x, %06x, %06x, %06x, %06x, "
        "%06x, %06x, %06x, %06x, %06x, %06x, %06x, %06x, %06x, %06x\n"
        "custom colors: OFF, tridx: 0000, "
        "colors: 000000, 000000, 000000, 000000\n";

    int subtitle_default = -1;
    for( ii = 0; ii < hb_list_count( job->list_subtitle ); ii++ )
    {
        hb_subtitle_t *subtitle = hb_list_item( job->list_subtitle, ii );

        if( subtitle->config.dest == PASSTHRUSUB )
        {
            if ( subtitle->config.default_track )
                subtitle_default = ii;
        }
    }
    // Quicktime requires that at least one subtitle is enabled,
    // else it doesn't show any of the subtitles.
    // So check to see if any of the subtitles are flagged to be
    // the defualt.  The default will the the enabled track, else
    // enable the first track.
    if (job->mux == HB_MUX_AV_MP4 && subtitle_default == -1)
    {
        subtitle_default = 0;
    }

    for( ii = 0; ii < hb_list_count( job->list_subtitle ); ii++ )
    {
        hb_subtitle_t * subtitle;
        uint32_t        rgb[16];
        char            subidx[2048];
        int             len;

        subtitle = hb_list_item( job->list_subtitle, ii );
        if (subtitle->config.dest != PASSTHRUSUB)
            continue;

        track = m->tracks[m->ntracks++] = calloc(1, sizeof( hb_mux_data_t ) );
        subtitle->mux_data = track;

        track->type = MUX_TYPE_SUBTITLE;
        track->st = avformat_new_stream(m->oc, NULL);
        if (track->st == NULL)
        {
            hb_error("Could not initialize subtitle stream");
            goto error;
        }
        avcodec_get_context_defaults3(track->st->codec, NULL);

        track->st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
        track->st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
        track->st->time_base = m->time_base;
        track->st->codec->time_base = m->time_base;
        track->st->codec->width = subtitle->width;
        track->st->codec->height = subtitle->height;

        priv_data = NULL;
        priv_size = 0;
        switch (subtitle->source)
        {
            case VOBSUB:
            {
                int jj;
                track->st->codec->codec_id = AV_CODEC_ID_DVD_SUBTITLE;

                for (jj = 0; jj < 16; jj++)
                    rgb[jj] = hb_yuv2rgb(subtitle->palette[jj]);
                len = snprintf(subidx, 2048, subidx_fmt,
                        subtitle->width, subtitle->height,
                        0, 0, "OFF",
                        rgb[0], rgb[1], rgb[2], rgb[3],
                        rgb[4], rgb[5], rgb[6], rgb[7],
                        rgb[8], rgb[9], rgb[10], rgb[11],
                        rgb[12], rgb[13], rgb[14], rgb[15]);

                priv_size = len + 1;
                priv_data = av_malloc(priv_size);
                if (priv_data == NULL)
                {
                    hb_error("malloc failure");
                    goto error;
                }
                memcpy(priv_data, subidx, priv_size);
            } break;

            case PGSSUB:
            {
                track->st->codec->codec_id = AV_CODEC_ID_HDMV_PGS_SUBTITLE;
            } break;

            case SSASUB:
            {
                if (job->mux == HB_MUX_AV_MP4)
                {
                    track->st->codec->codec_id = AV_CODEC_ID_MOV_TEXT;
                }
                else
                {
                    track->st->codec->codec_id = AV_CODEC_ID_SSA;
                    need_fonts = 1;

                    if (subtitle->extradata_size)
                    {
                        priv_size = subtitle->extradata_size;
                        priv_data = av_malloc(priv_size);
                        if (priv_data == NULL)
                        {
                            hb_error("malloc failure");
                            goto error;
                        }
                        memcpy(priv_data, subtitle->extradata, priv_size);
                    }
                }
            } break;

            case CC608SUB:
            case CC708SUB:
            case UTF8SUB:
            case TX3GSUB:
            case SRTSUB:
            {
                if (job->mux == HB_MUX_AV_MP4)
                    track->st->codec->codec_id = AV_CODEC_ID_MOV_TEXT;
                else
                    track->st->codec->codec_id = AV_CODEC_ID_TEXT;
            } break;

            default:
                continue;
        }
        if (track->st->codec->codec_id == AV_CODEC_ID_MOV_TEXT)
        {
            // Build codec extradata for tx3g.
            // If we were using a libav codec to generate this data
            // this would (or should) be done for us.
            uint8_t properties[] = {
                0x00, 0x00, 0x00, 0x00,     // Display Flags
                0x01,                       // Horiz. Justification
                0xff,                       // Vert. Justification
                0x00, 0x00, 0x00, 0xff,     // Bg color
                0x00, 0x00, 0x00, 0x00,     // Default text box
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,     // Reserved
                0x00, 0x01,                 // Font ID
                0x00,                       // Font face
                0x18,                       // Font size
                0xff, 0xff, 0xff, 0xff,     // Fg color
                // Font table:
                0x00, 0x00, 0x00, 0x12,     // Font table size
                'f','t','a','b',            // Tag
                0x00, 0x01,                 // Count
                0x00, 0x01,                 // Font ID
                0x05,                       // Font name length
                'A','r','i','a','l'         // Font name
            };

            int width, height = 60;
            if (job->anamorphic.mode)
                width = job->width * ((float)job->anamorphic.par_width / job->anamorphic.par_height);
            else
                width = job->width;
            track->st->codec->width = width;
            track->st->codec->height = height;
            properties[14] = height >> 8;
            properties[15] = height & 0xff;
            properties[16] = width >> 8;
            properties[17] = width & 0xff;

            priv_size = sizeof(properties);
            priv_data = av_malloc(priv_size);
            if (priv_data == NULL)
            {
                hb_error("malloc failure");
                goto error;
            }
            memcpy(priv_data, properties, priv_size);
        }
        track->st->codec->extradata = priv_data;
        track->st->codec->extradata_size = priv_size;

        if ( ii == subtitle_default )
        {
            track->st->disposition |= AV_DISPOSITION_DEFAULT;
        }

        lang = lookup_lang_code(job->mux, subtitle->iso639_2 );
        if (lang != NULL)
        {
            av_dict_set(&track->st->metadata, "language", lang, 0);
        }
    }
Пример #29
0
AVStream* AVFormatWriter::AddVideoStream(void)
{
    AVCodecContext *c;
    AVStream *st;
    AVCodec *codec;

    st = avformat_new_stream(m_ctx, NULL);
    if (!st)
    {
        LOG(VB_RECORD, LOG_ERR,
            LOC + "AddVideoStream(): avformat_new_stream() failed");
        return NULL;
    }
    st->id = 0;

    c = st->codec;

    codec = avcodec_find_encoder(m_ctx->oformat->video_codec);
    if (!codec)
    {
        LOG(VB_RECORD, LOG_ERR,
            LOC + "AddVideoStream(): avcodec_find_encoder() failed");
        return false;
    }

    avcodec_get_context_defaults3(c, codec);

    c->codec                      = codec;
    c->codec_id                   = m_ctx->oformat->video_codec;
    c->codec_type                 = AVMEDIA_TYPE_VIDEO;

    c->bit_rate                   = m_videoBitrate;
    c->width                      = m_width;
    c->height                     = m_height;

    // c->sample_aspect_ratio.num    = (int)floor(m_aspect * 10000);
    // c->sample_aspect_ratio.den    = 10000;

    c->time_base                  = GetCodecTimeBase();

    st->time_base.den             = 90000;
    st->time_base.num             = 1;
    st->r_frame_rate.num          = 0;
    st->r_frame_rate.den          = 0;

    c->gop_size                   = m_keyFrameDist;
    c->pix_fmt                    = PIX_FMT_YUV420P;
    c->thread_count               = m_encodingThreadCount;
    c->thread_type                = FF_THREAD_SLICE;

    if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
        c->max_b_frames          = 2;
    }
    else if (c->codec_id == CODEC_ID_MPEG1VIDEO)
    {
        c->mb_decision           = 2;
    }
    else if (c->codec_id == CODEC_ID_H264)
    {

        if ((c->width > 480) ||
            (c->bit_rate > 600000))
        {
            c->level = 31;
            av_opt_set(c->priv_data, "profile", "main", 0);
        }
        else
        {
            c->level = 30;
            av_opt_set(c->priv_data, "profile", "baseline", 0);
        }

        c->coder_type            = 0;
        c->max_b_frames          = 0;
        c->slices                = 8;

        c->flags                |= CODEC_FLAG_LOOP_FILTER;
        c->me_cmp               |= 1;
        c->me_method             = ME_HEX;
        c->me_subpel_quality     = 6;
        c->me_range              = 16;
        c->keyint_min            = 25;
        c->scenechange_threshold = 40;
        c->i_quant_factor        = 0.71;
        c->b_frame_strategy      = 1;
        c->qcompress             = 0.6;
        c->qmin                  = 10;
        c->qmax                  = 51;
        c->max_qdiff             = 4;
        c->refs                  = 3;
        c->trellis               = 0;

        av_opt_set(c, "partitions", "i8x8,i4x4,p8x8,b8x8", 0);
        av_opt_set_int(c, "direct-pred", 1, 0);
        av_opt_set_int(c, "rc-lookahead", 0, 0);
        av_opt_set_int(c, "fast-pskip", 1, 0);
        av_opt_set_int(c, "mixed-refs", 1, 0);
        av_opt_set_int(c, "8x8dct", 0, 0);
        av_opt_set_int(c, "weightb", 0, 0);
    }

    if(m_ctx->oformat->flags & AVFMT_GLOBALHEADER)
        c->flags |= CODEC_FLAG_GLOBAL_HEADER;

    return st;
}
Пример #30
0
/**********************************************************************
 * avformatInit
 **********************************************************************
 * Allocates hb_mux_data_t structures, create file and write headers
 *********************************************************************/
static int avformatInit( hb_mux_object_t * m )
{
    hb_job_t   * job   = m->job;
    hb_audio_t    * audio;
    hb_mux_data_t * track;
    int meta_mux;
    int max_tracks;
    int ii, jj, ret;

    int clock_min, clock_max, clock;
    hb_video_framerate_get_limits(&clock_min, &clock_max, &clock);

    const char *muxer_name = NULL;

    uint8_t         default_track_flag = 1;
    uint8_t         need_fonts = 0;
    char *lang;


    max_tracks = 1 + hb_list_count( job->list_audio ) +
                     hb_list_count( job->list_subtitle );

    m->tracks = calloc(max_tracks, sizeof(hb_mux_data_t*));

    m->oc = avformat_alloc_context();
    if (m->oc == NULL)
    {
        hb_error( "Could not initialize avformat context." );
        goto error;
    }

    AVDictionary * av_opts = NULL;
    switch (job->mux)
    {
        case HB_MUX_AV_MP4:
            m->time_base.num = 1;
            m->time_base.den = 90000;
            if( job->ipod_atom )
                muxer_name = "ipod";
            else
                muxer_name = "mp4";
            meta_mux = META_MUX_MP4;

            av_dict_set(&av_opts, "brand", "mp42", 0);
            if (job->mp4_optimize)
                av_dict_set(&av_opts, "movflags", "faststart+disable_chpl", 0);
            else
                av_dict_set(&av_opts, "movflags", "+disable_chpl", 0);
            break;

        case HB_MUX_AV_MKV:
            // libavformat is essentially hard coded such that it only
            // works with a timebase of 1/1000
            m->time_base.num = 1;
            m->time_base.den = 1000;
            muxer_name = "matroska";
            meta_mux = META_MUX_MKV;
            break;

        default:
        {
            hb_error("Invalid Mux %x", job->mux);
            goto error;
        }
    }
    m->oc->oformat = av_guess_format(muxer_name, NULL, NULL);
    if(m->oc->oformat == NULL)
    {
        hb_error("Could not guess output format %s", muxer_name);
        goto error;
    }
    av_strlcpy(m->oc->filename, job->file, sizeof(m->oc->filename));
    ret = avio_open2(&m->oc->pb, job->file, AVIO_FLAG_WRITE,
                     &m->oc->interrupt_callback, NULL);
    if( ret < 0 )
    {
        hb_error( "avio_open2 failed, errno %d", ret);
        goto error;
    }

    /* Video track */
    track = m->tracks[m->ntracks++] = calloc(1, sizeof( hb_mux_data_t ) );
    job->mux_data = track;

    track->type = MUX_TYPE_VIDEO;
    track->prev_chapter_tc = AV_NOPTS_VALUE;
    track->st = avformat_new_stream(m->oc, NULL);
    if (track->st == NULL)
    {
        hb_error("Could not initialize video stream");
        goto error;
    }
    track->st->time_base = m->time_base;
    avcodec_get_context_defaults3(track->st->codec, NULL);

    track->st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
    track->st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;

    uint8_t *priv_data = NULL;
    int priv_size = 0;
    switch (job->vcodec)
    {
        case HB_VCODEC_X264_8BIT:
        case HB_VCODEC_X264_10BIT:
        case HB_VCODEC_QSV_H264:
            track->st->codec->codec_id = AV_CODEC_ID_H264;

            /* Taken from x264 muxers.c */
            priv_size = 5 + 1 + 2 + job->config.h264.sps_length + 1 + 2 +
                        job->config.h264.pps_length;
            priv_data = av_malloc(priv_size + FF_INPUT_BUFFER_PADDING_SIZE);
            if (priv_data == NULL)
            {
                hb_error("H.264 extradata: malloc failure");
                goto error;
            }

            priv_data[0] = 1;
            priv_data[1] = job->config.h264.sps[1]; /* AVCProfileIndication */
            priv_data[2] = job->config.h264.sps[2]; /* profile_compat */
            priv_data[3] = job->config.h264.sps[3]; /* AVCLevelIndication */
            priv_data[4] = 0xff; // nalu size length is four bytes
            priv_data[5] = 0xe1; // one sps

            priv_data[6] = job->config.h264.sps_length >> 8;
            priv_data[7] = job->config.h264.sps_length;

            memcpy(priv_data+8, job->config.h264.sps,
                   job->config.h264.sps_length);

            priv_data[8+job->config.h264.sps_length] = 1; // one pps
            priv_data[9+job->config.h264.sps_length] =
                                        job->config.h264.pps_length >> 8;
            priv_data[10+job->config.h264.sps_length] =
                                        job->config.h264.pps_length;

            memcpy(priv_data+11+job->config.h264.sps_length,
                   job->config.h264.pps, job->config.h264.pps_length );
            break;

        case HB_VCODEC_FFMPEG_MPEG4:
            track->st->codec->codec_id = AV_CODEC_ID_MPEG4;

            if (job->config.mpeg4.length != 0)
            {
                priv_size = job->config.mpeg4.length;
                priv_data = av_malloc(priv_size + FF_INPUT_BUFFER_PADDING_SIZE);
                if (priv_data == NULL)
                {
                    hb_error("MPEG4 extradata: malloc failure");
                    goto error;
                }
                memcpy(priv_data, job->config.mpeg4.bytes, priv_size);
            }
            break;

        case HB_VCODEC_FFMPEG_MPEG2:
            track->st->codec->codec_id = AV_CODEC_ID_MPEG2VIDEO;

            if (job->config.mpeg4.length != 0)
            {
                priv_size = job->config.mpeg4.length;
                priv_data = av_malloc(priv_size + FF_INPUT_BUFFER_PADDING_SIZE);
                if (priv_data == NULL)
                {
                    hb_error("MPEG2 extradata: malloc failure");
                    goto error;
                }
                memcpy(priv_data, job->config.mpeg4.bytes, priv_size);
            }
            break;

        case HB_VCODEC_FFMPEG_VP8:
            track->st->codec->codec_id = AV_CODEC_ID_VP8;
            priv_data                  = NULL;
            priv_size                  = 0;
            break;

        case HB_VCODEC_FFMPEG_VP9:
            track->st->codec->codec_id = AV_CODEC_ID_VP9;
            priv_data                  = NULL;
            priv_size                  = 0;
            break;

        case HB_VCODEC_THEORA:
        {
            track->st->codec->codec_id = AV_CODEC_ID_THEORA;

            int size = 0;
            ogg_packet *ogg_headers[3];

            for (ii = 0; ii < 3; ii++)
            {
                ogg_headers[ii] = (ogg_packet *)job->config.theora.headers[ii];
                size += ogg_headers[ii]->bytes + 2;
            }

            priv_size = size;
            priv_data = av_malloc(priv_size + FF_INPUT_BUFFER_PADDING_SIZE);
            if (priv_data == NULL)
            {
                hb_error("Theora extradata: malloc failure");
                goto error;
            }

            size = 0;
            for(ii = 0; ii < 3; ii++)
            {
                AV_WB16(priv_data + size, ogg_headers[ii]->bytes);
                size += 2;
                memcpy(priv_data+size, ogg_headers[ii]->packet,
                                       ogg_headers[ii]->bytes);
                size += ogg_headers[ii]->bytes;
            }
        } break;

        case HB_VCODEC_X265_8BIT:
        case HB_VCODEC_X265_10BIT:
        case HB_VCODEC_X265_12BIT:
        case HB_VCODEC_X265_16BIT:
        case HB_VCODEC_QSV_H265:
            track->st->codec->codec_id = AV_CODEC_ID_HEVC;

            if (job->config.h265.headers_length > 0)
            {
                priv_size = job->config.h265.headers_length;
                priv_data = av_malloc(priv_size + FF_INPUT_BUFFER_PADDING_SIZE);
                if (priv_data == NULL)
                {
                    hb_error("H.265 extradata: malloc failure");
                    goto error;
                }
                memcpy(priv_data, job->config.h265.headers, priv_size);
            }
            break;

        default:
            hb_error("muxavformat: Unknown video codec: %x", job->vcodec);
            goto error;
    }
    track->st->codec->extradata = priv_data;
    track->st->codec->extradata_size = priv_size;

    track->st->sample_aspect_ratio.num        = job->par.num;
    track->st->sample_aspect_ratio.den        = job->par.den;
    track->st->codec->sample_aspect_ratio.num = job->par.num;
    track->st->codec->sample_aspect_ratio.den = job->par.den;
    track->st->codec->width                   = job->width;
    track->st->codec->height                  = job->height;
    track->st->disposition |= AV_DISPOSITION_DEFAULT;

    hb_rational_t vrate = job->vrate;

    // If the vrate is the internal clock rate, there's a good chance
    // this is a standard rate that we have in our hb_video_rates table.
    // Because of rounding errors and approximations made while
    // measuring framerate, the actual value may not be exact.  So
    // we look for rates that are "close" and make an adjustment
    // to fps.den.
    if (vrate.num == clock)
    {
        const hb_rate_t *video_framerate = NULL;
        while ((video_framerate = hb_video_framerate_get_next(video_framerate)) != NULL)
        {
            if (abs(vrate.den - video_framerate->rate) < 10)
            {
                vrate.den = video_framerate->rate;
                break;
            }
        }
    }
    hb_reduce(&vrate.num, &vrate.den, vrate.num, vrate.den);
    if (job->mux == HB_MUX_AV_MP4)
    {
        // libavformat mp4 muxer requires that the codec time_base have the
        // same denominator as the stream time_base, it uses it for the
        // mdhd timescale.
        double scale = (double)track->st->time_base.den / vrate.num;
        track->st->codec->time_base.den = track->st->time_base.den;
        track->st->codec->time_base.num = vrate.den * scale;
    }
    else
    {
        track->st->codec->time_base.num = vrate.den;
        track->st->codec->time_base.den = vrate.num;
    }
    track->st->avg_frame_rate.num = vrate.num;
    track->st->avg_frame_rate.den = vrate.den;

    /* add the audio tracks */
    for(ii = 0; ii < hb_list_count( job->list_audio ); ii++ )
    {
        audio = hb_list_item( job->list_audio, ii );
        track = m->tracks[m->ntracks++] = calloc(1, sizeof( hb_mux_data_t ) );
        audio->priv.mux_data = track;

        track->type = MUX_TYPE_AUDIO;

        track->st = avformat_new_stream(m->oc, NULL);
        if (track->st == NULL)
        {
            hb_error("Could not initialize audio stream");
            goto error;
        }
        avcodec_get_context_defaults3(track->st->codec, NULL);

        track->st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
        track->st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
        if (job->mux == HB_MUX_AV_MP4)
        {
            track->st->codec->time_base.num = audio->config.out.samples_per_frame;
            track->st->codec->time_base.den = audio->config.out.samplerate;
            track->st->time_base.num = 1;
            track->st->time_base.den = audio->config.out.samplerate;
        }
        else
        {
            track->st->codec->time_base = m->time_base;
            track->st->time_base = m->time_base;
        }

        priv_data = NULL;
        priv_size = 0;
        switch (audio->config.out.codec & HB_ACODEC_MASK)
        {
            case HB_ACODEC_DCA:
            case HB_ACODEC_DCA_HD:
                track->st->codec->codec_id = AV_CODEC_ID_DTS;
                break;
            case HB_ACODEC_AC3:
                track->st->codec->codec_id = AV_CODEC_ID_AC3;
                break;
            case HB_ACODEC_FFEAC3:
                track->st->codec->codec_id = AV_CODEC_ID_EAC3;
                break;
            case HB_ACODEC_FFTRUEHD:
                track->st->codec->codec_id = AV_CODEC_ID_TRUEHD;
                break;
            case HB_ACODEC_LAME:
            case HB_ACODEC_MP3:
                track->st->codec->codec_id = AV_CODEC_ID_MP3;
                break;
            case HB_ACODEC_VORBIS:
            {
                track->st->codec->codec_id = AV_CODEC_ID_VORBIS;

                int jj, size = 0;
                ogg_packet *ogg_headers[3];

                for (jj = 0; jj < 3; jj++)
                {
                    ogg_headers[jj] = (ogg_packet *)audio->priv.config.vorbis.headers[jj];
                    size += ogg_headers[jj]->bytes + 2;
                }

                priv_size = size;
                priv_data = av_malloc(priv_size + FF_INPUT_BUFFER_PADDING_SIZE);
                if (priv_data == NULL)
                {
                    hb_error("Vorbis extradata: malloc failure");
                    goto error;
                }

                size = 0;
                for(jj = 0; jj < 3; jj++)
                {
                    AV_WB16(priv_data + size, ogg_headers[jj]->bytes);
                    size += 2;
                    memcpy(priv_data+size, ogg_headers[jj]->packet,
                                           ogg_headers[jj]->bytes);
                    size += ogg_headers[jj]->bytes;
                }
            } break;
            case HB_ACODEC_FFFLAC:
            case HB_ACODEC_FFFLAC24:
                track->st->codec->codec_id = AV_CODEC_ID_FLAC;

                if (audio->priv.config.extradata.length)
                {
                    priv_size = audio->priv.config.extradata.length;
                    priv_data = av_malloc(priv_size + FF_INPUT_BUFFER_PADDING_SIZE);
                    if (priv_data == NULL)
                    {
                        hb_error("FLAC extradata: malloc failure");
                        goto error;
                    }
                    memcpy(priv_data,
                           audio->priv.config.extradata.bytes,
                           audio->priv.config.extradata.length);
                }
                break;
            case HB_ACODEC_FFAAC:
            case HB_ACODEC_CA_AAC:
            case HB_ACODEC_CA_HAAC:
            case HB_ACODEC_FDK_AAC:
            case HB_ACODEC_FDK_HAAC:
                track->st->codec->codec_id = AV_CODEC_ID_AAC;

                // libav mkv muxer expects there to be extradata for
                // AAC and will crash if it is NULL.
                //
                // Also, libav can over-read the buffer by up to 8 bytes
                // when it fills it's get_bits cache.
                //
                // So allocate extra bytes
                priv_size = audio->priv.config.extradata.length;
                priv_data = av_malloc(priv_size + FF_INPUT_BUFFER_PADDING_SIZE);
                if (priv_data == NULL)
                {
                    hb_error("AAC extradata: malloc failure");
                    goto error;
                }
                memcpy(priv_data,
                       audio->priv.config.extradata.bytes,
                       audio->priv.config.extradata.length);

                // AAC from pass-through source may be ADTS.
                // Therefore inserting "aac_adtstoasc" bitstream filter is
                // preferred.
                // The filter does nothing for non-ADTS bitstream.
                if (audio->config.out.codec == HB_ACODEC_AAC_PASS)
                {
                    track->bitstream_filter = av_bitstream_filter_init("aac_adtstoasc");
                }
                break;
            default:
                hb_error("muxavformat: Unknown audio codec: %x",
                         audio->config.out.codec);
                goto error;
        }
        track->st->codec->extradata = priv_data;
        track->st->codec->extradata_size = priv_size;

        if( default_track_flag )
        {
            track->st->disposition |= AV_DISPOSITION_DEFAULT;
            default_track_flag = 0;
        }

        lang = lookup_lang_code(job->mux, audio->config.lang.iso639_2 );
        if (lang != NULL)
        {
            av_dict_set(&track->st->metadata, "language", lang, 0);
        }
        track->st->codec->sample_rate = audio->config.out.samplerate;
        if (audio->config.out.codec & HB_ACODEC_PASS_FLAG)
        {
            track->st->codec->channels = av_get_channel_layout_nb_channels(audio->config.in.channel_layout);
            track->st->codec->channel_layout = audio->config.in.channel_layout;
        }
        else
        {
            track->st->codec->channels = hb_mixdown_get_discrete_channel_count(audio->config.out.mixdown);
            track->st->codec->channel_layout = hb_ff_mixdown_xlat(audio->config.out.mixdown, NULL);
        }

        char *name;
        if (audio->config.out.name == NULL)
        {
            switch (track->st->codec->channels)
            {
                case 1:
                    name = "Mono";
                    break;

                case 2:
                    name = "Stereo";
                    break;

                default:
                    name = "Surround";
                    break;
            }
        }
        else
        {
            name = audio->config.out.name;
        }
        // Set audio track title
        av_dict_set(&track->st->metadata, "title", name, 0);
        if (job->mux == HB_MUX_AV_MP4)
        {
            // Some software (MPC, mediainfo) use hdlr description
            // for track title
            av_dict_set(&track->st->metadata, "handler", name, 0);
        }
    }

    // Check for audio track associations
    for (ii = 0; ii < hb_list_count(job->list_audio); ii++)
    {
        audio = hb_list_item(job->list_audio, ii);
        switch (audio->config.out.codec & HB_ACODEC_MASK)
        {
            case HB_ACODEC_FFAAC:
            case HB_ACODEC_CA_AAC:
            case HB_ACODEC_CA_HAAC:
            case HB_ACODEC_FDK_AAC:
            case HB_ACODEC_FDK_HAAC:
                break;

            default:
            {
                // Mark associated fallback audio tracks for any non-aac track
                for(jj = 0; jj < hb_list_count( job->list_audio ); jj++ )
                {
                    hb_audio_t    * fallback;
                    int             codec;

                    if (ii == jj) continue;

                    fallback = hb_list_item( job->list_audio, jj );
                    codec = fallback->config.out.codec & HB_ACODEC_MASK;
                    if (fallback->config.in.track == audio->config.in.track &&
                        (codec == HB_ACODEC_FFAAC ||
                         codec == HB_ACODEC_CA_AAC ||
                         codec == HB_ACODEC_CA_HAAC ||
                         codec == HB_ACODEC_FDK_AAC ||
                         codec == HB_ACODEC_FDK_HAAC))
                    {
                        hb_mux_data_t * fallback_track;
                        int           * sd;

                        track = audio->priv.mux_data;
                        fallback_track = fallback->priv.mux_data;
                        sd = (int*)av_stream_new_side_data(track->st,
                                                     AV_PKT_DATA_FALLBACK_TRACK,
                                                     sizeof(int));
                        if (sd != NULL)
                        {
                            *sd = fallback_track->st->index;
                        }
                    }
                }
            } break;
        }
    }

    char * subidx_fmt =
        "size: %dx%d\n"
        "org: %d, %d\n"
        "scale: 100%%, 100%%\n"
        "alpha: 100%%\n"
        "smooth: OFF\n"
        "fadein/out: 50, 50\n"
        "align: OFF at LEFT TOP\n"
        "time offset: 0\n"
        "forced subs: %s\n"
        "palette: %06x, %06x, %06x, %06x, %06x, %06x, "
        "%06x, %06x, %06x, %06x, %06x, %06x, %06x, %06x, %06x, %06x\n"
        "custom colors: OFF, tridx: 0000, "
        "colors: 000000, 000000, 000000, 000000\n";

    int subtitle_default = -1;
    for( ii = 0; ii < hb_list_count( job->list_subtitle ); ii++ )
    {
        hb_subtitle_t *subtitle = hb_list_item( job->list_subtitle, ii );

        if( subtitle->config.dest == PASSTHRUSUB )
        {
            if ( subtitle->config.default_track )
                subtitle_default = ii;
        }
    }
    // Quicktime requires that at least one subtitle is enabled,
    // else it doesn't show any of the subtitles.
    // So check to see if any of the subtitles are flagged to be
    // the defualt.  The default will the the enabled track, else
    // enable the first track.
    if (job->mux == HB_MUX_AV_MP4 && subtitle_default == -1)
    {
        subtitle_default = 0;
    }

    for( ii = 0; ii < hb_list_count( job->list_subtitle ); ii++ )
    {
        hb_subtitle_t * subtitle;
        uint32_t        rgb[16];
        char            subidx[2048];
        int             len;

        subtitle = hb_list_item( job->list_subtitle, ii );
        if (subtitle->config.dest != PASSTHRUSUB)
            continue;

        track = m->tracks[m->ntracks++] = calloc(1, sizeof( hb_mux_data_t ) );
        subtitle->mux_data = track;

        track->type = MUX_TYPE_SUBTITLE;
        track->st = avformat_new_stream(m->oc, NULL);
        if (track->st == NULL)
        {
            hb_error("Could not initialize subtitle stream");
            goto error;
        }
        avcodec_get_context_defaults3(track->st->codec, NULL);

        track->st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
        track->st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
        track->st->time_base = m->time_base;
        track->st->codec->time_base = m->time_base;
        track->st->codec->width = subtitle->width;
        track->st->codec->height = subtitle->height;

        priv_data = NULL;
        priv_size = 0;
        switch (subtitle->source)
        {
            case VOBSUB:
            {
                int jj;
                track->st->codec->codec_id = AV_CODEC_ID_DVD_SUBTITLE;

                for (jj = 0; jj < 16; jj++)
                    rgb[jj] = hb_yuv2rgb(subtitle->palette[jj]);
                len = snprintf(subidx, 2048, subidx_fmt,
                        subtitle->width, subtitle->height,
                        0, 0, "OFF",
                        rgb[0], rgb[1], rgb[2], rgb[3],
                        rgb[4], rgb[5], rgb[6], rgb[7],
                        rgb[8], rgb[9], rgb[10], rgb[11],
                        rgb[12], rgb[13], rgb[14], rgb[15]);

                priv_size = len + 1;
                priv_data = av_malloc(priv_size + FF_INPUT_BUFFER_PADDING_SIZE);
                if (priv_data == NULL)
                {
                    hb_error("VOBSUB extradata: malloc failure");
                    goto error;
                }
                memcpy(priv_data, subidx, priv_size);
            } break;

            case PGSSUB:
            {
                track->st->codec->codec_id = AV_CODEC_ID_HDMV_PGS_SUBTITLE;
            } break;

            case CC608SUB:
            case CC708SUB:
            case TX3GSUB:
            case SRTSUB:
            case UTF8SUB:
            case SSASUB:
            {
                if (job->mux == HB_MUX_AV_MP4)
                {
                    track->st->codec->codec_id = AV_CODEC_ID_MOV_TEXT;
                }
                else
                {
                    track->st->codec->codec_id = AV_CODEC_ID_SSA;
                    need_fonts = 1;

                    if (subtitle->extradata_size)
                    {
                        priv_size = subtitle->extradata_size;
                        priv_data = av_malloc(priv_size + FF_INPUT_BUFFER_PADDING_SIZE);
                        if (priv_data == NULL)
                        {
                            hb_error("SSA extradata: malloc failure");
                            goto error;
                        }
                        memcpy(priv_data, subtitle->extradata, priv_size);
                    }
                }
            } break;

            default:
                continue;
        }
        if (track->st->codec->codec_id == AV_CODEC_ID_MOV_TEXT)
        {
            // Build codec extradata for tx3g.
            // If we were using a libav codec to generate this data
            // this would (or should) be done for us.
            uint8_t properties[] = {
                0x00, 0x00, 0x00, 0x00,     // Display Flags
                0x01,                       // Horiz. Justification
                0xff,                       // Vert. Justification
                0x00, 0x00, 0x00, 0xff,     // Bg color
                0x00, 0x00, 0x00, 0x00,     // Default text box
                0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,     // Reserved
                0x00, 0x01,                 // Font ID
                0x00,                       // Font face
                0x18,                       // Font size
                0xff, 0xff, 0xff, 0xff,     // Fg color
                // Font table:
                0x00, 0x00, 0x00, 0x12,     // Font table size
                'f','t','a','b',            // Tag
                0x00, 0x01,                 // Count
                0x00, 0x01,                 // Font ID
                0x05,                       // Font name length
                'A','r','i','a','l'         // Font name
            };

            int width, height = 60;
            width = job->width * job->par.num / job->par.den;
            track->st->codec->width = width;
            track->st->codec->height = height;
            properties[14] = height >> 8;
            properties[15] = height & 0xff;
            properties[16] = width >> 8;
            properties[17] = width & 0xff;

            priv_size = sizeof(properties);
            priv_data = av_malloc(priv_size + FF_INPUT_BUFFER_PADDING_SIZE);
            if (priv_data == NULL)
            {
                hb_error("TX3G extradata: malloc failure");
                goto error;
            }
            memcpy(priv_data, properties, priv_size);
        }
        track->st->codec->extradata = priv_data;
        track->st->codec->extradata_size = priv_size;

        if (ii == subtitle_default)
        {
            track->st->disposition |= AV_DISPOSITION_DEFAULT;
        }
        if (subtitle->config.default_track)
        {
            track->st->disposition |= AV_DISPOSITION_FORCED;
        }

        lang = lookup_lang_code(job->mux, subtitle->iso639_2 );
        if (lang != NULL)
        {
            av_dict_set(&track->st->metadata, "language", lang, 0);
        }
    }