コード例 #1
0
    CodecBoxDecoderContext(const char* filePath, CodecBoxDecoder& host_):
        host(host_),
        formatContext(nullptr),
        videoStream(-1),
        audioStream(-1),
        videoCodecContext(nullptr),
        audioCodecContext(nullptr),
        sws(nullptr),
        swr(nullptr),
        decodedFrame(nullptr),
        videoLineSize(0),
        videoBuffer(nullptr),
        audioBuffer(nullptr)
    {
        host.state = CodecBoxDecoderState::Init;
        JIF(avformat_open_input(&formatContext, filePath, nullptr, nullptr) != 0,
                "failed avformat_open_input: %s", filePath);
        JIF(avformat_find_stream_info(formatContext, nullptr) < 0,
                "failed avformat_find_stream_info: %s", filePath);
        av_dump_format(formatContext, 0, filePath, 0);

        host.duration = (double)formatContext->duration / AV_TIME_BASE;
        host.startTime = (double)formatContext->start_time / AV_TIME_BASE;

        for (int i = 0; i < formatContext->nb_streams; i++)
        {
            auto type = formatContext->streams[i]->codec->codec_type;
            if (videoStream < 0 && type == AVMEDIA_TYPE_VIDEO) videoStream = i;
            else if (audioStream < 0 && type == AVMEDIA_TYPE_AUDIO) audioStream = i;
        }

        JIF(videoStream < 0 && audioStream < 0 , "no audio/video stream found in %s", filePath);

        if (videoStream >= 0)
        {
            videoCodecContext = createCodecContext(formatContext, videoStream);
            JIF(videoCodecContext == nullptr, "video codec not supported");
            host.hasVideo = true;
            host.width = videoCodecContext->width;
            host.height = videoCodecContext->height;
            // videoCodecContext->framerate is usually not useful (0)
            auto fr = formatContext->streams[videoStream]->avg_frame_rate;
            host.frameRate = (double)fr.num / fr.den;
        }
        if (audioStream >= 0)
        {
            audioCodecContext = createCodecContext(formatContext, audioStream);
            JIF(audioCodecContext == nullptr, "audio codec not supported");
            host.hasAudio = true;
            host.sampleRate = audioCodecContext->sample_rate;
            host.channels = 2; // will be re-sampled as AV_CH_LAYOUT_STEREO. // audioCodecContext->channels;
        }
        decodedFrame = av_frame_alloc();
        JIF(!decodedFrame, "faild to alloc decodedFrame");
        host.state = CodecBoxDecoderState::Metadata;
        return;
    err:
        host.state = CodecBoxDecoderState::Failed;
        close();
    }
コード例 #2
0
ファイル: VideoEncoder.cpp プロジェクト: Junios/Falcor
    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;
    }