media_recorder.h 4.06 KB
Newer Older
1
/*
2
 *  Copyright (C) 2018-2019 Savoir-faire Linux Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 *  Author: Philippe Gorley <philippe.gorley@savoirfairelinux.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 */

#pragma once

#include "config.h"
24
#include "media_buffer.h"
25 26 27 28
#include "media_encoder.h"
#include "media_filter.h"
#include "media_stream.h"
#include "noncopyable.h"
29
#include "observer.h"
30 31 32 33

#include <map>
#include <memory>
#include <mutex>
34
#include <queue>
35 36 37 38
#include <stdexcept>
#include <string>
#include <utility>

Adrien Béraud's avatar
Adrien Béraud committed
39
namespace jami {
40

41
class MediaRecorder : public std::enable_shared_from_this<MediaRecorder>
42 43 44 45 46
{
public:
    MediaRecorder();
    ~MediaRecorder();

47 48 49 50
    /**
     * Gets whether or not the recorder is active.
     */
    bool isRecording() const;
51

52 53 54 55 56 57 58
    /**
     * Get file path of file to be recorded. Same path as sent to @setPath, but with
     * file extension appended.
     *
     * NOTE @audioOnly must be called to have the right extension.
     */
    std::string getPath() const;
59

60 61 62 63
    /**
     * Sets whether or not output file will have audio. Determines the extension of the
     * output file (.ogg or .webm).
     */
64 65
    void audioOnly(bool audioOnly);

66 67 68 69 70 71 72 73 74 75 76 77 78 79
    /**
     * Sets output file path.
     *
     * NOTE An empty path will put the output file in the working directory.
     */
    void setPath(const std::string& path);

    /**
     * Sets title and description metadata for the file. Uses default if either is empty.
     * Default title is "Conversation at %Y-%m-%d %H:%M:%S".
     * Default description is "Recorded with Jami https://jami.net".
     *
     * NOTE replaces %TIMESTAMP with time at start of recording
     */
80 81
    void setMetadata(const std::string& title, const std::string& desc);

82
    /**
83
     * Adds a stream to the recorder. Caller must then attach this to the media source.
84
     */
85 86 87 88 89 90
    Observer<std::shared_ptr<MediaFrame>>* addStream(const MediaStream& ms);

    /**
     * Gets the stream observer so the caller can detach it from the media source.
     */
    Observer<std::shared_ptr<MediaFrame>>* getStream(const std::string& name) const;
91

92 93 94 95
    /**
     * Starts the record. Streams must have been added using Observable::attach and
     * @addStream.
     */
96 97
    int startRecording();

98 99 100
    /**
     * Stops the record. Streams must be removed using Observable::detach afterwards.
     */
101 102 103 104 105
    void stopRecording();

private:
    NON_COPYABLE(MediaRecorder);

106
    struct StreamObserver;
107 108 109

    void onFrame(const std::string& name, const std::shared_ptr<MediaFrame>& frame);

110
    void flush();
111
    void reset();
112 113 114 115 116 117 118 119 120

    int initRecord();
    MediaStream setupVideoOutput();
    std::string buildVideoFilter(const std::vector<MediaStream>& peers, const MediaStream& local) const;
    MediaStream setupAudioOutput();
    std::string buildAudioFilter(const std::vector<MediaStream>& peers, const MediaStream& local) const;

    std::mutex mutex_; // protect against concurrent file writes

121
    std::map<std::string, std::unique_ptr<StreamObserver>> streams_;
122

123
    std::string path_;
124 125 126 127
    std::tm startTime_;
    std::string title_;
    std::string description_;

128 129 130
    std::unique_ptr<MediaEncoder> encoder_;
    std::unique_ptr<MediaFilter> videoFilter_;
    std::unique_ptr<MediaFilter> audioFilter_;
131

132 133
    bool hasAudio_ {false};
    bool hasVideo_ {false};
134 135 136 137 138
    int videoIdx_ = -1;
    int audioIdx_ = -1;
    bool isRecording_ = false;
    bool audioOnly_ = false;

139
    void filterAndEncode(MediaFilter* filter, int streamIdx);
140 141
};

Adrien Béraud's avatar
Adrien Béraud committed
142
}; // namespace jami