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