Blame view

trunk/src/app/srs_app_dvr.hpp 7.7 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
The MIT License (MIT)

Copyright (c) 2013-2014 winlin

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 32 33
*/
#include <srs_core.hpp>

#ifdef SRS_AUTO_DVR
winlin authored
34 35
class SrsSource;
class SrsRequest;
winlin authored
36
class SrsStream;
winlin authored
37
class SrsRtmpJitter;
winlin authored
38
class SrsOnMetaDataPacket;
39
class SrsSharedPtrMessage;
winlin authored
40 41

/**
winlin authored
42 43 44 45 46 47 48 49 50 51 52 53 54
* file stream to read/write file.
*/
class SrsFileStream
{
private:
    std::string _file;
    int fd;
public:
    SrsFileStream();
    virtual ~SrsFileStream();
public:
    virtual int open(std::string file);
    virtual int close();
winlin authored
55
    virtual bool is_open();
winlin authored
56 57 58 59 60 61 62 63 64
public:
    /**
    * @param pnread, return the read size. NULL to ignore.
    */
    virtual int read(void* buf, size_t count, ssize_t* pnread);
    /**
    * @param pnwrite, return the write size. NULL to ignore.
    */
    virtual int write(void* buf, size_t count, ssize_t* pnwrite);
65 66 67 68
    /**
    * tell current offset of stream.
    */
    virtual int64_t tellg();
winlin authored
69 70 71
};

/**
winlin authored
72 73 74 75
* encode data to flv file.
*/
class SrsFlvEncoder
{
winlin authored
76 77 78 79 80 81 82 83
private:
    SrsFileStream* _fs;
private:
    SrsStream* tag_stream;
public:
    SrsFlvEncoder();
    virtual ~SrsFlvEncoder();
public:
winlin authored
84 85 86 87
    /**
    * initialize the underlayer file stream,
    * user can initialize multiple times to encode multiple flv files.
    */
winlin authored
88 89 90 91 92 93 94 95 96 97
    virtual int initialize(SrsFileStream* fs);
public:
    /**
    * write flv header.
    * write following:
    *   1. E.2 The FLV header
    *   2. PreviousTagSize0 UI32 Always 0
    * that is, 9+4=13bytes.
    */
    virtual int write_header();
winlin authored
98 99 100 101 102 103
    /**
    * write flv metadata. 
    * serialize from:
    *   AMF0 string: onMetaData,
    *   AMF0 object: the metadata object.
    */
winlin authored
104
    virtual int write_metadata(char* data, int size);
winlin authored
105 106 107
    /**
    * write audio/video packet.
    */
108 109
    virtual int write_audio(int64_t timestamp, char* data, int size);
    virtual int write_video(int64_t timestamp, char* data, int size);
winlin authored
110
private:
winlin authored
111
    virtual int write_tag(char* header, int header_size, char* tag, int tag_size);
winlin authored
112 113 114
};

/**
115 116 117 118 119 120
* a piece of flv segment.
*/
class SrsFlvSegment
{
public:
    /**
121
    * current segment flv file path.
122
    */
123
    std::string path;
124 125 126
    /**
    * whether current segment has keyframe.
    */
127
    bool has_keyframe;
128
    /**
129 130 131 132
    * sequence header offset in file.
    */
    int64_t sequence_header_offset;
    /**
133
    * current segment starttime, RTMP pkt time.
134
    */
135
    int64_t starttime;
136
    /**
137 138 139 140 141
    * current segment duration
    */
    int64_t duration;
    /**
    * stream start time, to generate atc pts. abs time.
142 143
    */
    int64_t stream_starttime;
144 145 146 147 148 149 150 151 152
    /**
    * 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;
153 154 155 156 157 158
public:
    SrsFlvSegment();
    virtual void reset();
};

/**
159 160 161 162 163
* 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.
*/
164
// TODO: FIXME: the plan is too fat, refine me.
165 166 167 168 169 170 171 172 173 174 175 176
class SrsDvrPlan
{
protected:
    /**
    * the underlayer dvr stream.
    * if close, the flv is reap and closed.
    * if open, new flv file is crote.
    */
    SrsFileStream* fs;
    SrsFlvEncoder* enc;
    bool dvr_enabled;
    SrsSource* _source;
winlin authored
177 178
    SrsRequest* _req;
    SrsRtmpJitter* jitter;
179
    SrsFlvSegment* segment;
180 181 182 183
public:
    SrsDvrPlan();
    virtual ~SrsDvrPlan();
public:
184
    virtual int initialize(SrsSource* source, SrsRequest* req);
winlin authored
185
    virtual int on_publish();
186 187
    virtual void on_unpublish() = 0;
    virtual int on_meta_data(SrsOnMetaDataPacket* metadata);
188 189
    virtual int on_audio(SrsSharedPtrMessage* audio);
    virtual int on_video(SrsSharedPtrMessage* video);
190 191 192
protected:
    virtual int flv_open(std::string stream, std::string path);
    virtual int flv_close();
193
    virtual int open_new_segment();
194
    virtual int update_duration(SrsSharedPtrMessage* msg);
195 196 197 198
    virtual int write_flv_header();
    virtual int on_dvr_request_sh();
    virtual int on_video_keyframe();
    virtual int64_t filter_timestamp(int64_t timestamp);
199
private:
200
    /**
201
    * when srs reap the flv(close the segment), notice the api.
202
    */
winlin authored
203
    virtual int on_dvr_hss_reap_flv();
204
public:
205
    static SrsDvrPlan* create_plan(std::string vhost);
206 207 208
};

/**
209
* session plan: reap flv when session complete(unpublish)
210 211 212 213 214 215 216 217 218 219 220
*/
class SrsDvrSessionPlan : public SrsDvrPlan
{
public:
    SrsDvrSessionPlan();
    virtual ~SrsDvrSessionPlan();
public:
    virtual void on_unpublish();
};

/**
221 222 223 224 225 226 227 228 229 230 231 232
* segment plan: reap flv when duration exceed.
*/
class SrsDvrSegmentPlan : public SrsDvrPlan
{
private:
    // in config, in ms
    int segment_duration;
public:
    SrsDvrSegmentPlan();
    virtual ~SrsDvrSegmentPlan();
public:
    virtual int initialize(SrsSource* source, SrsRequest* req);
winlin authored
233
    virtual int on_publish();
234 235
    virtual void on_unpublish();
private:
236
    virtual int update_duration(SrsSharedPtrMessage* msg);
237 238 239
};

/**
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
* hss plan: use atc time to reap flv segment
*/
class SrsDvrHssPlan : public SrsDvrPlan
{
private:
    // in config, in ms
    int segment_duration;
    int64_t expect_reap_time;
public:
    SrsDvrHssPlan();
    virtual ~SrsDvrHssPlan();
public:
    virtual int initialize(SrsSource* source, SrsRequest* req);
    virtual int on_publish();
    virtual void on_unpublish();
255 256 257 258 259 260
    virtual int on_meta_data(SrsOnMetaDataPacket* metadata);
protected:
    virtual int write_flv_header();
    virtual int on_dvr_request_sh();
    virtual int on_video_keyframe();
    virtual int64_t filter_timestamp(int64_t timestamp);
261
private:
winlin authored
262
    virtual int on_dvr_hss_reap_flv_header(std::string path);
263
    virtual int update_duration(SrsSharedPtrMessage* msg);
264 265 266
};

/**
winlin authored
267 268 269 270 271 272 273
* dvr(digital video recorder) to record RTMP stream to flv file.
* TODO: FIXME: add utest for it.
*/
class SrsDvr
{
private:
    SrsSource* _source;
winlin authored
274
private:
275
    SrsDvrPlan* plan;
winlin authored
276 277 278 279 280
public:
    SrsDvr(SrsSource* source);
    virtual ~SrsDvr();
public:
    /**
281 282 283 284
    * 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.
    */
285
    virtual int initialize(SrsRequest* req);
286
    /**
winlin authored
287 288
    * publish stream event, 
    * when encoder start to publish RTMP stream.
winlin authored
289 290 291
    */
    virtual int on_publish(SrsRequest* req);
    /**
winlin authored
292 293
    * the unpublish event.,
    * when encoder stop(unpublish) to publish RTMP stream.
winlin authored
294 295 296 297 298
    */
    virtual void on_unpublish();
    /**
    * get some information from metadata, it's optinal.
    */
winlin authored
299
    virtual int on_meta_data(SrsOnMetaDataPacket* metadata);
winlin authored
300
    /**
winlin authored
301
    * mux the audio packets to dvr.
winlin authored
302
    */
303
    virtual int on_audio(SrsSharedPtrMessage* audio);
winlin authored
304
    /**
winlin authored
305
    * mux the video packets to dvr.
winlin authored
306
    */
307
    virtual int on_video(SrsSharedPtrMessage* video);
winlin authored
308 309
};
310 311 312
#endif

#endif