Blame view

trunk/src/app/srs_app_dvr.hpp 8.7 KB
1 2 3
/*
The MIT License (MIT)
4
Copyright (c) 2013-2015 SRS(simple-rtmp-server)
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
winlin authored
24 25
#ifndef SRS_APP_DVR_HPP
#define SRS_APP_DVR_HPP
26 27

/*
winlin authored
28
#include <srs_app_dvr.hpp>
29 30 31
*/
#include <srs_core.hpp>
32
#include <string>
33
#include <sstream>
34
35 36
#ifdef SRS_AUTO_DVR
winlin authored
37 38
class SrsSource;
class SrsRequest;
winlin authored
39
class SrsStream;
winlin authored
40
class SrsRtmpJitter;
winlin authored
41
class SrsOnMetaDataPacket;
42
class SrsSharedPtrMessage;
43
class SrsFileWriter;
44
class SrsFlvEncoder;
45
class SrsDvrPlan;
46
class SrsJsonAny;
47
class SrsJsonObject;
48
class SrsThread;
winlin authored
49
50 51
#include <srs_app_source.hpp>
#include <srs_app_reload.hpp>
52
#include <srs_app_async_call.hpp>
53
winlin authored
54
/**
55
* a piece of flv segment.
56
* when open segment, support start at 0 or not.
57
*/
58
class SrsFlvSegment : public ISrsReloadHandler
59
{
60 61 62 63 64 65 66 67 68 69 70 71 72 73
private:
    SrsRequest* req;
    SrsDvrPlan* plan;
private:
    /**
    * the underlayer dvr stream.
    * if close, the flv is reap and closed.
    * if open, new flv file is crote.
    */
    SrsFlvEncoder* enc;
    SrsRtmpJitter* jitter;
    SrsRtmpJitterAlgorithm jitter_algorithm;
    SrsFileWriter* fs;
private:
74 75 76 77 78 79 80 81 82 83 84
    /**
    * the offset of file for duration value.
    * the next 8 bytes is the double value.
    */
    int64_t duration_offset;
    /**
    * the offset of file for filesize value.
    * the next 8 bytes is the double value.
    */
    int64_t filesize_offset;
private:
85 86
    std::string tmp_flv_file;
private:
87
    /**
88
    * current segment flv file path.
89
    */
90
    std::string path;
91 92 93
    /**
    * whether current segment has keyframe.
    */
94
    bool has_keyframe;
95
    /**
96
    * current segment starttime, RTMP pkt time.
97
    */
98
    int64_t starttime;
99
    /**
100 101 102 103 104
    * current segment duration
    */
    int64_t duration;
    /**
    * stream start time, to generate atc pts. abs time.
105 106
    */
    int64_t stream_starttime;
107 108 109 110 111 112 113 114 115
    /**
    * stream duration, to generate atc segment.
    */
    int64_t stream_duration;
    /**
    * previous stream RTMP pkt time, used to calc the duration.
    * for the RTMP timestamp will overflow.
    */
    int64_t stream_previous_pkt_time;
116
public:
117
    SrsFlvSegment(SrsDvrPlan* p);
winlin authored
118 119
    virtual ~SrsFlvSegment();
public:
120 121 122
    /**
    * initialize the segment.
    */
123
    virtual int initialize(SrsRequest* r);
124 125 126 127 128 129 130
    /**
    * whether segment is overflow.
    */
    virtual bool is_overflow(int64_t max_duration);
    /**
    * open new segment file, timestamp start at 0 for fresh flv file.
    * @remark ignore when already open.
131
    * @param use_tmp_file whether use tmp file if possible.
132
    */
133
    virtual int open(bool use_tmp_file = true);
134 135 136 137 138 139 140 141
    /**
    * close current segment.
    * @remark ignore when already closed.
    */
    virtual int close();
    /**
    * write the metadata to segment.
    */
142
    virtual int write_metadata(SrsSharedPtrMessage* metadata);
143
    /**
144
    * @param shared_audio, directly ptr, copy it if need to save it.
145
    */
146
    virtual int write_audio(SrsSharedPtrMessage* shared_audio);
147
    /**
148
    * @param shared_video, directly ptr, copy it if need to save it.
149
    */
150
    virtual int write_video(SrsSharedPtrMessage* shared_video);
151 152 153 154
    /**
    * update the flv metadata.
    */
    virtual int update_flv_metadata();
155 156 157 158
    /**
    * get the current dvr path.
    */
    virtual std::string get_path();
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
private:
    /**
    * generate the flv segment path.
    */
    virtual std::string generate_path();
    /**
    * create flv jitter. load jitter when flv exists.
    * @param loads_from_flv whether loads the jitter from exists flv file.
    */
    virtual int create_jitter(bool loads_from_flv);
    /**
    * when update the duration of segment by rtmp msg.
    */
    virtual int on_update_duration(SrsSharedPtrMessage* msg);
// interface ISrsReloadHandler
public:
    virtual int on_reload_vhost_dvr(std::string vhost);
176 177 178
};

/**
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
* the dvr async call.
*/
class SrsDvrAsyncCallOnDvr : public ISrsDvrAsyncCall
{
private:
    std::string path;
    SrsRequest* req;
public:
    SrsDvrAsyncCallOnDvr(SrsRequest* r, std::string p);
    virtual ~SrsDvrAsyncCallOnDvr();
public:
    virtual int call();
    virtual std::string to_string();
};

/**
195 196 197 198 199
* the plan for dvr.
* use to control the following dvr params:
* 1. filename: the filename for record file.
* 2. reap flv: when to reap the flv and start new piece.
*/
200
// TODO: FIXME: the plan is too fat, refine me.
201
class SrsDvrPlan
202
{
203 204
public:
    friend class SrsFlvSegment;
205 206
public:
    SrsRequest* req;
207
protected:
208
    SrsFlvSegment* segment;
209
    SrsDvrAsyncCallThread* async;
210
    bool dvr_enabled;
211 212 213 214
public:
    SrsDvrPlan();
    virtual ~SrsDvrPlan();
public:
215
    virtual int initialize(SrsRequest* r);
216
    virtual int on_publish() = 0;
217
    virtual void on_unpublish() = 0;
218 219 220
    /**
    * when got metadata.
    */
221
    virtual int on_meta_data(SrsSharedPtrMessage* shared_metadata);
222
    /**
223
    * @param shared_audio, directly ptr, copy it if need to save it.
224
    */
225
    virtual int on_audio(SrsSharedPtrMessage* shared_audio);
226
    /**
227
    * @param shared_video, directly ptr, copy it if need to save it.
228
    */
229
    virtual int on_video(SrsSharedPtrMessage* shared_video);
230
protected:
231
    virtual int on_reap_segment();
232 233
    virtual int on_video_keyframe();
    virtual int64_t filter_timestamp(int64_t timestamp);
234
public:
235
    static SrsDvrPlan* create_plan(std::string vhost);
236 237 238
};

/**
239
* session plan: reap flv when session complete(unpublish)
240 241 242 243 244 245 246
*/
class SrsDvrSessionPlan : public SrsDvrPlan
{
public:
    SrsDvrSessionPlan();
    virtual ~SrsDvrSessionPlan();
public:
247
    virtual int on_publish();
248
    virtual void on_unpublish();
249 250 251 252 253 254 255
};

/**
* always append to flv file, never reap it.
*/
class SrsDvrAppendPlan : public SrsDvrPlan
{
256 257
private:
    int64_t last_update_time;
258 259 260 261 262 263
public:
    SrsDvrAppendPlan();
    virtual ~SrsDvrAppendPlan();
public:
    virtual int on_publish();
    virtual void on_unpublish();
264 265
    virtual int on_audio(SrsSharedPtrMessage* shared_audio);
    virtual int on_video(SrsSharedPtrMessage* shared_video);
266 267
private:
    virtual int update_duration(SrsSharedPtrMessage* msg);
268 269 270
};

/**
271 272 273 274 275 276 277
* segment plan: reap flv when duration exceed.
*/
class SrsDvrSegmentPlan : public SrsDvrPlan
{
private:
    // in config, in ms
    int segment_duration;
278 279
    SrsSharedPtrMessage* sh_audio;
    SrsSharedPtrMessage* sh_video;
280
    SrsSharedPtrMessage* metadata;
281 282 283 284
public:
    SrsDvrSegmentPlan();
    virtual ~SrsDvrSegmentPlan();
public:
285
    virtual int initialize(SrsRequest* req);
winlin authored
286
    virtual int on_publish();
287
    virtual void on_unpublish();
288 289 290
    virtual int on_meta_data(SrsSharedPtrMessage* shared_metadata);
    virtual int on_audio(SrsSharedPtrMessage* shared_audio);
    virtual int on_video(SrsSharedPtrMessage* shared_video);
291
private:
292
    virtual int update_duration(SrsSharedPtrMessage* msg);
293 294 295
};

/**
winlin authored
296 297 298 299 300 301
* dvr(digital video recorder) to record RTMP stream to flv file.
* TODO: FIXME: add utest for it.
*/
class SrsDvr
{
private:
302
    SrsSource* source;
winlin authored
303
private:
304
    SrsDvrPlan* plan;
winlin authored
305
public:
306
    SrsDvr();
winlin authored
307 308 309
    virtual ~SrsDvr();
public:
    /**
310 311 312 313
    * initialize dvr, create dvr plan.
    * when system initialize(encoder publish at first time, or reload),
    * initialize the dvr will reinitialize the plan, the whole dvr framework.
    */
314
    virtual int initialize(SrsSource* s, SrsRequest* r);
315
    /**
winlin authored
316 317
    * publish stream event, 
    * when encoder start to publish RTMP stream.
winlin authored
318
    */
319
    virtual int on_publish(SrsRequest* r);
winlin authored
320
    /**
winlin authored
321 322
    * the unpublish event.,
    * when encoder stop(unpublish) to publish RTMP stream.
winlin authored
323 324 325 326 327
    */
    virtual void on_unpublish();
    /**
    * get some information from metadata, it's optinal.
    */
328
    virtual int on_meta_data(SrsOnMetaDataPacket* m);
winlin authored
329
    /**
winlin authored
330
    * mux the audio packets to dvr.
331
    * @param shared_audio, directly ptr, copy it if need to save it.
winlin authored
332
    */
333
    virtual int on_audio(SrsSharedPtrMessage* shared_audio);
winlin authored
334
    /**
winlin authored
335
    * mux the video packets to dvr.
336
    * @param shared_video, directly ptr, copy it if need to save it.
winlin authored
337
    */
338
    virtual int on_video(SrsSharedPtrMessage* shared_video);
winlin authored
339 340
};
341 342
#endif
343
#endif
344