正在显示
5 个修改的文件
包含
155 行增加
和
4 行删除
@@ -41,8 +41,13 @@ SrsCodecSample::~SrsCodecSample() | @@ -41,8 +41,13 @@ SrsCodecSample::~SrsCodecSample() | ||
41 | 41 | ||
42 | void SrsCodecSample::clear() | 42 | void SrsCodecSample::clear() |
43 | { | 43 | { |
44 | - cts = 0; | 44 | + is_video = false; |
45 | nb_buffers = 0; | 45 | nb_buffers = 0; |
46 | + | ||
47 | + cts = 0; | ||
48 | + frame_type = SrsCodecVideoAVCFrameReserved; | ||
49 | + codec_id = SrsCodecVideoReserved; | ||
50 | + avc_packet_type = SrsCodecVideoAVCTypeReserved; | ||
46 | } | 51 | } |
47 | 52 | ||
48 | int SrsCodecSample::add_sample(char* bytes, int size) | 53 | int SrsCodecSample::add_sample(char* bytes, int size) |
@@ -99,6 +104,8 @@ int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample) | @@ -99,6 +104,8 @@ int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample) | ||
99 | { | 104 | { |
100 | int ret = ERROR_SUCCESS; | 105 | int ret = ERROR_SUCCESS; |
101 | 106 | ||
107 | + sample->is_video = false; | ||
108 | + | ||
102 | if (!data || size <= 0) { | 109 | if (!data || size <= 0) { |
103 | srs_trace("no audio present, hls ignore it."); | 110 | srs_trace("no audio present, hls ignore it."); |
104 | return ret; | 111 | return ret; |
@@ -176,6 +183,8 @@ int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample) | @@ -176,6 +183,8 @@ int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample) | ||
176 | { | 183 | { |
177 | int ret = ERROR_SUCCESS; | 184 | int ret = ERROR_SUCCESS; |
178 | 185 | ||
186 | + sample->is_video = true; | ||
187 | + | ||
179 | if (!data || size <= 0) { | 188 | if (!data || size <= 0) { |
180 | srs_trace("no video present, hls ignore it."); | 189 | srs_trace("no video present, hls ignore it."); |
181 | return ret; | 190 | return ret; |
@@ -196,13 +205,16 @@ int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample) | @@ -196,13 +205,16 @@ int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample) | ||
196 | int8_t codec_id = frame_type & 0x0f; | 205 | int8_t codec_id = frame_type & 0x0f; |
197 | frame_type = (frame_type >> 4) & 0x0f; | 206 | frame_type = (frame_type >> 4) & 0x0f; |
198 | 207 | ||
199 | - video_codec_id = codec_id; | 208 | + sample->frame_type = (SrsCodecVideoAVCFrame)frame_type; |
209 | + sample->codec_id = (SrsCodecVideo)codec_id; | ||
210 | + | ||
200 | // only support h.264/avc | 211 | // only support h.264/avc |
201 | if (codec_id != SrsCodecVideoAVC) { | 212 | if (codec_id != SrsCodecVideoAVC) { |
202 | ret = ERROR_HLS_DECODE_ERROR; | 213 | ret = ERROR_HLS_DECODE_ERROR; |
203 | srs_error("hls only support video h.264/avc codec. ret=%d", ret); | 214 | srs_error("hls only support video h.264/avc codec. ret=%d", ret); |
204 | return ret; | 215 | return ret; |
205 | } | 216 | } |
217 | + video_codec_id = codec_id; | ||
206 | 218 | ||
207 | if (!stream->require(4)) { | 219 | if (!stream->require(4)) { |
208 | ret = ERROR_HLS_DECODE_ERROR; | 220 | ret = ERROR_HLS_DECODE_ERROR; |
@@ -214,6 +226,7 @@ int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample) | @@ -214,6 +226,7 @@ int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample) | ||
214 | 226 | ||
215 | // pts = dts + cts. | 227 | // pts = dts + cts. |
216 | sample->cts = composition_time; | 228 | sample->cts = composition_time; |
229 | + sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type; | ||
217 | 230 | ||
218 | if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) { | 231 | if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) { |
219 | // AVCDecoderConfigurationRecord | 232 | // AVCDecoderConfigurationRecord |
@@ -45,6 +45,8 @@ class SrsStream; | @@ -45,6 +45,8 @@ class SrsStream; | ||
45 | // 7 = AVC | 45 | // 7 = AVC |
46 | enum SrsCodecVideo | 46 | enum SrsCodecVideo |
47 | { | 47 | { |
48 | + SrsCodecVideoReserved = 0, | ||
49 | + | ||
48 | SrsCodecVideoSorensonH263 = 2, | 50 | SrsCodecVideoSorensonH263 = 2, |
49 | SrsCodecVideoScreenVideo = 3, | 51 | SrsCodecVideoScreenVideo = 3, |
50 | SrsCodecVideoOn2VP6 = 4, | 52 | SrsCodecVideoOn2VP6 = 4, |
@@ -63,6 +65,8 @@ enum SrsCodecVideo | @@ -63,6 +65,8 @@ enum SrsCodecVideo | ||
63 | // 5 = video info/command frame | 65 | // 5 = video info/command frame |
64 | enum SrsCodecVideoAVCFrame | 66 | enum SrsCodecVideoAVCFrame |
65 | { | 67 | { |
68 | + SrsCodecVideoAVCFrameReserved = 0, | ||
69 | + | ||
66 | SrsCodecVideoAVCFrameKeyFrame = 1, | 70 | SrsCodecVideoAVCFrameKeyFrame = 1, |
67 | SrsCodecVideoAVCFrameInterFrame = 2, | 71 | SrsCodecVideoAVCFrameInterFrame = 2, |
68 | SrsCodecVideoAVCFrameDisposableInterFrame = 3, | 72 | SrsCodecVideoAVCFrameDisposableInterFrame = 3, |
@@ -78,6 +82,8 @@ enum SrsCodecVideoAVCFrame | @@ -78,6 +82,8 @@ enum SrsCodecVideoAVCFrame | ||
78 | // not required or supported) | 82 | // not required or supported) |
79 | enum SrsCodecVideoAVCType | 83 | enum SrsCodecVideoAVCType |
80 | { | 84 | { |
85 | + SrsCodecVideoAVCTypeReserved = -1, | ||
86 | + | ||
81 | SrsCodecVideoAVCTypeSequenceHeader = 0, | 87 | SrsCodecVideoAVCTypeSequenceHeader = 0, |
82 | SrsCodecVideoAVCTypeNALU = 1, | 88 | SrsCodecVideoAVCTypeNALU = 1, |
83 | SrsCodecVideoAVCTypeSequenceHeaderEOF = 2, | 89 | SrsCodecVideoAVCTypeSequenceHeaderEOF = 2, |
@@ -180,9 +186,14 @@ class SrsCodecSample | @@ -180,9 +186,14 @@ class SrsCodecSample | ||
180 | public: | 186 | public: |
181 | int nb_buffers; | 187 | int nb_buffers; |
182 | SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE]; | 188 | SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE]; |
189 | +public: | ||
190 | + bool is_video; | ||
183 | // CompositionTime, video_file_format_spec_v10_1.pdf, page 78. | 191 | // CompositionTime, video_file_format_spec_v10_1.pdf, page 78. |
184 | // cts = pts - dts, where dts = flvheader->timestamp. | 192 | // cts = pts - dts, where dts = flvheader->timestamp. |
185 | int32_t cts; | 193 | int32_t cts; |
194 | + SrsCodecVideoAVCFrame frame_type; | ||
195 | + SrsCodecVideo codec_id; | ||
196 | + SrsCodecVideoAVCType avc_packet_type; | ||
186 | public: | 197 | public: |
187 | SrsCodecSample(); | 198 | SrsCodecSample(); |
188 | virtual ~SrsCodecSample(); | 199 | virtual ~SrsCodecSample(); |
@@ -110,5 +110,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -110,5 +110,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
110 | #define ERROR_HLS_METADATA 600 | 110 | #define ERROR_HLS_METADATA 600 |
111 | #define ERROR_HLS_DECODE_ERROR 601 | 111 | #define ERROR_HLS_DECODE_ERROR 601 |
112 | #define ERROR_HLS_BUSY 602 | 112 | #define ERROR_HLS_BUSY 602 |
113 | +#define ERROR_HLS_OPEN_FAILED 603 | ||
114 | +#define ERROR_HLS_WRITE_FAILED 604 | ||
113 | 115 | ||
114 | #endif | 116 | #endif |
@@ -23,6 +23,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -23,6 +23,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
23 | 23 | ||
24 | #include <srs_core_hls.hpp> | 24 | #include <srs_core_hls.hpp> |
25 | 25 | ||
26 | +#include <sys/types.h> | ||
27 | +#include <sys/stat.h> | ||
28 | +#include <fcntl.h> | ||
29 | + | ||
26 | #include <srs_core_error.hpp> | 30 | #include <srs_core_error.hpp> |
27 | #include <srs_core_codec.hpp> | 31 | #include <srs_core_codec.hpp> |
28 | #include <srs_core_amf0.hpp> | 32 | #include <srs_core_amf0.hpp> |
@@ -63,6 +67,9 @@ int SrsHLS::on_publish(std::string _vhost) | @@ -63,6 +67,9 @@ int SrsHLS::on_publish(std::string _vhost) | ||
63 | if (!conf && conf->arg0() == "off") { | 67 | if (!conf && conf->arg0() == "off") { |
64 | return ret; | 68 | return ret; |
65 | } | 69 | } |
70 | + | ||
71 | + // TODO: check the audio and video, ensure both exsists. | ||
72 | + // for use fixed mpegts header specifeid the audio and video pid. | ||
66 | 73 | ||
67 | hls_enabled = true; | 74 | hls_enabled = true; |
68 | 75 | ||
@@ -71,6 +78,9 @@ int SrsHLS::on_publish(std::string _vhost) | @@ -71,6 +78,9 @@ int SrsHLS::on_publish(std::string _vhost) | ||
71 | path = conf->arg0(); | 78 | path = conf->arg0(); |
72 | } | 79 | } |
73 | 80 | ||
81 | + // TODO: generate by m3u8 muxer. | ||
82 | + path += "/1.ts"; | ||
83 | + | ||
74 | if ((ret = muxer->open(path)) != ERROR_SUCCESS) { | 84 | if ((ret = muxer->open(path)) != ERROR_SUCCESS) { |
75 | srs_error("open hls muxer failed. ret=%d", ret); | 85 | srs_error("open hls muxer failed. ret=%d", ret); |
76 | return ret; | 86 | return ret; |
@@ -82,6 +92,7 @@ int SrsHLS::on_publish(std::string _vhost) | @@ -82,6 +92,7 @@ int SrsHLS::on_publish(std::string _vhost) | ||
82 | void SrsHLS::on_unpublish() | 92 | void SrsHLS::on_unpublish() |
83 | { | 93 | { |
84 | hls_enabled = false; | 94 | hls_enabled = false; |
95 | + muxer->close(); | ||
85 | srs_freep(muxer); | 96 | srs_freep(muxer); |
86 | } | 97 | } |
87 | 98 | ||
@@ -185,6 +196,10 @@ int SrsHLS::on_audio(SrsCommonMessage* audio) | @@ -185,6 +196,10 @@ int SrsHLS::on_audio(SrsCommonMessage* audio) | ||
185 | return ret; | 196 | return ret; |
186 | } | 197 | } |
187 | 198 | ||
199 | + if ((ret = muxer->write(codec, sample)) != ERROR_SUCCESS) { | ||
200 | + return ret; | ||
201 | + } | ||
202 | + | ||
188 | return ret; | 203 | return ret; |
189 | } | 204 | } |
190 | 205 | ||
@@ -206,20 +221,125 @@ int SrsHLS::on_video(SrsCommonMessage* video) | @@ -206,20 +221,125 @@ int SrsHLS::on_video(SrsCommonMessage* video) | ||
206 | return ret; | 221 | return ret; |
207 | } | 222 | } |
208 | 223 | ||
224 | + if ((ret = muxer->write(codec, sample)) != ERROR_SUCCESS) { | ||
225 | + return ret; | ||
226 | + } | ||
227 | + | ||
209 | return ret; | 228 | return ret; |
210 | } | 229 | } |
211 | 230 | ||
231 | +// @see: ngx_rtmp_mpegts_header | ||
232 | +static u_char mpegts_header[] = { | ||
233 | + /* TS */ | ||
234 | + 0x47, 0x40, 0x00, 0x10, 0x00, | ||
235 | + /* PSI */ | ||
236 | + 0x00, 0xb0, 0x0d, 0x00, 0x01, 0xc1, 0x00, 0x00, | ||
237 | + /* PAT */ | ||
238 | + 0x00, 0x01, 0xf0, 0x01, | ||
239 | + /* CRC */ | ||
240 | + 0x2e, 0x70, 0x19, 0x05, | ||
241 | + /* stuffing 167 bytes */ | ||
242 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
243 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
244 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
245 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
246 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
247 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
248 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
249 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
250 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
251 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
252 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
253 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
254 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
255 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
256 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
257 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
258 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
259 | + | ||
260 | + /* TS */ | ||
261 | + 0x47, 0x50, 0x01, 0x10, 0x00, | ||
262 | + /* PSI */ | ||
263 | + 0x02, 0xb0, 0x17, 0x00, 0x01, 0xc1, 0x00, 0x00, | ||
264 | + /* PMT */ | ||
265 | + 0xe1, 0x00, | ||
266 | + 0xf0, 0x00, | ||
267 | + 0x1b, 0xe1, 0x00, 0xf0, 0x00, /* h264, pid=0x100=256 */ | ||
268 | + 0x0f, 0xe1, 0x01, 0xf0, 0x00, /* aac, pid=0x101=257 */ | ||
269 | + /*0x03, 0xe1, 0x01, 0xf0, 0x00,*/ /* mp3 */ | ||
270 | + /* CRC */ | ||
271 | + 0x2f, 0x44, 0xb9, 0x9b, /* crc for aac */ | ||
272 | + /*0x4e, 0x59, 0x3d, 0x1e,*/ /* crc for mp3 */ | ||
273 | + /* stuffing 157 bytes */ | ||
274 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
275 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
276 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
277 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
278 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
279 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
280 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
281 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
282 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
283 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
284 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
285 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
286 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
287 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
288 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
289 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
290 | +}; | ||
291 | + | ||
292 | +// the mpegts header specifed the video/audio pid. | ||
293 | +#define TS_VIDEO_PID 256 | ||
294 | +#define TS_AUDIO_PID 257 | ||
295 | + | ||
212 | SrsTSMuxer::SrsTSMuxer() | 296 | SrsTSMuxer::SrsTSMuxer() |
213 | { | 297 | { |
298 | + fd = -1; | ||
214 | } | 299 | } |
215 | 300 | ||
216 | SrsTSMuxer::~SrsTSMuxer() | 301 | SrsTSMuxer::~SrsTSMuxer() |
217 | { | 302 | { |
303 | + close(); | ||
218 | } | 304 | } |
219 | 305 | ||
220 | -int SrsTSMuxer::open(std::string path) | 306 | +int SrsTSMuxer::open(std::string _path) |
307 | +{ | ||
308 | + int ret = ERROR_SUCCESS; | ||
309 | + | ||
310 | + path = _path; | ||
311 | + | ||
312 | + close(); | ||
313 | + | ||
314 | + int flags = O_CREAT|O_WRONLY|O_TRUNC; | ||
315 | + mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; | ||
316 | + if ((fd = ::open(path.c_str(), flags, mode)) < 0) { | ||
317 | + ret = ERROR_HLS_OPEN_FAILED; | ||
318 | + srs_error("open ts file %s failed. ret=%d", path.c_str(), ret); | ||
319 | + return ret; | ||
320 | + } | ||
321 | + | ||
322 | + // write mpegts header | ||
323 | + if (::write(fd, mpegts_header, sizeof(mpegts_header)) != sizeof(mpegts_header)) { | ||
324 | + ret = ERROR_HLS_WRITE_FAILED; | ||
325 | + srs_error("write ts file header %s failed. ret=%d", path.c_str(), ret); | ||
326 | + return ret; | ||
327 | + } | ||
328 | + | ||
329 | + return ret; | ||
330 | +} | ||
331 | + | ||
332 | +int SrsTSMuxer::write(SrsCodec* codec, SrsCodecSample* sample) | ||
221 | { | 333 | { |
222 | int ret = ERROR_SUCCESS; | 334 | int ret = ERROR_SUCCESS; |
223 | return ret; | 335 | return ret; |
224 | } | 336 | } |
225 | 337 | ||
338 | +void SrsTSMuxer::close() | ||
339 | +{ | ||
340 | + if (fd > 0) { | ||
341 | + ::close(fd); | ||
342 | + fd = -1; | ||
343 | + } | ||
344 | +} | ||
345 | + |
@@ -58,11 +58,16 @@ public: | @@ -58,11 +58,16 @@ public: | ||
58 | 58 | ||
59 | class SrsTSMuxer | 59 | class SrsTSMuxer |
60 | { | 60 | { |
61 | +private: | ||
62 | + int fd; | ||
63 | + std::string path; | ||
61 | public: | 64 | public: |
62 | SrsTSMuxer(); | 65 | SrsTSMuxer(); |
63 | virtual ~SrsTSMuxer(); | 66 | virtual ~SrsTSMuxer(); |
64 | public: | 67 | public: |
65 | - virtual int open(std::string path); | 68 | + virtual int open(std::string _path); |
69 | + virtual int write(SrsCodec* codec, SrsCodecSample* sample); | ||
70 | + virtual void close(); | ||
66 | }; | 71 | }; |
67 | 72 | ||
68 | #endif | 73 | #endif |
-
请 注册 或 登录 后发表评论