void AudioInputElement::readFrame() { this->m_mutex.lock(); QByteArray buffer = this->m_audioDevice.read(this->m_bufferSize); this->m_mutex.unlock(); if (buffer.isEmpty()) return; QbBufferPtr oBuffer(new char[buffer.size()]); memcpy(oBuffer.data(), buffer.constData(), buffer.size()); QbCaps caps = this->m_caps; caps.setProperty("samples", this->m_bufferSize); QbPacket packet(caps, oBuffer, buffer.size()); qint64 pts = QTime::currentTime().msecsSinceStartOfDay() / this->m_timeBase.value(); packet.setPts(pts); packet.setTimeBase(this->m_timeBase); packet.setIndex(0); packet.setId(this->m_streamId); if (!this->m_threadedRead) { emit this->oStream(packet); return; } if (!this->m_threadStatus.isRunning()) { this->m_curPacket = packet; this->m_threadStatus = QtConcurrent::run(&this->m_threadPool, this->sendPacket, this, this->m_curPacket); } }
QVariantMap MediaSink::addStream(int streamIndex, const QbCaps &streamCaps, const QVariantMap &codecParams) { QString outputFormat; if (this->supportedFormats().contains(this->m_outputFormat)) outputFormat = this->m_outputFormat; else { AVOutputFormat *format = av_guess_format(NULL, this->m_location.toStdString().c_str(), NULL); if (format) outputFormat = QString(format->name); } if (outputFormat.isEmpty()) return QVariantMap(); QVariantMap outputParams; outputParams["index"] = streamIndex; QString codec; if (codecParams.contains("codec")) { if (supportedCodecs(outputFormat, streamCaps.mimeType()) .contains(codecParams["codec"].toString())) { codec = codecParams["codec"].toString(); } else codec = this->defaultCodec(outputFormat, streamCaps.mimeType()); } else codec = this->defaultCodec(outputFormat, streamCaps.mimeType()); outputParams["codec"] = codec; QVariantMap codecDefaults = this->defaultCodecParams(codec); outputParams["codecOptions"] = codecParams.value("codecOptions", QVariantMap()); if (streamCaps.mimeType() == "audio/x-raw") { int bitRate = codecParams.value("bitRate", codecDefaults["defaultBitRate"]).toInt(); outputParams["bitRate"] = bitRate > 0? bitRate: codecDefaults["defaultBitRate"].toInt(); QbAudioCaps audioCaps(streamCaps); QString sampleFormat = QbAudioCaps::sampleFormatToString(audioCaps.format()); QStringList supportedSampleFormats = codecDefaults["supportedSampleFormats"].toStringList(); if (!supportedSampleFormats.isEmpty() && !supportedSampleFormats.contains(sampleFormat)) { QString defaultSampleFormat = codecDefaults["defaultSampleFormat"].toString(); audioCaps.format() = QbAudioCaps::sampleFormatFromString(defaultSampleFormat); audioCaps.bps() = av_get_bytes_per_sample(av_get_sample_fmt(defaultSampleFormat.toStdString().c_str())); } QVariantList supportedSampleRates = codecDefaults["supportedSampleRates"].toList(); if (!supportedSampleRates.isEmpty()) { int sampleRate = 0; int maxDiff = std::numeric_limits<int>::max(); foreach (QVariant rate, supportedSampleRates) { int diff = qAbs(audioCaps.rate() - rate.toInt()); if (diff < maxDiff) { sampleRate = rate.toInt(); if (!diff) break; maxDiff = diff; } }
QList<QbPacket> VideoStream::readPackets(AVPacket *packet) { QList<QbPacket> packets; if (!this->isValid()) return packets; AVFrame iFrame; avcodec_get_frame_defaults(&iFrame); int gotFrame; avcodec_decode_video2(this->codecContext(), &iFrame, &gotFrame, packet); if (!gotFrame) return packets; int frameSize = avpicture_get_size(this->codecContext()->pix_fmt, this->codecContext()->width, this->codecContext()->height); QSharedPointer<uchar> oBuffer(new uchar[frameSize]); if (!oBuffer) return packets; static bool sync; if (this->m_fst) { sync = av_frame_get_best_effort_timestamp(&iFrame)? false: true; this->m_pts = 0; this->m_duration = this->fps().invert().value() * this->timeBase().invert().value(); this->m_fst = false; } else this->m_pts += this->m_duration; avpicture_layout((AVPicture *) &iFrame, this->codecContext()->pix_fmt, this->codecContext()->width, this->codecContext()->height, (uint8_t *) oBuffer.data(), frameSize); QbCaps caps = this->caps(); caps.setProperty("sync", sync); QbPacket oPacket(caps, oBuffer, frameSize); oPacket.setPts(this->m_pts); oPacket.setDuration(this->m_duration); oPacket.setTimeBase(this->timeBase()); oPacket.setIndex(this->index()); packets << oPacket; return packets; }