74 return "Read overflow";
80 return "Restart required";
97 if (
params.input ==
"pipewiregrab") {
103 input = fmt::format(
"pipewiregrab=draw_mouse=1:fd={}:node={}",
params.fd,
params.node);
104 JAMI_LOG(
"Attempting to open input {}", input);
130 auto framerate {
params.framerate.real()};
131 framerate =
params.framerate.numerator() / (
params.framerate.denominator() + 0.5);
132 if (
params.framerate.denominator() != 4999998)
153 if (!
params.pixel_format.empty()) {
156 if (!
params.window_id.empty()) {
162#if defined(__APPLE__) && TARGET_OS_MAC
168 JAMI_LOG(
"Attempting to open input {} with format {}, pixel format {}, size {}x{}, rate {}",
178 if (
params.disable_dts_probe_delay &&
params.format ==
"sdp") {
190 }
else if (inputCtx_->nb_streams > 0 && inputCtx_->streams[0]->codecpar) {
191 baseWidth_ = inputCtx_->streams[0]->codecpar->width;
192 baseHeight_ = inputCtx_->streams[0]->codecpar->height;
193 JAMI_LOG(
"Opened input Using format {:s} and resolution {:d}x{:d}",
194 params.format, baseWidth_, baseHeight_);
203 return inputCtx_->duration;
219 if (
not streamInfoFound_) {
225 streamInfoFound_ =
true;
234 auto st = inputCtx_->streams[
sti];
237 JAMI_DBG(
"Skipping attached picture stream");
248 inputCtx_->interrupt_callback.callback =
cb;
249 inputCtx_->interrupt_callback.opaque =
opaque;
251 inputCtx_->interrupt_callback.callback = 0;
257 needFrameCb_ = std::move(
cb);
263 fileFinishedCb_ = std::move(
cb);
267MediaDemuxer::clearFrames()
270 std::lock_guard
lk {videoBufferMutex_};
271 while (!videoBuffer_.empty()) {
276 std::lock_guard
lk {audioBufferMutex_};
277 while (!audioBuffer_.empty()) {
287 return pushFrameFrom(audioBuffer_,
isAudio, audioBufferMutex_);
289 return pushFrameFrom(videoBuffer_,
isAudio, videoBufferMutex_);
294MediaDemuxer::pushFrameFrom(
299 std::unique_lock lock(mutex);
308 auto packet = std::move(
buffer.front());
339 }
else if (
ret < 0) {
351 std::lock_guard
lk {videoBufferMutex_};
352 videoBuffer_.push(std::move(packet));
353 if (videoBuffer_.size() >= 90) {
357 std::lock_guard
lk {audioBufferMutex_};
358 audioBuffer_.push(std::move(packet));
359 if (audioBuffer_.size() >= 300) {
369 inputCtx_->pb =
ioctx->getContext();
375 if (inputParams_.
format ==
"x11grab" || inputParams_.
format ==
"dxgigrab") {
376 auto ret = inputCtx_->iformat->read_header(inputCtx_);
381 auto codecpar = inputCtx_->streams[0]->codecpar;
385 inputParams_.
height = ((baseHeight_ >> 3) << 3);
386 inputParams_.
width = ((baseWidth_ >> 3) << 3);
408 std::this_thread::sleep_for(std::chrono::microseconds(
timeToSleep));
414 }
else if (
ret < 0) {
415 auto media = inputCtx_->streams[0]->codecpar->codec_type;
416 const auto type =
media == AVMediaType::AVMEDIA_TYPE_AUDIO
418 : (
media == AVMediaType::AVMEDIA_TYPE_VIDEO ?
"VIDEO" :
"UNSUPPORTED");
441 , avStream_(
demuxer->getStream(index))
451 , avStream_(
demuxer->getStream(index))
461 return demuxer_->emitFrame(
isAudio);
476 if (decoderCtx_ && decoderCtx_->hw_device_ctx)
492 return demuxer_->openInput(p);
498 demuxer_->setInterruptCallback(
cb,
opaque);
504 demuxer_->setIOContext(
ioctx);
510 demuxer_->findStreamInfo();
511 auto stream = demuxer_->selectStream(type);
513 JAMI_ERR(
"No stream found for type %i",
static_cast<int>(type));
516 avStream_ = demuxer_->getStream(stream);
517 if (avStream_ ==
nullptr) {
518 JAMI_ERR(
"No stream found at index %i", stream);
521 demuxer_->setStreamCallback(stream, [
this](
AVPacket& packet) {
return decode(packet); });
522 return setupStream();
526MediaDecoder::setupStream()
531 if (prepareDecoderContext() < 0)
544 for (
const auto&
it :
APIs) {
545 accel_ = std::make_unique<video::HardwareAccel>(
it);
546 auto ret =
accel_->initAPI(
false,
nullptr);
551 if (prepareDecoderContext() < 0)
553 accel_->setDetails(decoderCtx_);
554 decoderCtx_->opaque =
accel_.get();
555 decoderCtx_->pix_fmt =
accel_->getFormat();
558 JAMI_WARN(
"Fail to open hardware decoder for %s with %s",
560 it.getName().c_str());
562 decoderCtx_ =
nullptr;
567 JAMI_WARN(
"Using hardware decoding for %s with %s",
569 it.getName().c_str());
576 JAMI_LOG(
"Using {} ({}) decoder for {}",
577 inputDecoder_->long_name,
580 decoderCtx_->thread_count = std::max(1u, std::min(8u, std::thread::hardware_concurrency() / 2));
582 JAMI_DBG() <<
"Using framerate emulation";
602MediaDecoder::prepareDecoderContext()
604 inputDecoder_ =
findDecoder(avStream_->codecpar->codec_id);
605 if (!inputDecoder_) {
612 JAMI_ERROR(
"Failed to create decoder context");
616 width_ = decoderCtx_->width;
617 height_ = decoderCtx_->height;
618 decoderCtx_->framerate = avStream_->avg_frame_rate;
620 if (decoderCtx_->framerate.num == 0 || decoderCtx_->framerate.den == 0)
621 decoderCtx_->framerate = inputParams_.
framerate;
622 if (decoderCtx_->framerate.num == 0 || decoderCtx_->framerate.den == 0)
623 decoderCtx_->framerate = {30, 1};
630 decoderCtx_->sample_fmt = format;
631 decoderCtx_->request_sample_fmt = format;
660 JAMI_WARN(
"Decoding error falling back to software");
675 ? std::static_pointer_cast<MediaFrame>(std::make_shared<VideoFrame>())
678 auto f = std::static_pointer_cast<MediaFrame>(std::make_shared<AudioFrame>());
680 auto frame =
f->pointer();
685 decoderCtx_->time_base.num = decoderCtx_->framerate.den;
686 decoderCtx_->time_base.den = decoderCtx_->framerate.num;
688 decoderCtx_->time_base.num = 1;
689 decoderCtx_->time_base.den = decoderCtx_->sample_rate;
691 frame->time_base = decoderCtx_->time_base;
692 if (resolutionChangedCallback_) {
693 if (decoderCtx_->width != width_
or decoderCtx_->height != height_) {
694 JAMI_DBG(
"Resolution changed from %dx%d to %dx%d",
698 decoderCtx_->height);
699 width_ = decoderCtx_->width;
700 height_ = decoderCtx_->height;
701 resolutionChangedCallback_(width_, height_);
716 decoderCtx_->time_base,
719 lastTimestamp_ =
frame->pts;
722 rational<double>
frame_time = rational<double>(getTimeBase())
740 callback_(std::move(
f));
742 if (contextCallback_ && firstDecode_.load()) {
743 firstDecode_.exchange(
false);
760 auto ret = demuxer_->decode();
779 decoderCtx_->opaque =
nullptr;
796 auto result = std::make_shared<MediaFrame>();
806 callback_(std::move(result));
817 return decoderCtx_ ? decoderCtx_->width : 0;
823 return decoderCtx_ ? decoderCtx_->height : 0;
829 return decoderCtx_ ? decoderCtx_->codec->name :
"";
835 return {(
double) avStream_->avg_frame_rate.num, (
double) avStream_->avg_frame_rate.den};
839MediaDecoder::getTimeBase()
const
841 return {(
unsigned) avStream_->time_base.num, (
unsigned) avStream_->time_base.den};
847 return decoderCtx_->pix_fmt;
882 auto ms =
MediaStream(name, decoderCtx_, lastTimestamp_);
886 ms.format =
accel_->getSoftwareFormat();
static LIBJAMI_TEST_EXPORT Manager & instance()
Naive implementation of the boost::rational interface, described here: http://www....
constexpr I numerator() const
static std::list< HardwareAccel > getCompatibleAccel(AVCodecID id, int width, int height, CodecType type)
void av_buffer_unref(AVBufferRef **buf)
#define JAMI_ERROR(formatstr,...)
#define JAMI_DEBUG(formatstr,...)
#define JAMI_LOG(formatstr,...)
AVSampleFormat choose_sample_fmt_default(const AVCodec *codec, AVSampleFormat defaultFormat)
std::string getError(int err)
const constexpr unsigned MAX_ACCEL_FAILURES
void emitSignal(Args... args)
const constexpr auto jitterBufferMaxDelay_
const unsigned jitterBufferMaxSize_
std::function< void(std::shared_ptr< MediaFrame > &&)> MediaObserver
std::string to_string(double value)
libjami::MediaFrame MediaFrame
libjami::AudioFrame AudioFrame
const AVCodec * findDecoder(const enum AVCodecID codec_id)
Attempt to find standalone AVCodec decoder using AVCodecID, or fallback to the default decoder.
std::unique_ptr< AVPacket, AVPacket_deleter > PacketBuffer
DeviceParams Parameters used by MediaDecoder and MediaEncoder to open a LibAV device/stream.
rational< double > framerate
void av_packet_free(AVPacket **frame)