forked from klaxa/ffserver
-
Notifications
You must be signed in to change notification settings - Fork 0
/
publisher.h
163 lines (142 loc) · 5.13 KB
/
publisher.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef PUBLISHER_H
#define PUBLISHER_H
#include <libavformat/avformat.h>
#include <libavutil/fifo.h>
#include <pthread.h>
#include "segment.h"
#include "httpd.h"
#define MAX_CLIENTS 16
#define MAX_SEGMENTS 16
#define BUFFER_SEGMENTS 10
/* Client State enum */
enum State {
FREE, // no client connected
RESERVED, // reserved for a client that just connected
WAIT, // up to date, no new Segments to write
WRITABLE, // buffer is not full, new Segments can be pushed
BUSY, // currently writing to this client
BUFFER_FULL, // client buffer is full, new Segments will be dropped
STATE_NB
};
struct Client {
AVFormatContext *ofmt_ctx; // writable AVFormatContext, basically our tcp connection to the client
AVFifoBuffer *buffer; // Client buffer of Segment references
char *method;
char *resource;
struct FFServerInfo *ffinfo;
enum State state;
pthread_mutex_t buffer_lock;
pthread_mutex_t state_lock;
int id;
int current_segment_id; // The stream-based id of the segment that has last been worked on.
};
struct PublisherContext {
struct Client clients[MAX_CLIENTS]; // currently compile-time configuration, easly made dynamic with malloc?
AVFifoBuffer *buffer; // publisher buffer for new Segments
AVFifoBuffer *fs_buffer; // fast start buffer
pthread_mutex_t buffer_lock;
pthread_mutex_t fs_buffer_lock;
int nb_threads;
int current_segment_id;
int shutdown; // indicate shutdown, gracefully close client connections and files and exit
char *stream_name;
};
/**
* Log a client's stats to the console.
*
* @param c pointer to the client to print
*/
void client_log(struct Client *c);
/**
* Disconnect a client.
*
* @param c pointer to the client to disconnect.
*/
void client_disconnect(struct Client *c, int write_trailer);
/**
* Set a client's state. Note: This is protected by mutex locks.
*
* @param c pointer to the client to set the state of
* @param state the state to set the client to
*/
void client_set_state(struct Client *c, enum State state);
/**
* Allocate and initialize a PublisherContext
*
* @param pub pointer to a pointer to a PublisherContext. It will be allocated and initialized.
* @param stream_name string containing the name of the stream.
*/
void publisher_init(struct PublisherContext **pub, char *stream_name);
/**
* Push a Segment to a PublisherContext.
*
* @param pub pointer to a PublisherContext
* @param seg pointer to the Segment to add
*/
void publisher_push_segment(struct PublisherContext *pub, struct Segment *seg);
/**
* Reserve a slot in the client struct of a PublisherContext. May fail if the number
* of maximum clients has been reached.
*
* @param pub pointer to a PublisherContext
* @return 0 in case of success, 1 in case of failure
*/
int publisher_reserve_client(struct PublisherContext *pub);
/**
* Cancel a single reservation. This can be used if a client spot was reserved, but the client
* unexpectedly disconnects or sends an invalid request.
*
* @param pub pointer to a PublisherContext
*/
void publisher_cancel_reserve(struct PublisherContext *pub);
/**
* Add a client by its ofmt_ctx. This initializes an element in the client struct of the PublisherContext
* that has been reserved prior to calling this function.
*
* @param pub pointer to a PublisherContext
* @param ofmt_ctx AVFormatContext of a client
* @param ffinfo pointer to struct containing custom IO information for server independent write implementation
*/
void publisher_add_client(struct PublisherContext *pub, AVFormatContext *ofmt_ctx, struct FFServerInfo *ffinfo);
/**
* Free buffers and associated client buffers.
*
* @param pub pointer to the PublisherContext to free
*/
void publisher_free(struct PublisherContext *pub);
/**
* Free buffers and associated client buffers and set *pub to NULL.
*
* @param pub pointer to the PublisherContext pointer to free
*/
void publisher_freep(struct PublisherContext **pub);
/**
* Signal to the PublisherContext to check its buffer and publish pending Segments.
*
* @param pub pointer to a PublisherContext
*/
void publish(struct PublisherContext *pub);
/**
* Print the current client and file reading status to a json string.
* @param pub pointer to a PublisherContext
* @param status string of at least 4096 bytes size.
*/
void publisher_gen_status_json(struct PublisherContext *pub, char *status);
#endif // PUBLISHER_H