Line data Source code
1 : /*
2 : * Copyright (C) 2004-2024 Savoir-faire Linux Inc.
3 : *
4 : * This program is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 3 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * This program is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "libav_deps.h" // MUST BE INCLUDED FIRST
19 : #include "media_decoder.h"
20 : #include "media_device.h"
21 : #include "media_buffer.h"
22 : #include "media_const.h"
23 : #include "media_io_handle.h"
24 : #include "audio/ringbuffer.h"
25 : #include "audio/resampler.h"
26 : #include "audio/ringbufferpool.h"
27 : #include "decoder_finder.h"
28 : #include "manager.h"
29 :
30 : #ifdef RING_ACCEL
31 : #include "video/accel.h"
32 : #endif
33 :
34 : #include "string_utils.h"
35 : #include "logger.h"
36 : #include "client/ring_signal.h"
37 :
38 : #include <iostream>
39 : #include <unistd.h>
40 : #include <thread> // hardware_concurrency
41 : #include <chrono>
42 : #include <algorithm>
43 :
44 : namespace jami {
45 :
46 : // maximum number of packets the jitter buffer can queue
47 : const unsigned jitterBufferMaxSize_ {1500};
48 : // maximum time a packet can be queued
49 : const constexpr auto jitterBufferMaxDelay_ = std::chrono::milliseconds(50);
50 : // maximum number of times accelerated decoding can fail in a row before falling back to software
51 : const constexpr unsigned MAX_ACCEL_FAILURES {5};
52 :
53 405 : MediaDemuxer::MediaDemuxer()
54 810 : : inputCtx_(avformat_alloc_context())
55 405 : , startTime_(AV_NOPTS_VALUE)
56 405 : {}
57 :
58 405 : MediaDemuxer::~MediaDemuxer()
59 : {
60 405 : if (inputCtx_)
61 347 : avformat_close_input(&inputCtx_);
62 405 : av_dict_free(&options_);
63 405 : }
64 :
65 : const char*
66 0 : MediaDemuxer::getStatusStr(Status status)
67 : {
68 0 : switch (status) {
69 0 : case Status::Success:
70 0 : return "Success";
71 0 : case Status::EndOfFile:
72 0 : return "End of file";
73 0 : case Status::ReadBufferOverflow:
74 0 : return "Read overflow";
75 0 : case Status::ReadError:
76 0 : return "Read error";
77 0 : case Status::FallBack:
78 0 : return "Fallback";
79 0 : case Status::RestartRequired:
80 0 : return "Restart required";
81 0 : default:
82 0 : return "Undefined";
83 : }
84 : }
85 :
86 : int
87 405 : MediaDemuxer::openInput(const DeviceParams& params)
88 : {
89 405 : inputParams_ = params;
90 405 : auto iformat = av_find_input_format(params.format.c_str());
91 :
92 405 : if (!iformat && !params.format.empty())
93 1 : JAMI_WARN("Unable to find format \"%s\"", params.format.c_str());
94 :
95 405 : std::string input;
96 :
97 405 : if (params.input == "pipewiregrab") {
98 : //
99 : // We rely on pipewiregrab for screen/window sharing on Wayland.
100 : // Because pipewiregrab is a "video source filter" (part of FFmpeg's libavfilter
101 : // library), its options must all be passed as part of the `input` string.
102 : //
103 0 : input = fmt::format("pipewiregrab=draw_mouse=1:fd={}:node={}", params.fd, params.node);
104 0 : JAMI_LOG("Attempting to open input {}", input);
105 : //
106 : // In all other cases, we use the `options_` AVDictionary to pass options to FFmpeg.
107 : //
108 : // NOTE: We rely on the "lavfi" virtual input device to read pipewiregrab's output
109 : // and create a corresponding stream (cf. the getDeviceParams function in
110 : // daemon/src/media/video/v4l2/video_device_impl.cpp). The `options_` dictionary
111 : // could be used to set lavfi's parameters if that was ever needed, but it isn't at
112 : // the moment. (Doc: https://ffmpeg.org/ffmpeg-devices.html#lavfi)
113 : //
114 : } else {
115 405 : if (params.width and params.height) {
116 0 : auto sizeStr = fmt::format("{}x{}", params.width, params.height);
117 0 : av_dict_set(&options_, "video_size", sizeStr.c_str(), 0);
118 0 : }
119 :
120 405 : if (params.framerate) {
121 : #ifdef _WIN32
122 : // On windows, framerate settings don't reduce to avrational values
123 : // that correspond to valid video device formats.
124 : // e.g. A the rational<double>(10000000, 333333) or 30.000030000
125 : // will be reduced by av_reduce to 999991/33333 or 30.00003000003
126 : // which cause the device opening routine to fail.
127 : // So we treat this imprecise reduction and adjust the value,
128 : // or let dshow choose the framerate, which is, unfortunately,
129 : // NOT the highest according to our experimentations.
130 : auto framerate {params.framerate.real()};
131 : framerate = params.framerate.numerator() / (params.framerate.denominator() + 0.5);
132 : if (params.framerate.denominator() != 4999998)
133 : av_dict_set(&options_, "framerate", jami::to_string(framerate).c_str(), 0);
134 : #else
135 1 : av_dict_set(&options_, "framerate", jami::to_string(params.framerate.real()).c_str(), 0);
136 : #endif
137 : }
138 :
139 405 : if (params.offset_x || params.offset_y) {
140 0 : av_dict_set(&options_, "offset_x", std::to_string(params.offset_x).c_str(), 0);
141 0 : av_dict_set(&options_, "offset_y", std::to_string(params.offset_y).c_str(), 0);
142 : }
143 405 : if (params.channel)
144 0 : av_dict_set(&options_, "channel", std::to_string(params.channel).c_str(), 0);
145 405 : av_dict_set(&options_, "loop", params.loop.c_str(), 0);
146 405 : av_dict_set(&options_, "sdp_flags", params.sdp_flags.c_str(), 0);
147 :
148 : // Set jitter buffer options
149 405 : av_dict_set(&options_, "reorder_queue_size", std::to_string(jitterBufferMaxSize_).c_str(), 0);
150 405 : auto us = std::chrono::duration_cast<std::chrono::microseconds>(jitterBufferMaxDelay_).count();
151 405 : av_dict_set(&options_, "max_delay", std::to_string(us).c_str(), 0);
152 :
153 405 : if (!params.pixel_format.empty()) {
154 0 : av_dict_set(&options_, "pixel_format", params.pixel_format.c_str(), 0);
155 : }
156 405 : if (!params.window_id.empty()) {
157 0 : av_dict_set(&options_, "window_id", params.window_id.c_str(), 0);
158 : }
159 405 : av_dict_set(&options_, "draw_mouse", "1", 0);
160 405 : av_dict_set(&options_, "is_area", std::to_string(params.is_area).c_str(), 0);
161 :
162 : #if defined(__APPLE__) && TARGET_OS_MAC
163 : input = params.name;
164 : #else
165 405 : input = params.input;
166 : #endif
167 :
168 1215 : JAMI_LOG("Attempting to open input {} with format {}, pixel format {}, size {}x{}, rate {}",
169 : input,
170 : params.format,
171 : params.pixel_format,
172 : params.width,
173 : params.height,
174 : params.framerate.real());
175 : }
176 :
177 : // Ask FFmpeg to open the input using the options set above
178 405 : av_opt_set_int(
179 405 : inputCtx_,
180 : "fpsprobesize",
181 : 1,
182 : AV_OPT_SEARCH_CHILDREN); // Don't waste time fetching framerate when finding stream info
183 405 : int ret = avformat_open_input(&inputCtx_, input.c_str(), iformat, options_ ? &options_ : NULL);
184 :
185 405 : if (ret) {
186 174 : JAMI_ERROR("avformat_open_input failed: {}", libav_utils::getError(ret));
187 347 : } else if (inputCtx_->nb_streams > 0 && inputCtx_->streams[0]->codecpar) {
188 347 : baseWidth_ = inputCtx_->streams[0]->codecpar->width;
189 347 : baseHeight_ = inputCtx_->streams[0]->codecpar->height;
190 1041 : JAMI_LOG("Opened input Using format {:s} and resolution {:d}x{:d}",
191 : params.format, baseWidth_, baseHeight_);
192 : }
193 :
194 405 : return ret;
195 405 : }
196 :
197 : int64_t
198 10 : MediaDemuxer::getDuration() const
199 : {
200 10 : return inputCtx_->duration;
201 : }
202 :
203 : bool
204 9 : MediaDemuxer::seekFrame(int, int64_t timestamp)
205 : {
206 9 : if (av_seek_frame(inputCtx_, -1, timestamp, AVSEEK_FLAG_BACKWARD) >= 0) {
207 9 : clearFrames();
208 9 : return true;
209 : }
210 0 : return false;
211 : }
212 :
213 : void
214 347 : MediaDemuxer::findStreamInfo()
215 : {
216 347 : if (not streamInfoFound_) {
217 347 : inputCtx_->max_analyze_duration = 30 * AV_TIME_BASE;
218 : int err;
219 347 : if ((err = avformat_find_stream_info(inputCtx_, nullptr)) < 0) {
220 0 : JAMI_ERR() << "Unable to find stream info: " << libav_utils::getError(err);
221 : }
222 347 : streamInfoFound_ = true;
223 : }
224 347 : }
225 :
226 : int
227 358 : MediaDemuxer::selectStream(AVMediaType type)
228 : {
229 358 : auto sti = av_find_best_stream(inputCtx_, type, -1, -1, nullptr, 0);
230 358 : if (type == AVMEDIA_TYPE_VIDEO && sti >= 0) {
231 156 : auto st = inputCtx_->streams[sti];
232 156 : auto disposition = st->disposition;
233 156 : if (disposition & AV_DISPOSITION_ATTACHED_PIC) {
234 1 : JAMI_DBG("Skipping attached picture stream");
235 1 : sti = -1;
236 : }
237 : }
238 358 : return sti;
239 : }
240 :
241 : void
242 355 : MediaDemuxer::setInterruptCallback(int (*cb)(void*), void* opaque)
243 : {
244 355 : if (cb) {
245 355 : inputCtx_->interrupt_callback.callback = cb;
246 355 : inputCtx_->interrupt_callback.opaque = opaque;
247 : } else {
248 0 : inputCtx_->interrupt_callback.callback = 0;
249 : }
250 355 : }
251 : void
252 11 : MediaDemuxer::setNeedFrameCb(std::function<void()> cb)
253 : {
254 11 : needFrameCb_ = std::move(cb);
255 11 : }
256 :
257 : void
258 11 : MediaDemuxer::setFileFinishedCb(std::function<void(bool)> cb)
259 : {
260 11 : fileFinishedCb_ = std::move(cb);
261 11 : }
262 :
263 : void
264 9 : MediaDemuxer::clearFrames()
265 : {
266 : {
267 9 : std::lock_guard lk {videoBufferMutex_};
268 9 : while (!videoBuffer_.empty()) {
269 0 : videoBuffer_.pop();
270 : }
271 9 : }
272 : {
273 9 : std::lock_guard lk {audioBufferMutex_};
274 9 : while (!audioBuffer_.empty()) {
275 0 : audioBuffer_.pop();
276 : }
277 9 : }
278 9 : }
279 :
280 : bool
281 0 : MediaDemuxer::emitFrame(bool isAudio)
282 : {
283 0 : if (isAudio) {
284 0 : return pushFrameFrom(audioBuffer_, isAudio, audioBufferMutex_);
285 : } else {
286 0 : return pushFrameFrom(videoBuffer_, isAudio, videoBufferMutex_);
287 : }
288 : }
289 :
290 : bool
291 0 : MediaDemuxer::pushFrameFrom(
292 : std::queue<std::unique_ptr<AVPacket, std::function<void(AVPacket*)>>>& buffer,
293 : bool isAudio,
294 : std::mutex& mutex)
295 : {
296 0 : std::unique_lock lock(mutex);
297 0 : if (buffer.empty()) {
298 0 : if (currentState_ == MediaDemuxer::CurrentState::Finished) {
299 0 : fileFinishedCb_(isAudio);
300 : } else {
301 0 : needFrameCb_();
302 : }
303 0 : return false;
304 : }
305 0 : auto packet = std::move(buffer.front());
306 0 : if (!packet) {
307 0 : return false;
308 : }
309 0 : auto streamIndex = packet->stream_index;
310 0 : if (static_cast<unsigned>(streamIndex) >= streams_.size() || streamIndex < 0) {
311 0 : return false;
312 : }
313 0 : if (auto& cb = streams_[streamIndex]) {
314 0 : buffer.pop();
315 0 : lock.unlock();
316 0 : cb(*packet.get());
317 : }
318 0 : return true;
319 0 : }
320 :
321 : MediaDemuxer::Status
322 204605208 : MediaDemuxer::demuxe()
323 : {
324 : auto packet = std::unique_ptr<AVPacket, std::function<void(AVPacket*)>>(av_packet_alloc(),
325 204605208 : [](AVPacket* p) {
326 204605208 : if (p)
327 204605208 : av_packet_free(
328 : &p);
329 204605208 : });
330 :
331 204605208 : int ret = av_read_frame(inputCtx_, packet.get());
332 204605208 : if (ret == AVERROR(EAGAIN)) {
333 0 : return Status::Success;
334 204605208 : } else if (ret == AVERROR_EOF) {
335 204604453 : return Status::EndOfFile;
336 755 : } else if (ret < 0) {
337 0 : JAMI_ERR("Unable to read frame: %s\n", libav_utils::getError(ret).c_str());
338 0 : return Status::ReadError;
339 : }
340 :
341 755 : auto streamIndex = packet->stream_index;
342 755 : if (static_cast<unsigned>(streamIndex) >= streams_.size() || streamIndex < 0) {
343 0 : return Status::Success;
344 : }
345 :
346 755 : AVStream* stream = inputCtx_->streams[streamIndex];
347 755 : if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
348 250 : std::lock_guard lk {videoBufferMutex_};
349 250 : videoBuffer_.push(std::move(packet));
350 250 : if (videoBuffer_.size() >= 90) {
351 0 : return Status::ReadBufferOverflow;
352 : }
353 250 : } else {
354 505 : std::lock_guard lk {audioBufferMutex_};
355 505 : audioBuffer_.push(std::move(packet));
356 505 : if (audioBuffer_.size() >= 300) {
357 0 : return Status::ReadBufferOverflow;
358 : }
359 505 : }
360 755 : return Status::Success;
361 204605208 : }
362 :
363 : void
364 670 : MediaDemuxer::setIOContext(MediaIOHandle* ioctx)
365 : {
366 670 : inputCtx_->pb = ioctx->getContext();
367 670 : }
368 :
369 : MediaDemuxer::Status
370 5371 : MediaDemuxer::decode()
371 : {
372 5371 : if (inputParams_.format == "x11grab" || inputParams_.format == "dxgigrab") {
373 0 : auto ret = inputCtx_->iformat->read_header(inputCtx_);
374 0 : if (ret == AVERROR_EXTERNAL) {
375 0 : JAMI_ERR("Unable to read frame: %s\n", libav_utils::getError(ret).c_str());
376 0 : return Status::ReadError;
377 : }
378 0 : auto codecpar = inputCtx_->streams[0]->codecpar;
379 0 : if (baseHeight_ != codecpar->height || baseWidth_ != codecpar->width) {
380 0 : baseHeight_ = codecpar->height;
381 0 : baseWidth_ = codecpar->width;
382 0 : inputParams_.height = ((baseHeight_ >> 3) << 3);
383 0 : inputParams_.width = ((baseWidth_ >> 3) << 3);
384 0 : return Status::RestartRequired;
385 : }
386 : }
387 :
388 5371 : libjami::PacketBuffer packet(av_packet_alloc());
389 5371 : int ret = av_read_frame(inputCtx_, packet.get());
390 5371 : if (ret == AVERROR(EAGAIN)) {
391 : /*no data available. Calculate time until next frame.
392 : We do not use the emulated frame mechanism from the decoder because it will affect all
393 : platforms. With the current implementation, the demuxer will be waiting just in case when
394 : av_read_frame returns EAGAIN. For some platforms, av_read_frame is blocking and it will
395 : never happen.
396 : */
397 0 : if (inputParams_.framerate.numerator() == 0)
398 0 : return Status::Success;
399 0 : rational<double> frameTime = 1e6 / inputParams_.framerate;
400 0 : int64_t timeToSleep = lastReadPacketTime_ - av_gettime_relative()
401 0 : + frameTime.real<int64_t>();
402 0 : if (timeToSleep <= 0) {
403 0 : return Status::Success;
404 : }
405 0 : std::this_thread::sleep_for(std::chrono::microseconds(timeToSleep));
406 0 : return Status::Success;
407 5371 : } else if (ret == AVERROR_EOF) {
408 119 : return Status::EndOfFile;
409 5252 : } else if (ret == AVERROR(EACCES)) {
410 0 : return Status::RestartRequired;
411 5252 : } else if (ret < 0) {
412 0 : auto media = inputCtx_->streams[0]->codecpar->codec_type;
413 0 : const auto type = media == AVMediaType::AVMEDIA_TYPE_AUDIO
414 0 : ? "AUDIO"
415 0 : : (media == AVMediaType::AVMEDIA_TYPE_VIDEO ? "VIDEO" : "UNSUPPORTED");
416 0 : JAMI_ERR("Unable to read [%s] frame: %s\n", type, libav_utils::getError(ret).c_str());
417 0 : return Status::ReadError;
418 : }
419 :
420 5252 : auto streamIndex = packet->stream_index;
421 5252 : if (static_cast<unsigned>(streamIndex) >= streams_.size() || streamIndex < 0) {
422 0 : return Status::Success;
423 : }
424 :
425 5252 : lastReadPacketTime_ = av_gettime_relative();
426 :
427 5252 : auto& cb = streams_[streamIndex];
428 5252 : if (cb) {
429 5252 : DecodeStatus ret = cb(*packet.get());
430 5252 : if (ret == DecodeStatus::FallBack)
431 0 : return Status::FallBack;
432 : }
433 5252 : return Status::Success;
434 5371 : }
435 :
436 0 : MediaDecoder::MediaDecoder(const std::shared_ptr<MediaDemuxer>& demuxer, int index)
437 0 : : demuxer_(demuxer)
438 0 : , avStream_(demuxer->getStream(index))
439 : {
440 0 : demuxer->setStreamCallback(index, [this](AVPacket& packet) { return decode(packet); });
441 0 : setupStream();
442 0 : }
443 :
444 20 : MediaDecoder::MediaDecoder(const std::shared_ptr<MediaDemuxer>& demuxer,
445 : int index,
446 20 : MediaObserver observer)
447 20 : : demuxer_(demuxer)
448 20 : , avStream_(demuxer->getStream(index))
449 40 : , callback_(std::move(observer))
450 : {
451 20 : demuxer->setStreamCallback(index, [this](AVPacket& packet) { return decode(packet); });
452 20 : setupStream();
453 20 : }
454 :
455 : bool
456 0 : MediaDecoder::emitFrame(bool isAudio)
457 : {
458 0 : return demuxer_->emitFrame(isAudio);
459 : }
460 :
461 0 : MediaDecoder::MediaDecoder()
462 0 : : demuxer_(new MediaDemuxer)
463 0 : {}
464 :
465 394 : MediaDecoder::MediaDecoder(MediaObserver o)
466 394 : : demuxer_(new MediaDemuxer)
467 394 : , callback_(std::move(o))
468 394 : {}
469 :
470 414 : MediaDecoder::~MediaDecoder()
471 : {
472 : #ifdef RING_ACCEL
473 414 : if (decoderCtx_ && decoderCtx_->hw_device_ctx)
474 0 : av_buffer_unref(&decoderCtx_->hw_device_ctx);
475 : #endif
476 414 : if (decoderCtx_)
477 356 : avcodec_free_context(&decoderCtx_);
478 414 : }
479 :
480 : void
481 18 : MediaDecoder::flushBuffers()
482 : {
483 18 : avcodec_flush_buffers(decoderCtx_);
484 18 : }
485 :
486 : int
487 394 : MediaDecoder::openInput(const DeviceParams& p)
488 : {
489 394 : return demuxer_->openInput(p);
490 : }
491 :
492 : void
493 355 : MediaDecoder::setInterruptCallback(int (*cb)(void*), void* opaque)
494 : {
495 355 : demuxer_->setInterruptCallback(cb, opaque);
496 355 : }
497 :
498 : void
499 670 : MediaDecoder::setIOContext(MediaIOHandle* ioctx)
500 : {
501 670 : demuxer_->setIOContext(ioctx);
502 670 : }
503 :
504 : int
505 336 : MediaDecoder::setup(AVMediaType type)
506 : {
507 336 : demuxer_->findStreamInfo();
508 336 : auto stream = demuxer_->selectStream(type);
509 336 : if (stream < 0) {
510 0 : JAMI_ERR("No stream found for type %i", static_cast<int>(type));
511 0 : return -1;
512 : }
513 336 : avStream_ = demuxer_->getStream(stream);
514 336 : if (avStream_ == nullptr) {
515 0 : JAMI_ERR("No stream found at index %i", stream);
516 0 : return -1;
517 : }
518 5588 : demuxer_->setStreamCallback(stream, [this](AVPacket& packet) { return decode(packet); });
519 336 : return setupStream();
520 : }
521 :
522 : int
523 356 : MediaDecoder::setupStream()
524 : {
525 356 : int ret = 0;
526 356 : avcodec_free_context(&decoderCtx_);
527 :
528 356 : if (prepareDecoderContext() < 0)
529 0 : return -1; // failed
530 :
531 : #ifdef RING_ACCEL
532 : // if there was a fallback to software decoding, do not enable accel
533 : // it has been disabled already by the video_receive_thread/video_input
534 356 : enableAccel_ &= Manager::instance().videoPreferences.getDecodingAccelerated();
535 :
536 356 : if (enableAccel_ and not fallback_) {
537 356 : auto APIs = video::HardwareAccel::getCompatibleAccel(decoderCtx_->codec_id,
538 356 : decoderCtx_->width,
539 356 : decoderCtx_->height,
540 356 : CODEC_DECODER);
541 801 : for (const auto& it : APIs) {
542 445 : accel_ = std::make_unique<video::HardwareAccel>(it); // save accel
543 445 : auto ret = accel_->initAPI(false, nullptr);
544 445 : if (ret < 0) {
545 445 : accel_.reset();
546 445 : continue;
547 : }
548 0 : if (prepareDecoderContext() < 0)
549 0 : return -1; // failed
550 0 : accel_->setDetails(decoderCtx_);
551 0 : decoderCtx_->opaque = accel_.get();
552 0 : decoderCtx_->pix_fmt = accel_->getFormat();
553 0 : if (avcodec_open2(decoderCtx_, inputDecoder_, &options_) < 0) {
554 : // Failed to open codec
555 0 : JAMI_WARN("Fail to open hardware decoder for %s with %s",
556 : avcodec_get_name(decoderCtx_->codec_id),
557 : it.getName().c_str());
558 0 : avcodec_free_context(&decoderCtx_);
559 0 : decoderCtx_ = nullptr;
560 0 : accel_.reset();
561 0 : continue;
562 : } else {
563 : // Succeed to open codec
564 0 : JAMI_WARN("Using hardware decoding for %s with %s",
565 : avcodec_get_name(decoderCtx_->codec_id),
566 : it.getName().c_str());
567 0 : break;
568 : }
569 : }
570 356 : }
571 : #endif
572 :
573 1068 : JAMI_LOG("Using {} ({}) decoder for {}",
574 : inputDecoder_->long_name,
575 : inputDecoder_->name,
576 : av_get_media_type_string(avStream_->codecpar->codec_type));
577 356 : decoderCtx_->thread_count = std::max(1u, std::min(8u, std::thread::hardware_concurrency() / 2));
578 356 : if (emulateRate_)
579 0 : JAMI_DBG() << "Using framerate emulation";
580 356 : startTime_ = av_gettime(); // used to set pts after decoding, and for rate emulation
581 :
582 : #ifdef RING_ACCEL
583 356 : if (!accel_) {
584 356 : JAMI_WARN("Not using hardware decoding for %s", avcodec_get_name(decoderCtx_->codec_id));
585 356 : ret = avcodec_open2(decoderCtx_, inputDecoder_, nullptr);
586 : }
587 : #else
588 : ret = avcodec_open2(decoderCtx_, inputDecoder_, nullptr);
589 : #endif
590 356 : if (ret < 0) {
591 0 : JAMI_ERR() << "Unable to open codec: " << libav_utils::getError(ret);
592 0 : return -1;
593 : }
594 :
595 356 : return 0;
596 : }
597 :
598 : int
599 356 : MediaDecoder::prepareDecoderContext()
600 : {
601 356 : inputDecoder_ = findDecoder(avStream_->codecpar->codec_id);
602 356 : if (!inputDecoder_) {
603 0 : JAMI_ERROR("Unsupported codec");
604 0 : return -1;
605 : }
606 :
607 356 : decoderCtx_ = avcodec_alloc_context3(inputDecoder_);
608 356 : if (!decoderCtx_) {
609 0 : JAMI_ERROR("Failed to create decoder context");
610 0 : return -1;
611 : }
612 356 : avcodec_parameters_to_context(decoderCtx_, avStream_->codecpar);
613 356 : width_ = decoderCtx_->width;
614 356 : height_ = decoderCtx_->height;
615 356 : decoderCtx_->framerate = avStream_->avg_frame_rate;
616 356 : if (avStream_->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
617 155 : if (decoderCtx_->framerate.num == 0 || decoderCtx_->framerate.den == 0)
618 99 : decoderCtx_->framerate = inputParams_.framerate;
619 155 : if (decoderCtx_->framerate.num == 0 || decoderCtx_->framerate.den == 0)
620 99 : decoderCtx_->framerate = {30, 1};
621 : }
622 201 : else if (avStream_->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
623 201 : if (decoderCtx_->codec_id == AV_CODEC_ID_OPUS) {
624 199 : av_opt_set_int(decoderCtx_, "decode_fec", fecEnabled_ ? 1 : 0, AV_OPT_SEARCH_CHILDREN);
625 : }
626 201 : auto format = libav_utils::choose_sample_fmt_default(inputDecoder_, Manager::instance().getRingBufferPool().getInternalAudioFormat().sampleFormat);
627 201 : decoderCtx_->sample_fmt = format;
628 201 : decoderCtx_->request_sample_fmt = format;
629 : }
630 356 : return 0;
631 : }
632 :
633 : void
634 56 : MediaDecoder::updateStartTime(int64_t startTime)
635 : {
636 56 : startTime_ = startTime;
637 56 : }
638 :
639 : DecodeStatus
640 5252 : MediaDecoder::decode(AVPacket& packet)
641 : {
642 5252 : int frameFinished = 0;
643 5252 : auto ret = avcodec_send_packet(decoderCtx_, &packet);
644 5252 : if (ret < 0 && ret != AVERROR(EAGAIN)) {
645 : #ifdef RING_ACCEL
646 0 : if (accel_) {
647 0 : JAMI_WARN("Decoding error falling back to software");
648 0 : fallback_ = true;
649 0 : accel_.reset();
650 0 : avcodec_flush_buffers(decoderCtx_);
651 0 : setupStream();
652 0 : return DecodeStatus::FallBack;
653 : }
654 : #endif
655 0 : avcodec_flush_buffers(decoderCtx_);
656 0 : return ret == AVERROR_EOF ? DecodeStatus::Success : DecodeStatus::DecodeError;
657 : }
658 :
659 : #ifdef ENABLE_VIDEO
660 5252 : auto f = (inputDecoder_->type == AVMEDIA_TYPE_VIDEO)
661 5248 : ? std::static_pointer_cast<MediaFrame>(std::make_shared<VideoFrame>())
662 10504 : : std::static_pointer_cast<MediaFrame>(std::make_shared<AudioFrame>());
663 : #else
664 : auto f = std::static_pointer_cast<MediaFrame>(std::make_shared<AudioFrame>());
665 : #endif
666 5252 : auto frame = f->pointer();
667 5252 : ret = avcodec_receive_frame(decoderCtx_, frame);
668 : // time_base is not set in AVCodecContext for decoding
669 : // fail to set it causes pts to be incorrectly computed down in the function
670 5252 : if (inputDecoder_->type == AVMEDIA_TYPE_VIDEO) {
671 5248 : decoderCtx_->time_base.num = decoderCtx_->framerate.den;
672 5248 : decoderCtx_->time_base.den = decoderCtx_->framerate.num;
673 : } else {
674 4 : decoderCtx_->time_base.num = 1;
675 4 : decoderCtx_->time_base.den = decoderCtx_->sample_rate;
676 : }
677 5252 : frame->time_base = decoderCtx_->time_base;
678 5252 : if (resolutionChangedCallback_) {
679 5248 : if (decoderCtx_->width != width_ or decoderCtx_->height != height_) {
680 0 : JAMI_DBG("Resolution changed from %dx%d to %dx%d",
681 : width_,
682 : height_,
683 : decoderCtx_->width,
684 : decoderCtx_->height);
685 0 : width_ = decoderCtx_->width;
686 0 : height_ = decoderCtx_->height;
687 0 : resolutionChangedCallback_(width_, height_);
688 : }
689 : }
690 5252 : if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
691 0 : return DecodeStatus::DecodeError;
692 : }
693 5252 : if (ret >= 0)
694 5025 : frameFinished = 1;
695 :
696 5252 : if (frameFinished) {
697 5025 : if (inputDecoder_->type == AVMEDIA_TYPE_VIDEO)
698 5021 : frame->format = (AVPixelFormat) correctPixFmt(frame->format);
699 5025 : auto packetTimestamp = frame->pts; // in stream time base
700 5025 : frame->pts = av_rescale_q_rnd(av_gettime() - startTime_,
701 : {1, AV_TIME_BASE},
702 5025 : decoderCtx_->time_base,
703 : static_cast<AVRounding>(AV_ROUND_NEAR_INF
704 : | AV_ROUND_PASS_MINMAX));
705 5025 : lastTimestamp_ = frame->pts;
706 5025 : if (emulateRate_ and packetTimestamp != AV_NOPTS_VALUE) {
707 0 : auto startTime = avStream_->start_time == AV_NOPTS_VALUE ? 0 : avStream_->start_time;
708 0 : rational<double> frame_time = rational<double>(getTimeBase())
709 0 : * rational<double>(packetTimestamp - startTime);
710 0 : auto target_relative = static_cast<std::int64_t>(frame_time.real() * 1e6);
711 0 : auto target_absolute = startTime_ + target_relative;
712 0 : if (target_relative < seekTime_) {
713 0 : return DecodeStatus::Success;
714 : }
715 : // required frame found. Reset seek time
716 0 : if (target_relative >= seekTime_) {
717 0 : resetSeekTime();
718 : }
719 0 : auto now = av_gettime();
720 0 : if (target_absolute > now) {
721 0 : std::this_thread::sleep_for(std::chrono::microseconds(target_absolute - now));
722 : }
723 : }
724 :
725 5025 : if (callback_)
726 5025 : callback_(std::move(f));
727 :
728 5025 : if (contextCallback_ && firstDecode_.load()) {
729 31 : firstDecode_.exchange(false);
730 31 : contextCallback_();
731 : }
732 5025 : return DecodeStatus::FrameFinished;
733 : }
734 227 : return DecodeStatus::Success;
735 5252 : }
736 :
737 : void
738 18 : MediaDecoder::setSeekTime(int64_t time)
739 : {
740 18 : seekTime_ = time;
741 18 : }
742 :
743 : MediaDemuxer::Status
744 5371 : MediaDecoder::decode()
745 : {
746 5371 : auto ret = demuxer_->decode();
747 5371 : if (ret == MediaDemuxer::Status::RestartRequired) {
748 0 : avcodec_flush_buffers(decoderCtx_);
749 0 : setupStream();
750 0 : ret = MediaDemuxer::Status::EndOfFile;
751 : }
752 5371 : return ret;
753 : }
754 :
755 : #ifdef ENABLE_VIDEO
756 : #ifdef RING_ACCEL
757 : void
758 0 : MediaDecoder::enableAccel(bool enableAccel)
759 : {
760 0 : enableAccel_ = enableAccel;
761 0 : emitSignal<libjami::ConfigurationSignal::HardwareDecodingChanged>(enableAccel_);
762 0 : if (!enableAccel) {
763 0 : accel_.reset();
764 0 : if (decoderCtx_)
765 0 : decoderCtx_->opaque = nullptr;
766 : }
767 0 : }
768 : #endif
769 :
770 : DecodeStatus
771 0 : MediaDecoder::flush()
772 : {
773 : AVPacket inpacket;
774 0 : av_init_packet(&inpacket);
775 :
776 0 : int frameFinished = 0;
777 0 : int ret = 0;
778 0 : ret = avcodec_send_packet(decoderCtx_, &inpacket);
779 0 : if (ret < 0 && ret != AVERROR(EAGAIN))
780 0 : return ret == AVERROR_EOF ? DecodeStatus::Success : DecodeStatus::DecodeError;
781 :
782 0 : auto result = std::make_shared<MediaFrame>();
783 0 : ret = avcodec_receive_frame(decoderCtx_, result->pointer());
784 0 : if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
785 0 : return DecodeStatus::DecodeError;
786 0 : if (ret >= 0)
787 0 : frameFinished = 1;
788 :
789 0 : if (frameFinished) {
790 0 : av_packet_unref(&inpacket);
791 0 : if (callback_)
792 0 : callback_(std::move(result));
793 0 : return DecodeStatus::FrameFinished;
794 : }
795 :
796 0 : return DecodeStatus::Success;
797 0 : }
798 : #endif // ENABLE_VIDEO
799 :
800 : int
801 165 : MediaDecoder::getWidth() const
802 : {
803 165 : return decoderCtx_ ? decoderCtx_->width : 0;
804 : }
805 :
806 : int
807 165 : MediaDecoder::getHeight() const
808 : {
809 165 : return decoderCtx_ ? decoderCtx_->height : 0;
810 : }
811 :
812 : std::string
813 0 : MediaDecoder::getDecoderName() const
814 : {
815 0 : return decoderCtx_ ? decoderCtx_->codec->name : "";
816 : }
817 :
818 : rational<double>
819 10 : MediaDecoder::getFps() const
820 : {
821 10 : return {(double) avStream_->avg_frame_rate.num, (double) avStream_->avg_frame_rate.den};
822 : }
823 :
824 : rational<unsigned>
825 0 : MediaDecoder::getTimeBase() const
826 : {
827 0 : return {(unsigned) avStream_->time_base.num, (unsigned) avStream_->time_base.den};
828 : }
829 :
830 : AVPixelFormat
831 10 : MediaDecoder::getPixelFormat() const
832 : {
833 10 : return decoderCtx_->pix_fmt;
834 : }
835 :
836 : int
837 5021 : MediaDecoder::correctPixFmt(int input_pix_fmt)
838 : {
839 : // https://ffmpeg.org/pipermail/ffmpeg-user/2014-February/020152.html
840 : int pix_fmt;
841 5021 : switch (input_pix_fmt) {
842 0 : case AV_PIX_FMT_YUVJ420P:
843 0 : pix_fmt = AV_PIX_FMT_YUV420P;
844 0 : break;
845 0 : case AV_PIX_FMT_YUVJ422P:
846 0 : pix_fmt = AV_PIX_FMT_YUV422P;
847 0 : break;
848 0 : case AV_PIX_FMT_YUVJ444P:
849 0 : pix_fmt = AV_PIX_FMT_YUV444P;
850 0 : break;
851 0 : case AV_PIX_FMT_YUVJ440P:
852 0 : pix_fmt = AV_PIX_FMT_YUV440P;
853 0 : break;
854 5021 : default:
855 5021 : pix_fmt = input_pix_fmt;
856 5021 : break;
857 : }
858 5021 : return pix_fmt;
859 : }
860 :
861 : MediaStream
862 206 : MediaDecoder::getStream(std::string name) const
863 : {
864 206 : if (!decoderCtx_) {
865 128 : JAMI_WARN("No decoder context");
866 128 : return {};
867 : }
868 78 : auto ms = MediaStream(name, decoderCtx_, lastTimestamp_);
869 : #ifdef RING_ACCEL
870 : // accel_ is null if not using accelerated codecs
871 78 : if (accel_)
872 2 : ms.format = accel_->getSoftwareFormat();
873 : #endif
874 78 : return ms;
875 78 : }
876 :
877 : } // namespace jami
|