1 | /* --------------------------------------------------------------------------- |
2 | ** This software is in the public domain, furnished "as is", without technical |
3 | ** support, and with no warranty, express or implied, as to its usefulness for |
4 | ** any purpose. |
5 | ** |
6 | ** ServerMediaSubsession.cpp |
7 | ** |
8 | ** -------------------------------------------------------------------------*/ |
9 | |
10 | #include <sstream> |
11 | #include <linux/videodev2.h> |
12 | |
13 | // project |
14 | #include "ServerMediaSubsession.h" |
15 | #include "MJPEGVideoSource.h" |
16 | #include "DeviceSource.h" |
17 | |
18 | // --------------------------------- |
19 | // BaseServerMediaSubsession |
20 | // --------------------------------- |
21 | FramedSource* BaseServerMediaSubsession::createSource(UsageEnvironment& env, FramedSource* videoES, const std::string& format) |
22 | { |
23 | FramedSource* source = NULL; |
24 | if (format == "video/MP2T" ) |
25 | { |
26 | source = MPEG2TransportStreamFramer::createNew(env, videoES); |
27 | } |
28 | else if (format == "video/H264" ) |
29 | { |
30 | source = H264VideoStreamDiscreteFramer::createNew(env, videoES); |
31 | } |
32 | #if LIVEMEDIA_LIBRARY_VERSION_INT > 1414454400 |
33 | else if (format == "video/H265" ) |
34 | { |
35 | source = H265VideoStreamDiscreteFramer::createNew(env, videoES); |
36 | } |
37 | #endif |
38 | else if (format == "video/JPEG" ) |
39 | { |
40 | source = MJPEGVideoSource::createNew(env, videoES); |
41 | } |
42 | else |
43 | { |
44 | source = videoES; |
45 | } |
46 | return source; |
47 | } |
48 | |
49 | RTPSink* BaseServerMediaSubsession::createSink(UsageEnvironment& env, Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, const std::string& format, V4L2DeviceSource* source) |
50 | { |
51 | RTPSink* videoSink = NULL; |
52 | if (format == "video/MP2T" ) |
53 | { |
54 | videoSink = SimpleRTPSink::createNew(env, rtpGroupsock,rtpPayloadTypeIfDynamic, 90000, "video" , "MP2T" , 1, True, False); |
55 | } |
56 | else if (format == "video/H264" ) |
57 | { |
58 | videoSink = H264VideoRTPSink::createNew(env, rtpGroupsock,rtpPayloadTypeIfDynamic); |
59 | } |
60 | else if (format == "video/VP8" ) |
61 | { |
62 | videoSink = VP8VideoRTPSink::createNew (env, rtpGroupsock,rtpPayloadTypeIfDynamic); |
63 | } |
64 | #if LIVEMEDIA_LIBRARY_VERSION_INT > 1414454400 |
65 | else if (format == "video/VP9" ) |
66 | { |
67 | videoSink = VP9VideoRTPSink::createNew (env, rtpGroupsock,rtpPayloadTypeIfDynamic); |
68 | } |
69 | else if (format == "video/H265" ) |
70 | { |
71 | videoSink = H265VideoRTPSink::createNew(env, rtpGroupsock,rtpPayloadTypeIfDynamic); |
72 | } |
73 | #endif |
74 | else if (format == "video/JPEG" ) |
75 | { |
76 | videoSink = JPEGVideoRTPSink::createNew (env, rtpGroupsock); |
77 | } |
78 | #if LIVEMEDIA_LIBRARY_VERSION_INT >= 1536192000 |
79 | else if (format =="video/RAW" ) |
80 | { |
81 | std::string sampling; |
82 | switch (source->getCaptureFormat()) { |
83 | case V4L2_PIX_FMT_YUV444: sampling = "YCbCr-4:4:4" ; break; |
84 | case V4L2_PIX_FMT_YUYV: sampling = "YCbCr-4:2:2" ; break; |
85 | case V4L2_PIX_FMT_UYVY: sampling = "YCbCr-4:2:2" ; break; |
86 | } |
87 | videoSink = RawVideoRTPSink::createNew(env, rtpGroupsock, rtpPayloadTypeIfDynamic, source->getHeight(), source->getWidth(), 8, sampling.c_str()); |
88 | } |
89 | #endif |
90 | else if (format.find("audio/L16" ) == 0) |
91 | { |
92 | std::istringstream is(format); |
93 | std::string dummy; |
94 | getline(is, dummy, '/'); |
95 | getline(is, dummy, '/'); |
96 | std::string sampleRate("44100" ); |
97 | getline(is, sampleRate, '/'); |
98 | std::string channels("2" ); |
99 | getline(is, channels); |
100 | videoSink = SimpleRTPSink::createNew(env, rtpGroupsock,rtpPayloadTypeIfDynamic, atoi(sampleRate.c_str()), "audio" , "L16" , atoi(channels.c_str()), True, False); |
101 | } |
102 | return videoSink; |
103 | } |
104 | |
105 | char const* BaseServerMediaSubsession::getAuxLine(V4L2DeviceSource* source, RTPSink* rtpSink) |
106 | { |
107 | const char* auxLine = NULL; |
108 | if (rtpSink) { |
109 | std::ostringstream os; |
110 | if (rtpSink->auxSDPLine()) { |
111 | os << rtpSink->auxSDPLine(); |
112 | } |
113 | else if (source) { |
114 | unsigned char rtpPayloadType = rtpSink->rtpPayloadType(); |
115 | os << "a=fmtp:" << int(rtpPayloadType) << " " << source->getAuxLine() << "\r\n" ; |
116 | int width = source->getWidth(); |
117 | int height = source->getHeight(); |
118 | if ( (width > 0) && (height>0) ) { |
119 | os << "a=x-dimensions:" << width << "," << height << "\r\n" ; |
120 | } |
121 | } |
122 | auxLine = strdup(os.str().c_str()); |
123 | } |
124 | return auxLine; |
125 | } |
126 | |
127 | |