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; }
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; }
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; }
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; }
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; }