void Parser::setStream() { int error = 0; AVCodec *codec = NULL; AVCodecID codecID = getCodecID(); codec = avcodec_find_encoder(codecID); fmt_ctx_out->audio_codec = codec; stm_out = avformat_new_stream(fmt_ctx_out, codec); if (!stm_out) throw StreamException() << errno_code(MIR_ERR_OPEN_STREAM_1); cdc_ctx_out = stm_out->codec; cdc_ctx_out->codec = codec; cdc_ctx_out->codec_id = codecID; cdc_ctx_out->codec_type = AVMEDIA_TYPE_AUDIO; cdc_ctx_out->sample_fmt = getSampleFormat(codecID); if (!isVBR) cdc_ctx_out->bit_rate = bitRate; else { cdc_ctx_out->rc_max_rate = 0; cdc_ctx_out->rc_min_rate = 0; cdc_ctx_out->bit_rate_tolerance = bitRate; cdc_ctx_out->bit_rate = bitRate; } cdc_ctx_out->sample_rate = sampleRate; cdc_ctx_out->channels = nbChannel; cdc_ctx_out->channel_layout = av_get_default_channel_layout(nbChannel); error = avcodec_open2(cdc_ctx_out, codec, NULL); if (error < 0) throw StreamException() << errno_code(MIR_ERR_OPEN_STREAM_2); if (codecID == AV_CODEC_ID_PCM_S16LE || codecID == AV_CODEC_ID_MP3) cdc_ctx_out->frame_size = av_rescale_rnd(nbSamplesIn, cdc_ctx_out->sample_rate, sampleRateIn, AV_ROUND_UP); else if (codecID == AV_CODEC_ID_AAC) { cdc_ctx_out->profile = FF_PROFILE_AAC_LOW; cdc_ctx_out->frame_size = 1024; // some formats want stream headers to be separate if(fmt_ctx_out->oformat->flags & AVFMT_GLOBALHEADER) cdc_ctx_out->flags |= CODEC_FLAG_GLOBAL_HEADER; } cdc_out = codec; if (audioFormat == AUDIOFORMAT::arq) { fmt_ctx_out->oformat->flags |= AVFMT_ALLOW_FLUSH; } }
bool VideoEncoder::init(const Desc& desc) { // Register the codecs av_register_all(); // create the output context avformat_alloc_output_context2(&mpOutputContext, nullptr, nullptr, mFilename.c_str()); if(mpOutputContext == nullptr) { // The sample tries again, while explicitly requesting mpeg format. I chose not to do it, since it might lead to a container with a wrong extension return error(mFilename, "File output format not recognized. Make sure you use a known file extension (avi/mpeg/mp4)"); } // Get the output format of the container AVOutputFormat* pOutputFormat = mpOutputContext->oformat; assert((pOutputFormat->flags & AVFMT_NOFILE) == 0); // Problem. We want a file. // create the video codec AVCodec* pVideoCodec; mpOutputStream = createVideoStream(mpOutputContext, desc.fps, getCodecID(desc.codec), mFilename, pVideoCodec); if(mpOutputStream == nullptr) { return false; } mpCodecContext = createCodecContext(mpOutputContext, desc.width, desc.height, desc.fps, desc.bitrateMbps, desc.gopSize, getCodecID(desc.codec), pVideoCodec); if(mpCodecContext == nullptr) { return false; } // Open the video stream if(openVideo(pVideoCodec, mpCodecContext, mpFrame, mFilename) == false) { return false; } // copy the stream parameters to the muxer if(avcodec_parameters_from_context(mpOutputStream->codecpar, mpCodecContext) < 0) { return error(desc.filename, "Could not copy the stream parameters\n"); } av_dump_format(mpOutputContext, 0, mFilename.c_str(), 1); // Open the output file assert((pOutputFormat->flags & AVFMT_NOFILE) == 0); // No output file required. Not sure if/when this happens. if(avio_open(&mpOutputContext->pb, mFilename.c_str(), AVIO_FLAG_WRITE) < 0) { return error(mFilename, "Can't open output file."); } // Write the stream header if(avformat_write_header(mpOutputContext, nullptr) < 0) { return error(mFilename, "Can't write file header."); } mFormat = desc.format; mRowPitch = getFormatBytesPerBlock(desc.format) * desc.width; if(desc.flipY) { mpFlippedImage = new uint8_t[desc.height * mRowPitch]; } mpSwsContext = sws_getContext(desc.width, desc.height, getPictureFormatFromFalcorFormat(desc.format), desc.width, desc.height, mpCodecContext->pix_fmt, SWS_POINT, nullptr, nullptr, nullptr); if(mpSwsContext == nullptr) { return error(mFilename, "Failed to allocate SWScale context"); } return true; }