Beispiel #1
0
/**
 * SPDIFEncoder constructor
 * Args:
 *   QString muxer       : name of the muxer.
 *                         Use "spdif" for IEC 958 or IEC 61937 encapsulation
 *                         (AC3, DTS, E-AC3, TrueHD, DTS-HD-MA)
 *                         Use "adts" for ADTS encpsulation (AAC)
 *   AVCodecContext *ctx : CodecContext to be encaspulated
 */
SPDIFEncoder::SPDIFEncoder(QString muxer, int codec_id)
    : m_complete(false), m_oc(NULL), m_stream(NULL), m_size(0)
{
    QByteArray dev_ba     = muxer.toAscii();
    AVOutputFormat *fmt;

    avcodeclock->lock();
    av_register_all();
    avcodeclock->unlock();

    fmt = av_guess_format(dev_ba.constData(), NULL, NULL);
    if (!fmt)
    {
        LOG(VB_AUDIO, LOG_ERR, LOC + "av_guess_format");
        return;
    }

    m_oc = avformat_alloc_context();
    if (!m_oc)
    {
        LOG(VB_AUDIO, LOG_ERR, LOC + "avformat_alloc_context");
        return;
    }
    m_oc->oformat = fmt;

    m_oc->pb = avio_alloc_context(m_buffer, sizeof(m_buffer), 0,
                                  this, NULL, funcIO, NULL);
    if (!m_oc->pb)
    {
        LOG(VB_AUDIO, LOG_ERR, LOC + "avio_alloc_context");
        Destroy();
        return;
    }

    m_oc->pb->seekable    = 0;
    m_oc->flags          |= AVFMT_NOFILE | AVFMT_FLAG_IGNIDX;

    m_stream = avformat_new_stream(m_oc, NULL);
    if (!m_stream)
    {
        LOG(VB_AUDIO, LOG_ERR, LOC + "avformat_new_stream");
        Destroy();
        return;
    }

    m_stream->id          = 1;

    AVCodecContext *codec = m_stream->codec;

    codec->codec_id       = (CodecID)codec_id;
    avformat_write_header(m_oc, NULL);

    LOG(VB_AUDIO, LOG_INFO, LOC + QString("Creating %1 encoder (for %2)")
            .arg(muxer).arg(ff_codec_id_string((CodecID)codec_id)));

    m_complete = true;
}
Beispiel #2
0
SPDIFEncoder::SPDIFEncoder(QString muxer, AVCodecContext *ctx)
    : m_complete(false), m_oc(NULL), m_stream(NULL), m_size(0)
{
    QByteArray dev_ba     = muxer.toAscii();
    AVOutputFormat *fmt =
        av_guess_format(dev_ba.constData(), NULL, NULL);

    if (!(av_guess_format && avformat_alloc_context &&
          av_new_stream && av_write_header && av_write_frame &&
          av_write_trailer && av_set_parameters))
    {
        VERBOSE(VB_IMPORTANT, LOC_ERR + "Couldn't find libavformat");
        return;
    }

    if (!avcodec_close)
    {
        VERBOSE(VB_IMPORTANT, LOC_ERR + "Couldn't find libavcodec");
        return;
    }

    if (!(av_freep && av_alloc_put_byte))
    {
        VERBOSE(VB_IMPORTANT, LOC_ERR + "Couldn't find libavutil");
        return;
    }

    if (!fmt)
    {
        VERBOSE(VB_AUDIO, LOC_ERR + "av_guess_format");
        return;
    }

    m_oc = avformat_alloc_context();
    if (!m_oc)
    {
        VERBOSE(VB_AUDIO, LOC_ERR + "avformat_alloc_context");
        return;
    }
    m_oc->oformat = fmt;

    if (av_set_parameters(m_oc, NULL) < 0)
    {
        VERBOSE(VB_AUDIO, LOC_ERR + "av_set_parameters");
        Destroy();
        return;
    }

    m_oc->pb = av_alloc_put_byte(m_buffer, sizeof(m_buffer), URL_RDONLY,
                                 this, NULL, funcIO, NULL);
    if (!m_oc->pb)
    {
        VERBOSE(VB_AUDIO, LOC_ERR + "av_alloc_put_byte");
        Destroy();
        return;
    }

    m_oc->pb->is_streamed    = true;
    m_oc->flags             |= AVFMT_NOFILE | AVFMT_FLAG_IGNIDX;

    if (av_set_parameters(m_oc, NULL) != 0)
    {
        VERBOSE(VB_AUDIO, LOC_ERR + "av_set_parameters");
        Destroy();
        return;
    }

    m_stream = av_new_stream(m_oc, 1);
    if (!m_stream)
    {
        VERBOSE(VB_AUDIO, LOC_ERR + "av_new_stream");
        Destroy();
        return;
    }

        // copy without decoding or reencoding
    m_stream->stream_copy           = true;

    AVCodecContext *codec = m_stream->codec;

    codec->codec_type     = ctx->codec_type;
    codec->codec_id       = ctx->codec_id;
    codec->sample_rate    = ctx->sample_rate;
    codec->sample_fmt     = ctx->sample_fmt;
    codec->channels       = ctx->channels;
    codec->bit_rate       = ctx->bit_rate;
    codec->extradata      = new uint8_t[ctx->extradata_size];
    codec->extradata_size = ctx->extradata_size;
    memcpy(codec->extradata, ctx->extradata, ctx->extradata_size);

    av_write_header(m_oc);

    VERBOSE(VB_AUDIO, LOC + QString("Creating %1 encoder (%2, %3Hz)")
            .arg(muxer).arg(ff_codec_id_string((CodecID)codec->codec_type))
            .arg(codec->sample_rate));

    m_complete = true;
}
bool AudioOutputDigitalEncoder::Init(
    CodecID codec_id, int bitrate, int samplerate, int channels)
{
    AVCodec *codec;
    int ret;

    LOG(VB_AUDIO, LOG_INFO, QString("Init codecid=%1, br=%2, sr=%3, ch=%4")
            .arg(ff_codec_id_string(codec_id)) .arg(bitrate)
            .arg(samplerate) .arg(channels));

    // We need to do this when called from mythmusic
    avcodec_init();
    avcodec_register_all();
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT( 52, 113, 0 )
    codec = avcodec_find_encoder_by_name("ac3_fixed");
#else
    codec = avcodec_find_encoder(CODEC_ID_AC3);
#endif
    if (!codec)
    {
        LOG(VB_GENERAL, LOG_ERR, "Could not find codec");
        return false;
    }

    av_context                 = avcodec_alloc_context();
    avcodec_get_context_defaults3(av_context, codec);

    av_context->bit_rate       = bitrate;
    av_context->sample_rate    = samplerate;
    av_context->channels       = channels;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT( 52, 113, 0 )
    av_context->channel_layout = AV_CH_LAYOUT_5POINT1;
    av_context->sample_fmt     = AV_SAMPLE_FMT_S16;
#else
    av_context->channel_layout = CH_LAYOUT_5POINT1;
    av_context->sample_fmt     = SAMPLE_FMT_S16;
#endif

// open it
    ret = avcodec_open(av_context, codec);
    if (ret < 0)
    {
        LOG(VB_GENERAL, LOG_ERR,
            "Could not open codec, invalid bitrate or samplerate");

        Dispose();
        return false;
    }

    if (m_spdifenc)
    {
        delete m_spdifenc;
    }

    m_spdifenc = new SPDIFEncoder("spdif", CODEC_ID_AC3);
    if (!m_spdifenc->Succeeded())
    {
        Dispose();
        LOG(VB_GENERAL, LOG_ERR, "Could not create spdif muxer");
        return false;
    }

    samples_per_frame  = av_context->frame_size * av_context->channels;

    LOG(VB_AUDIO, LOG_INFO, QString("DigitalEncoder::Init fs=%1, spf=%2")
            .arg(av_context->frame_size) .arg(samples_per_frame));

    return true;
}
bool PrivateDecoderCrystalHD::Init(const QString &decoder,
                                   PlayerFlags flags,
                                   AVCodecContext *avctx)
{
    if ((decoder != "crystalhd") || !(flags & kDecodeAllowEXT) ||
        !avctx || getenv("NO_CRYSTALHD"))
        return false;

    static bool debugged = false;

    uint32_t well_documented = DTS_PLAYBACK_MODE | DTS_LOAD_FILE_PLAY_FW |
                               DTS_SKIP_TX_CHK_CPB |
                               DTS_PLAYBACK_DROP_RPT_MODE |
                               DTS_DFLT_RESOLUTION(vdecRESOLUTION_CUSTOM);
    INIT_ST;
    st = DtsDeviceOpen(&m_device, well_documented);
    CHECK_ST;
    if (!ok)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to open CrystalHD device");
        return false;
    }

    _BC_INFO_CRYSTAL_ info;
    st = DtsCrystalHDVersion(m_device, &info);
    CHECK_ST;
    if (!ok)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to get device info.");
        return false;
    }

    m_device_type = (BC_DEVICE_TYPE)info.device;

    if (!debugged)
    {
        LOG(VB_GENERAL, LOG_INFO, LOC + QString("Device: %1")
                .arg(device_to_string(m_device_type)));
        LOG(VB_GENERAL, LOG_INFO, LOC + QString("Library : %1.%2.%3")
                .arg(info.dilVersion.dilMajor)
                .arg(info.dilVersion.dilMinor)
                .arg(info.dilVersion.version));
        LOG(VB_GENERAL, LOG_INFO, LOC + QString("Driver  : %1.%2.%3")
                .arg(info.drvVersion.drvMajor)
                .arg(info.drvVersion.drvMinor)
                .arg(info.drvVersion.version));
        LOG(VB_GENERAL, LOG_INFO, LOC + QString("Firmware: %1.%2.%3")
                .arg(info.fwVersion.fwMajor)
                .arg(info.fwVersion.fwMinor)
                .arg(info.fwVersion.version));
    }

    if (BC_70012 == m_device_type)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC +
            "BCM70012 device is currently unsupported.");
        return false;
    }

    BC_HW_CAPS hw_caps;
    uint32_t codecs;
    st = DtsGetCapabilities(m_device, &hw_caps);
    CHECK_ST;
    if (!ok)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to get device capabilities");
        return false;
    }

    BC_OUTPUT_FORMAT m_desired_fmt = (m_device_type == BC_70015) ?
                                     OUTPUT_MODE422_YUY2 : OUTPUT_MODE420;
    m_pix_fmt = OUTPUT_MODE_INVALID;
    for (int i = 0; i < hw_caps.ColorCaps.Count; i++)
    {
        if (m_desired_fmt == hw_caps.ColorCaps.OutFmt[i])
            m_pix_fmt = m_desired_fmt;
        if (!debugged)
        {
            LOG(VB_PLAYBACK, LOG_INFO, LOC +
                QString("Supported output format: %1")
                    .arg(bcmpixfmt_to_string(hw_caps.ColorCaps.OutFmt[i])));
        }
    }
    if (m_pix_fmt != m_desired_fmt)
    {
        LOG(VB_PLAYBACK, LOG_ERR, LOC +
            "Failed to find correct output format.");
        return false;
    }
    LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Using: %1")
            .arg(bcmpixfmt_to_string(m_pix_fmt)));

    codecs = hw_caps.DecCaps;
    if (!debugged)
    {
        LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("H.264 support: %1")
                .arg((bool)(codecs & BC_DEC_FLAGS_H264)));
        LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("MPEG2 support: %1")
                .arg((bool)(codecs & BC_DEC_FLAGS_MPEG2)));
        LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("VC1   support: %1")
                .arg((bool)(codecs & BC_DEC_FLAGS_VC1)));
        LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("MPEG4 support: %1")
                .arg((bool)(codecs & BC_DEC_FLAGS_M4P2)));
        debugged = true;
    }

    BC_MEDIA_SUBTYPE sub_type = BC_MSUBTYPE_INVALID;

    switch (avctx->codec_id)
    {
        case AV_CODEC_ID_MPEG4:
            if (codecs & BC_DEC_FLAGS_M4P2)
                sub_type = BC_MSUBTYPE_DIVX;
            break;
        case AV_CODEC_ID_MPEG1VIDEO:
            if (codecs & BC_DEC_FLAGS_MPEG2)
                sub_type = BC_MSUBTYPE_MPEG1VIDEO;
            break;
        case AV_CODEC_ID_MPEG2VIDEO:
            if (codecs & BC_DEC_FLAGS_MPEG2)
                sub_type = BC_MSUBTYPE_MPEG2VIDEO;
            break;
        case AV_CODEC_ID_VC1:
            if (codecs & BC_DEC_FLAGS_VC1)
            {
                if (avctx->codec_tag == MKTAG('W','V','C','1'))
                    sub_type = BC_MSUBTYPE_WVC1;
                else
                    sub_type = BC_MSUBTYPE_VC1;
            }
            break;
        case AV_CODEC_ID_WMV3:
            if (codecs & BC_DEC_FLAGS_VC1)
                sub_type = BC_MSUBTYPE_WMV3;
            break;
        case AV_CODEC_ID_H264:
            if (codecs & BC_DEC_FLAGS_H264)
            {
                if (avctx->extradata[0] == 0x01)
                {
                    if (!CreateFilter(avctx))
                    {
                        LOG(VB_PLAYBACK, LOG_ERR, LOC +
                            "Failed to create stream filter");
                        return false;
                    }
                    sub_type = BC_MSUBTYPE_AVC1;
                }
                else
                    sub_type = BC_MSUBTYPE_H264;
            }
            break;
    }

    if (sub_type == BC_MSUBTYPE_INVALID)
    {
        LOG(VB_PLAYBACK, LOG_ERR, LOC + QString("Codec %1 not supported")
                .arg(ff_codec_id_string(avctx->codec_id)));
        return false;
    }

    int nalsize = 4;
    if (avctx->codec_id == AV_CODEC_ID_H264)
    {
        LOG(VB_PLAYBACK, LOG_INFO, LOC +
            QString("H.264 Profile: %1 RefFrames: %2 Codec tag: %3")
                .arg(avctx->profile).arg(avctx->refs)
                .arg(fourcc_str(avctx->codec_tag)));
        if (avctx->extradata[0] == 1)
        {
            nalsize = (avctx->extradata[4] & 0x03) + 1;
            LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("avcC nal size: %1")
                    .arg(nalsize));
        }
    }

    BC_INPUT_FORMAT fmt;
    memset(&fmt, 0, sizeof(BC_INPUT_FORMAT));
    fmt.OptFlags       = 0x80000000 | vdecFrameRateUnknown;
    fmt.width          = avctx->coded_width;
    fmt.height         = avctx->coded_height;
    fmt.Progressive    = 1;
    fmt.FGTEnable      = 0;
    fmt.MetaDataEnable = 0;
    fmt.metaDataSz     = avctx->extradata_size;
    fmt.pMetaData      = avctx->extradata;
    fmt.startCodeSz    = nalsize;
    fmt.mSubtype       = sub_type;

    st = DtsSetInputFormat(m_device, &fmt);
    CHECK_ST;
    if (!ok)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to set decoder input format");
        return false;
    }

    st = DtsOpenDecoder(m_device, BC_STREAM_TYPE_ES);
    CHECK_ST;
    if (!ok)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to open CrystalHD decoder");
        return false;
    }

    st = DtsSetColorSpace(m_device, m_pix_fmt);
    if (!ok)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to set decoder output format");
        return false;
    }

    st = DtsStartDecoder(m_device);
    if (!ok)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to start decoder");
        return false;
    }

    st = DtsStartCapture(m_device);
    if (!ok)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to start capture");
        return false;
    }

    Reset();

    LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Created decoder %1 %2x%3")
        .arg(ff_codec_id_string(avctx->codec_id))
        .arg(avctx->coded_width).arg(avctx->coded_height));
    return true;
}