mirror of
https://git.jami.net/savoirfairelinux/jami-daemon.git
synced 2025-08-12 22:09:25 +08:00
recorder: use video input as source
MediaRecorder no longer uses VideoSender (encoder) as a source for its local video and will directly use VideoInput (decoder), as it is earlier in the pipeline. This is the first step to support switching inputs while recording. Change-Id: Ia163efa3b20a349a93fc7b05213ec5e00de1704e Reviewed-by: Sebastien Blin <sebastien.blin@savoirfairelinux.com>
This commit is contained in:

committed by
Sébastien Blin

parent
33293017c2
commit
f8bd331d66
@ -295,16 +295,17 @@ MediaDecoder::decode(VideoFrame& result)
|
||||
static_cast<AVRounding>(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
|
||||
|
||||
if (auto rec = recorder_.lock()) {
|
||||
bool fromPeer = (inputCtx_->iformat->name == std::string("sdp"));
|
||||
if (!recordingStarted_) {
|
||||
auto ms = MediaStream("", decoderCtx_, frame->pts);
|
||||
ms.format = frame->format; // might not match avStream_ if accel is used
|
||||
if (rec->addStream(true, true, ms) >= 0)
|
||||
if (rec->addStream(true, fromPeer, ms) >= 0)
|
||||
recordingStarted_ = true;
|
||||
else
|
||||
recorder_ = std::weak_ptr<MediaRecorder>();
|
||||
}
|
||||
if (recordingStarted_)
|
||||
rec->recordData(frame, true, true);
|
||||
rec->recordData(frame, true, fromPeer);
|
||||
}
|
||||
|
||||
if (emulateRate_ and packetTimestamp != AV_NOPTS_VALUE) {
|
||||
|
@ -443,6 +443,18 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
|
||||
nb_frames -= frame->nb_samples;
|
||||
offset_ptr += frame->nb_samples * buffer.channels();
|
||||
|
||||
if (auto rec = recorder_.lock()) {
|
||||
if (!recordingStarted_) {
|
||||
auto ms = MediaStream("", encoders_[currentStreamIdx_], frame->pts);
|
||||
if (rec->addStream(false, false, ms) >= 0)
|
||||
recordingStarted_ = true;
|
||||
else
|
||||
recorder_ = std::weak_ptr<MediaRecorder>();
|
||||
}
|
||||
if (recordingStarted_)
|
||||
rec->recordData(frame, false, false);
|
||||
}
|
||||
|
||||
encode(frame, currentStreamIdx_);
|
||||
av_frame_free(&frame);
|
||||
}
|
||||
@ -460,19 +472,6 @@ MediaEncoder::encode(AVFrame* frame, int streamIdx)
|
||||
pkt.data = nullptr; // packet data will be allocated by the encoder
|
||||
pkt.size = 0;
|
||||
|
||||
if (auto rec = recorder_.lock()) {
|
||||
bool isVideo = encoderCtx->codec_type == AVMEDIA_TYPE_VIDEO;
|
||||
if (!recordingStarted_) {
|
||||
auto ms = MediaStream("", encoderCtx, frame->pts);
|
||||
if (rec->addStream(isVideo, false, ms) >= 0)
|
||||
recordingStarted_ = true;
|
||||
else
|
||||
recorder_ = std::weak_ptr<MediaRecorder>();
|
||||
}
|
||||
if (recordingStarted_)
|
||||
rec->recordData(frame, isVideo, false);
|
||||
}
|
||||
|
||||
ret = avcodec_send_frame(encoderCtx, frame);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
@ -587,4 +587,11 @@ VideoInput::foundDecOpts(const DeviceParams& params)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VideoInput::startRecorder(std::shared_ptr<MediaRecorder>& rec)
|
||||
{
|
||||
if (decoder_)
|
||||
decoder_->startRecorder(rec);
|
||||
}
|
||||
|
||||
}} // namespace ring::video
|
||||
|
@ -42,6 +42,7 @@
|
||||
|
||||
namespace ring {
|
||||
class MediaDecoder;
|
||||
class MediaRecorder;
|
||||
}
|
||||
|
||||
namespace ring { namespace video {
|
||||
@ -88,6 +89,8 @@ public:
|
||||
void releaseFrame(void *frame);
|
||||
#endif
|
||||
|
||||
void startRecorder(std::shared_ptr<MediaRecorder>& rec);
|
||||
|
||||
private:
|
||||
NON_COPYABLE(VideoInput);
|
||||
|
||||
|
@ -571,14 +571,12 @@ VideoRtpSession::startRecorder(std::shared_ptr<MediaRecorder>& rec)
|
||||
const constexpr int keyframes = 3;
|
||||
if (receiveThread_)
|
||||
receiveThread_->startRecorder(rec);
|
||||
if (sender_)
|
||||
sender_->startRecorder(rec);
|
||||
for (int i = 0; i < keyframes; ++i) {
|
||||
if (auto vidInput = std::static_pointer_cast<VideoInput>(videoLocal_))
|
||||
vidInput->startRecorder(rec);
|
||||
for (int i = 0; i < keyframes; ++i)
|
||||
if (receiveThread_)
|
||||
receiveThread_->triggerKeyFrameRequest();
|
||||
if (sender_)
|
||||
sender_->forceKeyFrame();
|
||||
}
|
||||
// TODO trigger keyframes for local video
|
||||
}
|
||||
|
||||
}} // namespace ring::video
|
||||
|
@ -106,11 +106,4 @@ VideoSender::useCodec(const ring::AccountVideoCodecInfo* codec) const
|
||||
return videoEncoder_->useCodec(codec);
|
||||
}
|
||||
|
||||
void
|
||||
VideoSender::startRecorder(std::shared_ptr<MediaRecorder>& rec)
|
||||
{
|
||||
if (videoEncoder_)
|
||||
videoEncoder_->startRecorder(rec);
|
||||
}
|
||||
|
||||
}} // namespace ring::video
|
||||
|
@ -35,7 +35,6 @@
|
||||
namespace ring {
|
||||
class SocketPair;
|
||||
struct AccountVideoCodecInfo;
|
||||
class MediaRecorder;
|
||||
}
|
||||
|
||||
namespace ring { namespace video {
|
||||
@ -63,8 +62,6 @@ public:
|
||||
|
||||
bool useCodec(const AccountVideoCodecInfo* codec) const;
|
||||
|
||||
void startRecorder(std::shared_ptr<MediaRecorder>& rec);
|
||||
|
||||
private:
|
||||
static constexpr int KEYFRAMES_AT_START {4}; // Number of keyframes to enforce at stream startup
|
||||
static constexpr unsigned KEY_FRAME_PERIOD {0}; // seconds before forcing a keyframe
|
||||
|
Reference in New Issue
Block a user