Ejemplo n.º 1
0
static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext* of) 
{
	AVStream* st;
	AVCodecContext* c;
	AVCodec* codec;

	st = av_new_stream(of, 1);
	if (!st) return NULL;

	c = st->codec;
	c->codec_id = codec_id;
	c->codec_type = AVMEDIA_TYPE_AUDIO;

	c->sample_rate = rd->ffcodecdata.audio_mixrate;
	c->bit_rate = ffmpeg_audio_bitrate*1000;
	c->sample_fmt = SAMPLE_FMT_S16;
	c->channels = rd->ffcodecdata.audio_channels;
	codec = avcodec_find_encoder(c->codec_id);
	if (!codec) {
		//XXX error("Couldn't find a valid audio codec");
		return NULL;
	}

	set_ffmpeg_properties(rd, c, "audio");

	if (avcodec_open(c, codec) < 0) {
		//XXX error("Couldn't initialize audio codec");
		return NULL;
	}

	/* need to prevent floating point exception when using vorbis audio codec,
	   initialize this value in the same way as it's done in FFmpeg iteslf (sergey) */
	st->codec->time_base.num= 1;
	st->codec->time_base.den= st->codec->sample_rate;

	audio_outbuf_size = FF_MIN_BUFFER_SIZE;

	if((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD))
		audio_input_samples = audio_outbuf_size * 8 / c->bits_per_coded_sample / c->channels;
	else
	{
		audio_input_samples = c->frame_size;
		if(c->frame_size * c->channels * sizeof(int16_t) * 4 > audio_outbuf_size)
			audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
	}

	audio_output_buffer = (uint8_t*)av_malloc(
		audio_outbuf_size);

	audio_input_buffer = (uint8_t*)av_malloc(
		audio_input_samples * c->channels * sizeof(int16_t));

	audio_time = 0.0f;

	return st;
}
Ejemplo n.º 2
0
static AVStream *alloc_audio_stream(FFMpegContext *context, RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size)
{
	AVStream *st;
	AVCodecContext *c;
	AVCodec *codec;
	AVDictionary *opts = NULL;

	error[0] = '\0';

	st = avformat_new_stream(of, NULL);
	if (!st) return NULL;
	st->id = 1;

	c = st->codec;
	c->codec_id = codec_id;
	c->codec_type = AVMEDIA_TYPE_AUDIO;

	c->sample_rate = rd->ffcodecdata.audio_mixrate;
	c->bit_rate = context->ffmpeg_audio_bitrate * 1000;
	c->sample_fmt = AV_SAMPLE_FMT_S16;
	c->channels = rd->ffcodecdata.audio_channels;

	if (request_float_audio_buffer(codec_id)) {
		/* mainly for AAC codec which is experimental */
		c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
		c->sample_fmt = AV_SAMPLE_FMT_FLT;
	}

	codec = avcodec_find_encoder(c->codec_id);
	if (!codec) {
		//XXX error("Couldn't find a valid audio codec");
		return NULL;
	}

	if (codec->sample_fmts) {
		/* check if the preferred sample format for this codec is supported.
		 * this is because, depending on the version of libav, and with the whole ffmpeg/libav fork situation,
		 * you have various implementations around. float samples in particular are not always supported.
		 */
		const enum AVSampleFormat *p = codec->sample_fmts;
		for (; *p != -1; p++) {
			if (*p == st->codec->sample_fmt)
				break;
		}
		if (*p == -1) {
			/* sample format incompatible with codec. Defaulting to a format known to work */
			st->codec->sample_fmt = codec->sample_fmts[0];
		}
	}

	if (codec->supported_samplerates) {
		const int *p = codec->supported_samplerates;
		int best = 0;
		int best_dist = INT_MAX;
		for (; *p; p++) {
			int dist = abs(st->codec->sample_rate - *p);
			if (dist < best_dist) {
				best_dist = dist;
				best = *p;
			}
		}
		/* best is the closest supported sample rate (same as selected if best_dist == 0) */
		st->codec->sample_rate = best;
	}

	if (of->oformat->flags & AVFMT_GLOBALHEADER) {
		c->flags |= CODEC_FLAG_GLOBAL_HEADER;
	}

	set_ffmpeg_properties(rd, c, "audio", &opts);

	if (avcodec_open2(c, codec, &opts) < 0) {
		//XXX error("Couldn't initialize audio codec");
		BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
		av_dict_free(&opts);
		return NULL;
	}
	av_dict_free(&opts);

	/* need to prevent floating point exception when using vorbis audio codec,
	 * initialize this value in the same way as it's done in FFmpeg itself (sergey) */
	st->codec->time_base.num = 1;
	st->codec->time_base.den = st->codec->sample_rate;

#ifndef FFMPEG_HAVE_ENCODE_AUDIO2
	context->audio_outbuf_size = FF_MIN_BUFFER_SIZE;
#endif

	if (c->frame_size == 0)
		// used to be if ((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD))
		// not sure if that is needed anymore, so let's try out if there are any
		// complaints regarding some ffmpeg versions users might have
		context->audio_input_samples = FF_MIN_BUFFER_SIZE * 8 / c->bits_per_coded_sample / c->channels;
	else {
		context->audio_input_samples = c->frame_size;
#ifndef FFMPEG_HAVE_ENCODE_AUDIO2
		if (c->frame_size * c->channels * sizeof(int16_t) * 4 > context->audio_outbuf_size)
			context->audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
#endif
	}

	context->audio_deinterleave = av_sample_fmt_is_planar(c->sample_fmt);

	context->audio_sample_size = av_get_bytes_per_sample(c->sample_fmt);

	context->audio_input_buffer = (uint8_t *) av_malloc(context->audio_input_samples * c->channels * context->audio_sample_size);
#ifndef FFMPEG_HAVE_ENCODE_AUDIO2
	context->audio_output_buffer = (uint8_t *) av_malloc(context->audio_outbuf_size);
#endif

	if (context->audio_deinterleave)
		context->audio_deinterleave_buffer = (uint8_t *) av_malloc(context->audio_input_samples * c->channels * context->audio_sample_size);

	context->audio_time = 0.0f;

	return st;
}
Ejemplo n.º 3
0
static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int codec_id, AVFormatContext *of,
                                    int rectx, int recty, char *error, int error_size)
{
	AVStream *st;
	AVCodecContext *c;
	AVCodec *codec;
	AVDictionary *opts = NULL;

	error[0] = '\0';

	st = avformat_new_stream(of, NULL);
	if (!st) return NULL;
	st->id = 0;

	/* Set up the codec context */
	
	c = st->codec;
	c->codec_id = codec_id;
	c->codec_type = AVMEDIA_TYPE_VIDEO;

	/* Get some values from the current render settings */
	
	c->width = rectx;
	c->height = recty;

	/* FIXME: Really bad hack (tm) for NTSC support */
	if (context->ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) {
		c->time_base.den = 2997;
		c->time_base.num = 100;
	}
	else if ((float) ((int) rd->frs_sec_base) == rd->frs_sec_base) {
		c->time_base.den = rd->frs_sec;
		c->time_base.num = (int) rd->frs_sec_base;
	}
	else {
		c->time_base.den = rd->frs_sec * 100000;
		c->time_base.num = ((double) rd->frs_sec_base) * 100000;
	}
	
	c->gop_size = context->ffmpeg_gop_size;
	c->bit_rate = context->ffmpeg_video_bitrate * 1000;
	c->rc_max_rate = rd->ffcodecdata.rc_max_rate * 1000;
	c->rc_min_rate = rd->ffcodecdata.rc_min_rate * 1000;
	c->rc_buffer_size = rd->ffcodecdata.rc_buffer_size * 1024;

#if 0
	/* this options are not set in ffmpeg.c and leads to artifacts with MPEG-4
	 * see #33586: Encoding to mpeg4 makes first frame(s) blocky
	 */
	c->rc_initial_buffer_occupancy = rd->ffcodecdata.rc_buffer_size * 3 / 4;
	c->rc_buffer_aggressivity = 1.0;
#endif

	c->me_method = ME_EPZS;
	
	codec = avcodec_find_encoder(c->codec_id);
	if (!codec)
		return NULL;
	
	/* Be sure to use the correct pixel format(e.g. RGB, YUV) */

	if (codec->pix_fmts) {
		c->pix_fmt = codec->pix_fmts[0];
	}
	else {
		/* makes HuffYUV happy ... */
		c->pix_fmt = PIX_FMT_YUV422P;
	}

	if (context->ffmpeg_type == FFMPEG_XVID) {
		/* arghhhh ... */
		c->pix_fmt = PIX_FMT_YUV420P;
		c->codec_tag = (('D' << 24) + ('I' << 16) + ('V' << 8) + 'X');
	}

	if (codec_id == AV_CODEC_ID_H264) {
		/* correct wrong default ffmpeg param which crash x264 */
		c->qmin = 10;
		c->qmax = 51;
	}
	
	/* Keep lossless encodes in the RGB domain. */
	if (codec_id == AV_CODEC_ID_HUFFYUV) {
		if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
			c->pix_fmt = PIX_FMT_BGRA;
		}
		else {
			c->pix_fmt = PIX_FMT_RGB32;
		}
	}

	if (codec_id == AV_CODEC_ID_FFV1) {
		c->pix_fmt = PIX_FMT_RGB32;
	}

	if (codec_id == AV_CODEC_ID_QTRLE) {
		if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
			c->pix_fmt = PIX_FMT_ARGB;
		}
	}

	if (codec_id == AV_CODEC_ID_PNG) {
		if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
			c->pix_fmt = PIX_FMT_RGBA;
		}
	}

	if ((of->oformat->flags & AVFMT_GLOBALHEADER)
#if 0
	    || STREQ(of->oformat->name, "mp4")
	    || STREQ(of->oformat->name, "mov")
	    || STREQ(of->oformat->name, "3gp")
#endif
	    )
	{
		PRINT("Using global header\n");
		c->flags |= CODEC_FLAG_GLOBAL_HEADER;
	}
	
	/* Determine whether we are encoding interlaced material or not */
	if (rd->mode & R_FIELDS) {
		PRINT("Encoding interlaced video\n");
		c->flags |= CODEC_FLAG_INTERLACED_DCT;
		c->flags |= CODEC_FLAG_INTERLACED_ME;
	}

	/* xasp & yasp got float lately... */

	st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q(((double) rd->xasp / (double) rd->yasp), 255);

	set_ffmpeg_properties(rd, c, "video", &opts);

	if (avcodec_open2(c, codec, &opts) < 0) {
		BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
		av_dict_free(&opts);
		return NULL;
	}
	av_dict_free(&opts);

	context->current_frame = alloc_picture(c->pix_fmt, c->width, c->height);

	context->img_convert_ctx = sws_getContext(c->width, c->height, PIX_FMT_BGR32, c->width, c->height, c->pix_fmt, SWS_BICUBIC,
	                                 NULL, NULL, NULL);
	return st;
}
Ejemplo n.º 4
0
static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContext* of,
					int rectx, int recty) 
{
	AVStream* st;
	AVCodecContext* c;
	AVCodec* codec;
	st = av_new_stream(of, 0);
	if (!st) return NULL;

	/* Set up the codec context */
	
	c = st->codec;
	c->codec_id = codec_id;
	c->codec_type = AVMEDIA_TYPE_VIDEO;


	/* Get some values from the current render settings */
	
	c->width = rectx;
	c->height = recty;

	/* FIXME: Really bad hack (tm) for NTSC support */
	if (ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) {
		c->time_base.den = 2997;
		c->time_base.num = 100;
	} else if ((double) ((int) rd->frs_sec_base) == 
		   rd->frs_sec_base) {
		c->time_base.den = rd->frs_sec;
		c->time_base.num = (int) rd->frs_sec_base;
	} else {
		c->time_base.den = rd->frs_sec * 100000;
		c->time_base.num = ((double) rd->frs_sec_base) * 100000;
	}
	
	c->gop_size = ffmpeg_gop_size;
	c->bit_rate = ffmpeg_video_bitrate*1000;
	c->rc_max_rate = rd->ffcodecdata.rc_max_rate*1000;
	c->rc_min_rate = rd->ffcodecdata.rc_min_rate*1000;
	c->rc_buffer_size = rd->ffcodecdata.rc_buffer_size * 1024;
	c->rc_initial_buffer_occupancy 
		= rd->ffcodecdata.rc_buffer_size*3/4;
	c->rc_buffer_aggressivity = 1.0;
	c->me_method = ME_EPZS;
	
	codec = avcodec_find_encoder(c->codec_id);
	if (!codec) return NULL;
	
	/* Be sure to use the correct pixel format(e.g. RGB, YUV) */
	
	if (codec->pix_fmts) {
		c->pix_fmt = codec->pix_fmts[0];
	} else {
		/* makes HuffYUV happy ... */
		c->pix_fmt = PIX_FMT_YUV422P;
	}

	if (ffmpeg_type == FFMPEG_XVID) {
		/* arghhhh ... */
		c->pix_fmt = PIX_FMT_YUV420P;
		c->codec_tag = (('D'<<24) + ('I'<<16) + ('V'<<8) + 'X');
	}

	if (codec_id == CODEC_ID_H264) {
		/* correct wrong default ffmpeg param which crash x264 */
		c->qmin=10;
		c->qmax=51;
	}
	
	// Keep lossless encodes in the RGB domain.
	if (codec_id == CODEC_ID_HUFFYUV || codec_id == CODEC_ID_FFV1) {
		/* HUFFYUV was PIX_FMT_YUV422P before */
		c->pix_fmt = PIX_FMT_RGB32;
	}

	if ((of->oformat->flags & AVFMT_GLOBALHEADER)
//		|| !strcmp(of->oformat->name, "mp4")
//	    || !strcmp(of->oformat->name, "mov")
//	    || !strcmp(of->oformat->name, "3gp")
		) {
		fprintf(stderr, "Using global header\n");
		c->flags |= CODEC_FLAG_GLOBAL_HEADER;
	}
	
	/* Determine whether we are encoding interlaced material or not */
	if (rd->mode & R_FIELDS) {
		fprintf(stderr, "Encoding interlaced video\n");
		c->flags |= CODEC_FLAG_INTERLACED_DCT;
		c->flags |= CODEC_FLAG_INTERLACED_ME;
	}

	/* xasp & yasp got float lately... */

	st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q(
		((double) rd->xasp / (double) rd->yasp), 255);

	set_ffmpeg_properties(rd, c, "video");
	
	if (avcodec_open(c, codec) < 0) {
		//
		//XXX error("Couldn't initialize codec");
		return NULL;
	}

	video_buffersize = avpicture_get_size(c->pix_fmt, c->width, c->height);
	video_buffer = (uint8_t*)MEM_mallocN(video_buffersize*sizeof(uint8_t),
						 "FFMPEG video buffer");
	
	current_frame = alloc_picture(c->pix_fmt, c->width, c->height);

	img_convert_ctx = sws_getContext(c->width, c->height,
					 PIX_FMT_BGR32,
					 c->width, c->height,
					 c->pix_fmt,
					 SWS_BICUBIC,
					 NULL, NULL, NULL);
	return st;
}
Ejemplo n.º 5
0
static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContext *of,
                                    int rectx, int recty, char *error, int error_size)
{
	AVStream *st;
	AVCodecContext *c;
	AVCodec *codec;

	error[0] = '\0';

	st = av_new_stream(of, 0);
	if (!st) return NULL;

	/* Set up the codec context */
	
	c = st->codec;
	c->codec_id = codec_id;
	c->codec_type = AVMEDIA_TYPE_VIDEO;

	/* Get some values from the current render settings */
	
	c->width = rectx;
	c->height = recty;

	/* FIXME: Really bad hack (tm) for NTSC support */
	if (ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) {
		c->time_base.den = 2997;
		c->time_base.num = 100;
	}
	else if ((float) ((int) rd->frs_sec_base) == rd->frs_sec_base) {
		c->time_base.den = rd->frs_sec;
		c->time_base.num = (int) rd->frs_sec_base;
	}
	else {
		c->time_base.den = rd->frs_sec * 100000;
		c->time_base.num = ((double) rd->frs_sec_base) * 100000;
	}
	
	c->gop_size = ffmpeg_gop_size;
	c->bit_rate = ffmpeg_video_bitrate * 1000;
	c->rc_max_rate = rd->ffcodecdata.rc_max_rate * 1000;
	c->rc_min_rate = rd->ffcodecdata.rc_min_rate * 1000;
	c->rc_buffer_size = rd->ffcodecdata.rc_buffer_size * 1024;

#if 0
	/* this options are not set in ffmpeg.c and leads to artifacts with MPEG-4
	 * see #33586: Encoding to mpeg4 makes first frame(s) blocky
	 */
	c->rc_initial_buffer_occupancy = rd->ffcodecdata.rc_buffer_size * 3 / 4;
	c->rc_buffer_aggressivity = 1.0;
#endif

	c->me_method = ME_EPZS;
	
	codec = avcodec_find_encoder(c->codec_id);
	if (!codec)
		return NULL;
	
	/* Be sure to use the correct pixel format(e.g. RGB, YUV) */

	if (codec->pix_fmts) {
		c->pix_fmt = codec->pix_fmts[0];
	}
	else {
		/* makes HuffYUV happy ... */
		c->pix_fmt = PIX_FMT_YUV422P;
	}

	if (ffmpeg_type == FFMPEG_XVID) {
		/* arghhhh ... */
		c->pix_fmt = PIX_FMT_YUV420P;
		c->codec_tag = (('D' << 24) + ('I' << 16) + ('V' << 8) + 'X');
	}

	if (codec_id == CODEC_ID_H264) {
		/* correct wrong default ffmpeg param which crash x264 */
		c->qmin = 10;
		c->qmax = 51;
	}
	
	/* Keep lossless encodes in the RGB domain. */
	if (codec_id == CODEC_ID_HUFFYUV) {
		/* HUFFYUV was PIX_FMT_YUV422P before */
		c->pix_fmt = PIX_FMT_RGB32;
	}

	if (codec_id == CODEC_ID_FFV1) {
#ifdef FFMPEG_FFV1_ALPHA_SUPPORTED
		if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
			c->pix_fmt = PIX_FMT_RGB32;
		}
		else {
			c->pix_fmt = PIX_FMT_BGR0;
		}
#else
		c->pix_fmt = PIX_FMT_RGB32;
#endif
	}

	if (codec_id == CODEC_ID_QTRLE) {
		if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
			c->pix_fmt = PIX_FMT_ARGB;
		}
	}

	if ((of->oformat->flags & AVFMT_GLOBALHEADER)
//		|| !strcmp(of->oformat->name, "mp4")
//	    || !strcmp(of->oformat->name, "mov")
//	    || !strcmp(of->oformat->name, "3gp")
	    )
	{
		PRINT("Using global header\n");
		c->flags |= CODEC_FLAG_GLOBAL_HEADER;
	}
	
	/* Determine whether we are encoding interlaced material or not */
	if (rd->mode & R_FIELDS) {
		PRINT("Encoding interlaced video\n");
		c->flags |= CODEC_FLAG_INTERLACED_DCT;
		c->flags |= CODEC_FLAG_INTERLACED_ME;
	}

	/* xasp & yasp got float lately... */

	st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q(((double) rd->xasp / (double) rd->yasp), 255);

	set_ffmpeg_properties(rd, c, "video");
	
	if (avcodec_open(c, codec) < 0) {
		BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
		return NULL;
	}

	if (codec_id == CODEC_ID_QTRLE) {
		/* normally it should be enough to have buffer with actual image size,
		 * but some codecs like QTRLE might store extra information in this buffer,
		 * so it should be a way larger */

		/* maximum video buffer size is 6-bytes per pixel, plus DPX header size (1664)
		 * (from FFmpeg sources) */
		int size = c->width * c->height;
		video_buffersize = 7 * size + 10000;
	}
	else
		video_buffersize = avpicture_get_size(c->pix_fmt, c->width, c->height);

	video_buffer = (uint8_t *)MEM_mallocN(video_buffersize * sizeof(uint8_t), "FFMPEG video buffer");
	
	current_frame = alloc_picture(c->pix_fmt, c->width, c->height);

	img_convert_ctx = sws_getContext(c->width, c->height, PIX_FMT_BGR32, c->width, c->height, c->pix_fmt, SWS_BICUBIC,
	                                 NULL, NULL, NULL);
	return st;
}