Example #1
0
int MediaDecoder::setupFromAudioData(const AudioFormat format)
{
    int ret;

    if (decoderCtx_)
        avcodec_close(decoderCtx_);

    // Increase analyze time to solve synchronization issues between callers.
    static const unsigned MAX_ANALYZE_DURATION = 30; // time in seconds

    inputCtx_->max_analyze_duration = MAX_ANALYZE_DURATION * AV_TIME_BASE;

    RING_DBG("Finding stream info");
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 8, 0)
    ret = av_find_stream_info(inputCtx_);
#else
    ret = avformat_find_stream_info(inputCtx_, NULL);
#endif
    RING_DBG("Finding stream info DONE");

    if (ret < 0) {
        // workaround for this bug:
        // http://patches.libav.org/patch/22541/
        if (ret == -1)
            ret = AVERROR_INVALIDDATA;
        char errBuf[64] = {0};
        // print nothing for unknown errors
        if (av_strerror(ret, errBuf, sizeof errBuf) < 0)
            errBuf[0] = '\0';

        // always fail here
        RING_ERR("Could not find stream info: %s", errBuf);
        return -1;
    }

    // find the first audio stream from the input
    for (size_t i = 0; streamIndex_ == -1 && i < inputCtx_->nb_streams; ++i)
        if (inputCtx_->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
            streamIndex_ = i;

    if (streamIndex_ == -1) {
        RING_ERR("Could not find audio stream");
        return -1;
    }

    // Get a pointer to the codec context for the video stream
    avStream_ = inputCtx_->streams[streamIndex_];
    decoderCtx_ = avStream_->codec;
    if (decoderCtx_ == 0) {
        RING_ERR("Decoder context is NULL");
        return -1;
    }

    // find the decoder for the audio stream
    inputDecoder_ = avcodec_find_decoder(decoderCtx_->codec_id);
    if (!inputDecoder_) {
        RING_ERR("Unsupported codec");
        return -1;
    }

    decoderCtx_->thread_count = std::thread::hardware_concurrency();
    decoderCtx_->channels = format.nb_channels;
    decoderCtx_->sample_rate = format.sample_rate;

    RING_DBG("Audio decoding using %s with %s",
             inputDecoder_->name, format.toString().c_str());

    if (emulateRate_) {
        RING_DBG("Using framerate emulation");
        startTime_ = av_gettime();
    }

#if LIBAVCODEC_VERSION_MAJOR >= 55
    decoderCtx_->refcounted_frames = 1;
#endif
    ret = avcodec_open2(decoderCtx_, inputDecoder_, NULL);
    if (ret) {
        RING_ERR("Could not open codec");
        return -1;
    }

    return 0;
}