AbstractStream::AbstractStream(const AVFormatContext *formatContext, uint index, qint64 id, Clock *globalClock, bool noModify, QObject *parent): QObject(parent) { this->m_runPacketLoop = false; this->m_runDataLoop = false; this->m_paused = false; this->m_isValid = false; this->m_clockDiff = 0; this->m_maxData = 0; this->m_index = index; this->m_id = id; this->m_stream = (formatContext && index < formatContext->nb_streams)? formatContext->streams[index]: NULL; this->m_mediaType = this->m_stream? this->m_stream->codec->codec_type: AVMEDIA_TYPE_UNKNOWN; this->m_codecContext = this->m_stream? this->m_stream->codec: NULL; this->m_codec = this->m_codecContext? avcodec_find_decoder(this->m_codecContext->codec_id): NULL; this->m_codecOptions = NULL; this->m_packetQueueSize = 0; this->m_globalClock = globalClock; if (!this->m_codec) return; if (this->m_stream) this->m_timeBase = AkFrac(this->m_stream->time_base.num, this->m_stream->time_base.den); if (!noModify) { this->m_stream->discard = AVDISCARD_DEFAULT; this->m_codecContext->workaround_bugs = 1; this->m_codecContext->idct_algo = FF_IDCT_AUTO; this->m_codecContext->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; if (this->m_codec->capabilities & CODEC_CAP_DR1) this->m_codecContext->flags |= CODEC_FLAG_EMU_EDGE; av_dict_set_int(&this->m_codecOptions, "refcounted_frames", 1, 0); } this->m_isValid = true; }
AkPacket::AkPacket(const AkCaps &caps, const QByteArray &buffer, qint64 pts, const AkFrac &timeBase, int index, qint64 id) { this->d = new AkPacketPrivate(); this->d->m_caps = caps; bool isValid = this->d->m_caps.isValid(); this->d->m_buffer = isValid? buffer: QByteArray(); this->d->m_pts = isValid? pts: 0; this->d->m_timeBase = isValid? timeBase: AkFrac(); this->d->m_index = isValid? index: -1; this->d->m_id = isValid? id: -1; }
AkVideoCaps &AkVideoCaps::operator =(const AkCaps &caps) { if (caps.mimeType() == "video/x-raw") { this->d->m_isValid = caps.isValid(); this->update(caps); } else { this->d->m_isValid = false; this->d->m_format = AkVideoCaps::Format_none; this->d->m_bpp = 0; this->d->m_width = 0; this->d->m_height = 0; this->d->m_fps = AkFrac(); } return *this; }
DesktopCaptureElement::DesktopCaptureElement(): AkMultimediaSourceElement() { this->m_fps = AkFrac(30000, 1001); this->m_curScreenNumber = -1; this->m_threadedRead = true; QObject::connect(qApp, &QGuiApplication::screenAdded, this, &DesktopCaptureElement::screenCountChanged); QObject::connect(qApp, &QGuiApplication::screenRemoved, this, &DesktopCaptureElement::screenCountChanged); QObject::connect(QApplication::desktop(), &QDesktopWidget::resized, this, &DesktopCaptureElement::srceenResized); QObject::connect(&this->m_timer, &QTimer::timeout, this, &DesktopCaptureElement::readFrame); }
void AkPacket::resetTimeBase() { this->setTimeBase(AkFrac()); }
bool CaptureDShow::init() { // Create the pipeline. if (FAILED(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, reinterpret_cast<void **>(&this->m_graph)))) return false; // Create the webcam filter. IBaseFilter *webcamFilter = this->findFilterP(this->m_device); if (!webcamFilter) { this->m_graph->Release(); this->m_graph = NULL; return false; } if (FAILED(this->m_graph->AddFilter(webcamFilter, SOURCE_FILTER_NAME))) { this->m_graph->Release(); this->m_graph = NULL; return false; } // Create the Sample Grabber filter. IBaseFilter *grabberFilter = NULL; if (FAILED(CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast<void **>(&grabberFilter)))) { this->m_graph->Release(); this->m_graph = NULL; return false; } if (FAILED(this->m_graph->AddFilter(grabberFilter, L"Grabber"))) { this->m_graph->Release(); this->m_graph = NULL; return false; } ISampleGrabber *grabberPtr = NULL; if (FAILED(grabberFilter->QueryInterface(IID_ISampleGrabber, reinterpret_cast<void **>(&grabberPtr)))) { this->m_graph->Release(); this->m_graph = NULL; return false; } if (FAILED(grabberPtr->SetOneShot(FALSE))) { this->m_graph->Release(); this->m_graph = NULL; return false; } HRESULT hr = grabberPtr->SetBufferSamples(TRUE); if (FAILED(hr)) { this->m_graph->Release(); this->m_graph = NULL; return false; } if (this->m_ioMethod != IoMethodDirectRead) { int type = this->m_ioMethod == IoMethodGrabSample? 0: 1; hr = grabberPtr->SetCallback(&this->m_frameGrabber, type); } this->m_grabber = SampleGrabberPtr(grabberPtr, this->deleteUnknown); if (!this->connectFilters(this->m_graph, webcamFilter, grabberFilter)) { this->m_graph->Release(); this->m_graph = NULL; return false; } // Create null filter. IBaseFilter *nullFilter = NULL; if (FAILED(CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast<void **>(&nullFilter)))) { this->m_graph->Release(); this->m_graph = NULL; return false; } if (FAILED(this->m_graph->AddFilter(nullFilter, L"NullFilter"))) { this->m_graph->Release(); this->m_graph = NULL; return false; } if (!this->connectFilters(this->m_graph, grabberFilter, nullFilter)) { this->m_graph->Release(); this->m_graph = NULL; return false; } // Set capture format QList<int> streams = this->streams(); if (streams.isEmpty()) { this->m_graph->Release(); this->m_graph = NULL; return false; } MediaTypesList mediaTypes = this->listMediaTypes(webcamFilter); if (mediaTypes.isEmpty()) { this->m_graph->Release(); this->m_graph = NULL; return false; } MediaTypePtr mediaType = streams[0] < mediaTypes.size()? mediaTypes[streams[0]]: mediaTypes.first(); if (FAILED(grabberPtr->SetMediaType(mediaType.data()))) { this->m_graph->Release(); this->m_graph = NULL; return false; } PinList pins = this->enumPins(webcamFilter, PINDIR_OUTPUT); for (const PinPtr &pin: pins) { IAMStreamConfig *pStreamConfig = NULL; HRESULT hr = pin->QueryInterface(IID_IAMStreamConfig, reinterpret_cast<void **>(&pStreamConfig)); if (SUCCEEDED(hr)) pStreamConfig->SetFormat(mediaType.data()); if (pStreamConfig) pStreamConfig->Release(); } // Run the pipeline IMediaControl *control = NULL; if (FAILED(this->m_graph->QueryInterface(IID_IMediaControl, reinterpret_cast<void **>(&control)))) { this->m_graph->Release(); this->m_graph = NULL; return false; } this->m_id = Ak::id(); AkCaps caps = this->capsFromMediaType(mediaType); this->m_timeBase = AkFrac(caps.property("fps").toString()).invert(); if (FAILED(control->Run())) { control->Release(); this->m_graph->Release(); this->m_graph = NULL; return false; } control->Release(); this->m_localImageControls.clear(); this->m_localImageControls.clear(); return true; }
void DesktopCaptureElement::resetFps() { this->setFps(AkFrac(30000, 1001)); }
AkPacket ConvertAudioFFmpeg::convert(const AkAudioPacket &packet, const AkCaps &oCaps) { AkAudioCaps oAudioCaps(oCaps); int64_t iSampleLayout = channelLayouts->value(packet.caps().layout(), 0); AVSampleFormat iSampleFormat = av_get_sample_fmt(AkAudioCaps::sampleFormatToString(packet.caps().format()) .toStdString().c_str()); int iSampleRate = packet.caps().rate(); int iNChannels = packet.caps().channels(); int iNSamples = packet.caps().samples(); int64_t oSampleLayout = channelLayouts->value(oAudioCaps.layout(), AV_CH_LAYOUT_STEREO); AVSampleFormat oSampleFormat = av_get_sample_fmt(AkAudioCaps::sampleFormatToString(oAudioCaps.format()) .toStdString().c_str()); int oSampleRate = oAudioCaps.rate(); int oNChannels = oAudioCaps.channels(); this->m_resampleContext = swr_alloc_set_opts(this->m_resampleContext, oSampleLayout, oSampleFormat, oSampleRate, iSampleLayout, iSampleFormat, iSampleRate, 0, NULL); if (!this->m_resampleContext) return AkPacket(); // Create input audio frame. static AVFrame iFrame; memset(&iFrame, 0, sizeof(AVFrame)); iFrame.format = iSampleFormat; iFrame.channels = iNChannels; iFrame.channel_layout = uint64_t(iSampleLayout); iFrame.sample_rate = iSampleRate; iFrame.nb_samples = iNSamples; iFrame.pts = iFrame.pkt_pts = packet.pts(); if (avcodec_fill_audio_frame(&iFrame, iFrame.channels, iSampleFormat, reinterpret_cast<const uint8_t *>(packet.buffer().constData()), packet.buffer().size(), 1) < 0) { return AkPacket(); } // Fill output audio frame. AVFrame oFrame; memset(&oFrame, 0, sizeof(AVFrame)); oFrame.format = oSampleFormat; oFrame.channels = oNChannels; oFrame.channel_layout = uint64_t(oSampleLayout); oFrame.sample_rate = oSampleRate; oFrame.nb_samples = int(swr_get_delay(this->m_resampleContext, oSampleRate)) + iFrame.nb_samples * oSampleRate / iSampleRate + 3; oFrame.pts = oFrame.pkt_pts = iFrame.pts * oSampleRate / iSampleRate; // Calculate the size of the audio buffer. int frameSize = av_samples_get_buffer_size(oFrame.linesize, oFrame.channels, oFrame.nb_samples, oSampleFormat, 1); QByteArray oBuffer(frameSize, Qt::Uninitialized); if (avcodec_fill_audio_frame(&oFrame, oFrame.channels, oSampleFormat, reinterpret_cast<const uint8_t *>(oBuffer.constData()), oBuffer.size(), 1) < 0) { return AkPacket(); } // convert to destination format if (swr_convert_frame(this->m_resampleContext, &oFrame, &iFrame) < 0) return AkPacket(); frameSize = av_samples_get_buffer_size(oFrame.linesize, oFrame.channels, oFrame.nb_samples, oSampleFormat, 1); oBuffer.resize(frameSize); AkAudioPacket oAudioPacket; oAudioPacket.caps() = oAudioCaps; oAudioPacket.caps().samples() = oFrame.nb_samples; oAudioPacket.buffer() = oBuffer; oAudioPacket.pts() = oFrame.pts; oAudioPacket.timeBase() = AkFrac(1, oAudioCaps.rate()); oAudioPacket.index() = packet.index(); oAudioPacket.id() = packet.id(); return oAudioPacket.toPacket(); }
void AkVideoCaps::resetFps() { this->setFps(AkFrac()); }
AkFrac AkFrac::invert() const { return AkFrac(this->d->m_den, this->d->m_num); }
AkFrac AkFrac::operator *(const AkFrac &other) const { return AkFrac(this->d->m_num * other.d->m_num, this->d->m_den * other.d->m_den); }