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