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 | ** H264_V4l2DeviceSource.cpp |
7 | ** |
8 | ** H264 V4L2 Live555 source |
9 | ** |
10 | ** -------------------------------------------------------------------------*/ |
11 | |
12 | #include <sstream> |
13 | |
14 | // live555 |
15 | #include <Base64.hh> |
16 | |
17 | // project |
18 | #include "logger.h" |
19 | #include "H264_V4l2DeviceSource.h" |
20 | |
21 | // --------------------------------- |
22 | // H264 V4L2 FramedSource |
23 | // --------------------------------- |
24 | |
25 | |
26 | // split packet in frames |
27 | std::list< std::pair<unsigned char*,size_t> > H264_V4L2DeviceSource::splitFrames(unsigned char* frame, unsigned frameSize) |
28 | { |
29 | std::list< std::pair<unsigned char*,size_t> > frameList; |
30 | |
31 | size_t bufSize = frameSize; |
32 | size_t size = 0; |
33 | int frameType = 0; |
34 | unsigned char* buffer = this->extractFrame(frame, bufSize, size, frameType); |
35 | while (buffer != NULL) |
36 | { |
37 | switch (frameType&0x1F) |
38 | { |
39 | case 7: LOG(INFO) << "SPS size:" << size << " bufSize:" << bufSize; m_sps.assign((char*)buffer,size); break; |
40 | case 8: LOG(INFO) << "PPS size:" << size << " bufSize:" << bufSize; m_pps.assign((char*)buffer,size); break; |
41 | case 5: LOG(INFO) << "IDR size:" << size << " bufSize:" << bufSize; |
42 | if (m_repeatConfig && !m_sps.empty() && !m_pps.empty()) |
43 | { |
44 | frameList.push_back(std::pair<unsigned char*,size_t>((unsigned char*)m_sps.c_str(), m_sps.size())); |
45 | frameList.push_back(std::pair<unsigned char*,size_t>((unsigned char*)m_pps.c_str(), m_pps.size())); |
46 | } |
47 | break; |
48 | default: |
49 | break; |
50 | } |
51 | |
52 | if (!m_sps.empty() && !m_pps.empty()) |
53 | { |
54 | u_int32_t profile_level_id = 0; |
55 | if (m_sps.size() >= 4) profile_level_id = (((unsigned char)m_sps[1])<<16)|(((unsigned char)m_sps[2])<<8)|((unsigned char)m_sps[3]); |
56 | |
57 | char* sps_base64 = base64Encode(m_sps.c_str(), m_sps.size()); |
58 | char* pps_base64 = base64Encode(m_pps.c_str(), m_pps.size()); |
59 | |
60 | std::ostringstream os; |
61 | os << "profile-level-id=" << std::hex << std::setw(6) << std::setfill('0') << profile_level_id; |
62 | os << ";sprop-parameter-sets=" << sps_base64 <<"," << pps_base64; |
63 | m_auxLine.assign(os.str()); |
64 | |
65 | delete [] sps_base64; |
66 | delete [] pps_base64; |
67 | } |
68 | frameList.push_back(std::pair<unsigned char*,size_t>(buffer, size)); |
69 | |
70 | buffer = this->extractFrame(&buffer[size], bufSize, size, frameType); |
71 | } |
72 | return frameList; |
73 | } |
74 | |
75 | // split packet in frames |
76 | std::list< std::pair<unsigned char*,size_t> > H265_V4L2DeviceSource::splitFrames(unsigned char* frame, unsigned frameSize) |
77 | { |
78 | std::list< std::pair<unsigned char*,size_t> > frameList; |
79 | |
80 | size_t bufSize = frameSize; |
81 | size_t size = 0; |
82 | int frameType = 0; |
83 | unsigned char* buffer = this->extractFrame(frame, bufSize, size, frameType); |
84 | while (buffer != NULL) |
85 | { |
86 | switch ((frameType&0x7E)>>1) |
87 | { |
88 | case 32: LOG(INFO) << "VPS size:" << size << " bufSize:" << bufSize; m_vps.assign((char*)buffer,size); break; |
89 | case 33: LOG(INFO) << "SPS size:" << size << " bufSize:" << bufSize; m_sps.assign((char*)buffer,size); break; |
90 | case 34: LOG(INFO) << "PPS size:" << size << " bufSize:" << bufSize; m_pps.assign((char*)buffer,size); break; |
91 | case 19: |
92 | case 20: LOG(INFO) << "IDR size:" << size << " bufSize:" << bufSize; |
93 | if (m_repeatConfig && !m_vps.empty() && !m_sps.empty() && !m_pps.empty()) |
94 | { |
95 | frameList.push_back(std::pair<unsigned char*,size_t>((unsigned char*)m_vps.c_str(), m_vps.size())); |
96 | frameList.push_back(std::pair<unsigned char*,size_t>((unsigned char*)m_sps.c_str(), m_sps.size())); |
97 | frameList.push_back(std::pair<unsigned char*,size_t>((unsigned char*)m_pps.c_str(), m_pps.size())); |
98 | } |
99 | break; |
100 | default: break; |
101 | } |
102 | |
103 | if (!m_vps.empty() && !m_sps.empty() && !m_pps.empty()) |
104 | { |
105 | char* vps_base64 = base64Encode(m_vps.c_str(), m_vps.size()); |
106 | char* sps_base64 = base64Encode(m_sps.c_str(), m_sps.size()); |
107 | char* pps_base64 = base64Encode(m_pps.c_str(), m_pps.size()); |
108 | |
109 | std::ostringstream os; |
110 | os << "sprop-vps=" << vps_base64; |
111 | os << ";sprop-sps=" << sps_base64; |
112 | os << ";sprop-pps=" << pps_base64; |
113 | m_auxLine.assign(os.str()); |
114 | |
115 | delete [] vps_base64; |
116 | delete [] sps_base64; |
117 | delete [] pps_base64; |
118 | } |
119 | frameList.push_back(std::pair<unsigned char*,size_t>(buffer, size)); |
120 | |
121 | buffer = this->extractFrame(&buffer[size], bufSize, size, frameType); |
122 | } |
123 | return frameList; |
124 | } |
125 | |
126 | // extract a frame |
127 | unsigned char* H26X_V4L2DeviceSource::(unsigned char* frame, size_t& size, size_t& outsize, int& frameType) |
128 | { |
129 | unsigned char * outFrame = NULL; |
130 | outsize = 0; |
131 | unsigned int markerlength = 0; |
132 | frameType = 0; |
133 | |
134 | unsigned char *startFrame = (unsigned char*)memmem(frame,size,H264marker,sizeof(H264marker)); |
135 | if (startFrame != NULL) { |
136 | markerlength = sizeof(H264marker); |
137 | } else { |
138 | startFrame = (unsigned char*)memmem(frame,size,H264shortmarker,sizeof(H264shortmarker)); |
139 | if (startFrame != NULL) { |
140 | markerlength = sizeof(H264shortmarker); |
141 | } |
142 | } |
143 | if (startFrame != NULL) { |
144 | frameType = startFrame[markerlength]; |
145 | |
146 | int remainingSize = size-(startFrame-frame+markerlength); |
147 | unsigned char *endFrame = (unsigned char*)memmem(&startFrame[markerlength], remainingSize, H264marker, sizeof(H264marker)); |
148 | if (endFrame == NULL) { |
149 | endFrame = (unsigned char*)memmem(&startFrame[markerlength], remainingSize, H264shortmarker, sizeof(H264shortmarker)); |
150 | } |
151 | |
152 | if (m_keepMarker) |
153 | { |
154 | size -= startFrame-frame; |
155 | outFrame = startFrame; |
156 | } |
157 | else |
158 | { |
159 | size -= startFrame-frame+markerlength; |
160 | outFrame = &startFrame[markerlength]; |
161 | } |
162 | |
163 | if (endFrame != NULL) |
164 | { |
165 | outsize = endFrame - outFrame; |
166 | } |
167 | else |
168 | { |
169 | outsize = size; |
170 | } |
171 | size -= outsize; |
172 | } else if (size>= sizeof(H264shortmarker)) { |
173 | LOG(INFO) << "No marker found" ; |
174 | } |
175 | |
176 | return outFrame; |
177 | } |
178 | |
179 | |