|
1 /* |
|
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 // ============================ INCLUDES ======================================= |
|
21 |
|
22 #include "mcch263oldpayloadencoder.h" |
|
23 #include "mcch263formatlogs.h" |
|
24 |
|
25 // ============================ MEMBER FUNCTIONS =============================== |
|
26 |
|
27 |
|
28 |
|
29 // ----------------------------------------------------------------------------- |
|
30 // CIPMediaVideoSink::NewL() |
|
31 // First stage constructor |
|
32 // (other items were commented in a header). |
|
33 // ----------------------------------------------------------------------------- |
|
34 // |
|
35 CMccH263OldPayloadEncoder* CMccH263OldPayloadEncoder::NewL() |
|
36 { |
|
37 return new ( ELeave ) CMccH263OldPayloadEncoder(); |
|
38 } |
|
39 |
|
40 CMccH263OldPayloadEncoder::~CMccH263OldPayloadEncoder() |
|
41 { |
|
42 } |
|
43 |
|
44 // ----------------------------------------------------------------------------- |
|
45 // CIPMediaVideoSink::WriteBufferL() |
|
46 // Write media buffer |
|
47 // (other items were commented in a header). |
|
48 // ----------------------------------------------------------------------------- |
|
49 // |
|
50 void CMccH263OldPayloadEncoder::EncodeL( |
|
51 CMMFBuffer* aMMFBuffer, |
|
52 RPointerArray<CBufferContainer>& aDesBuffers ) |
|
53 { |
|
54 __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::EncodeL, enter") |
|
55 |
|
56 CMMFDataBuffer* buf = static_cast<CMMFDataBuffer*>( aMMFBuffer ); |
|
57 iSendHeader.iMarker = 0; |
|
58 |
|
59 // Get timestamp to RTP header. conversion to 90kHz clock |
|
60 TInt64 tmpStamp = ( buf->TimeToPlay().Int64() + iTimeStamp.Int64() ) / KConst100 * KConst9 ; |
|
61 iSendHeader.iTimestamp = TRtpTimeStamp( tmpStamp ) ; |
|
62 |
|
63 __H263FORMAT_MEDIA_INT2( "CMccH263OldPayloadEncoder::EncodeL, TimeStamp:", |
|
64 iSendHeader.iTimestamp, "Length:", buf->BufferSize() ) |
|
65 |
|
66 // Reset marker from last frame |
|
67 iSendHeader.iMarker = 0; |
|
68 |
|
69 // Get pointer to raw data |
|
70 TPtrC8 frame = buf->Data(); |
|
71 |
|
72 // Check that descriptor length is included. |
|
73 // Missing length causes panic in frame.Mid() function |
|
74 if ( frame.Length() == 0 || buf->BufferSize() != frame.Length() ) |
|
75 { |
|
76 __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::EncodeL, ERROR Buffer corrupted") |
|
77 User::Leave( KErrBadDescriptor ); |
|
78 } |
|
79 |
|
80 const TUint8 *dataPtr = buf->Data().Ptr(); |
|
81 // Get buffer length |
|
82 TUint frameLength = buf->BufferSize(); |
|
83 |
|
84 // Get frame header information |
|
85 GetHeaderInfoL( frame ); |
|
86 |
|
87 // If packet is smaller than max Packet size. Send right away |
|
88 if ( frame.Length() <= TInt( KVideoPacketSize ) ) |
|
89 { |
|
90 __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::EncodeL, Sending whole frame...") |
|
91 |
|
92 // Set marker to indicate last packet of current frame |
|
93 CreateNewBufferL( aMMFBuffer, |
|
94 aDesBuffers, |
|
95 frame, |
|
96 frameLength + KConst4, |
|
97 1 ); |
|
98 |
|
99 __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::EncodeL, exit" ) |
|
100 return; |
|
101 } |
|
102 |
|
103 // Initialize splitting variables |
|
104 TInt lastGOB = 0; |
|
105 TInt lastsend = 0; |
|
106 |
|
107 // Scan frame for GOBs |
|
108 for( TUint i= 0; i < frameLength; i++ ) |
|
109 { |
|
110 dataPtr += i; |
|
111 if ( *dataPtr == TUint8( 0x00 ) ) |
|
112 { |
|
113 dataPtr++; |
|
114 if ( *dataPtr == TUint8( 0x00 ) ) |
|
115 { |
|
116 dataPtr++; |
|
117 if ( TUint8( *dataPtr&0xfc )>0x80 ) |
|
118 { |
|
119 if ( ( i - lastsend ) >= KVideoPacketSize && lastGOB ) |
|
120 { |
|
121 __H263FORMAT_MEDIA_INT2("CMccH263OldPayloadEncoder::EncodeL(scan gobs), Sending packet f", |
|
122 lastsend, "len", ( lastGOB - lastsend ) ) |
|
123 |
|
124 // Packet size exceeded send new RTP Packet |
|
125 TPtrC8 packetData = |
|
126 frame.Mid( lastsend, ( lastGOB - lastsend ) ); |
|
127 |
|
128 CreateNewBufferL( aMMFBuffer, |
|
129 aDesBuffers, |
|
130 packetData, |
|
131 packetData.Length() + KConst4, |
|
132 iSendHeader.iMarker ); |
|
133 |
|
134 lastsend = lastGOB; |
|
135 } |
|
136 lastGOB = i; |
|
137 } |
|
138 } |
|
139 } |
|
140 // Return pointer to begining of frame |
|
141 dataPtr = frame.Ptr(); |
|
142 } |
|
143 |
|
144 // Check that last packet does not exceed packet size |
|
145 if ( ( frameLength - lastsend ) >= KVideoPacketSize && lastsend != 0 ) |
|
146 { |
|
147 __H263FORMAT_MEDIA_INT2("CMccH263OldPayloadEncoder::EncodeL(last packet check), Sending packet f", |
|
148 lastsend, "len", ( lastGOB - lastsend ) ) |
|
149 |
|
150 TPtrC8 packetData = |
|
151 frame.Mid( lastsend, ( lastGOB - lastsend ) ); |
|
152 |
|
153 CreateNewBufferL( aMMFBuffer, |
|
154 aDesBuffers, |
|
155 packetData, |
|
156 packetData.Length() + KConst4, |
|
157 iSendHeader.iMarker ); |
|
158 |
|
159 lastsend = lastGOB; |
|
160 } |
|
161 |
|
162 // Send last packet to RTP API |
|
163 if ( lastsend != 0 ) |
|
164 { |
|
165 __H263FORMAT_MEDIA_INT2("CMccH263OldPayloadEncoder::EncodeL(last packet), Sending packet f", |
|
166 lastsend, "len", ( frameLength - lastsend ) ) |
|
167 |
|
168 TPtrC8 packetData = |
|
169 frame.Mid( lastsend, ( frameLength - lastsend ) ); |
|
170 |
|
171 // Set marker to indicate last packet of current frame |
|
172 CreateNewBufferL( aMMFBuffer, |
|
173 aDesBuffers, |
|
174 packetData, |
|
175 packetData.Length() + KConst4, |
|
176 1 ); |
|
177 |
|
178 } |
|
179 |
|
180 // Special case no GOBs found try to send whole frame |
|
181 else |
|
182 { |
|
183 __H263FORMAT_MEDIA_INT1("CMccH263OldPayloadEncoder::EncodeL(no gobs), Sending whole packet len", |
|
184 frameLength ) |
|
185 |
|
186 if ( buf->BufferSize() > TInt( KVideoPacketSize + KConst4 ) ) |
|
187 { |
|
188 __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::EncodeL, ERROR, too big frame, exit") |
|
189 |
|
190 return; |
|
191 } |
|
192 |
|
193 // Set marker to indicate last packet of current frame |
|
194 CreateNewBufferL( aMMFBuffer, |
|
195 aDesBuffers, |
|
196 frame, |
|
197 frameLength + KConst4, |
|
198 1 ); |
|
199 |
|
200 } |
|
201 |
|
202 __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::EncodeL, exit") |
|
203 |
|
204 } |
|
205 |
|
206 // ----------------------------------------------------------------------------- |
|
207 // CMccH263OldPayloadEncoder::WriteHeaderData() |
|
208 // Write payload header information byte |
|
209 // (other items were commented in a header). |
|
210 // ----------------------------------------------------------------------------- |
|
211 // |
|
212 TUint8 CMccH263OldPayloadEncoder::WriteHeaderData( TInt aByte ) |
|
213 { |
|
214 __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::WriteHeaderData") |
|
215 |
|
216 //byte to be written |
|
217 TUint8 wbyte = 0; |
|
218 //construct needed byte |
|
219 switch ( aByte ) |
|
220 { |
|
221 case 0: |
|
222 { |
|
223 wbyte |= TUint8( headerA.F << KConst7 ); |
|
224 wbyte |= TUint8( headerA.P << KConst6 ); |
|
225 wbyte |= TUint8( headerA.SBIT << KConst3 ); |
|
226 wbyte |= TUint8( headerA.EBIT ); |
|
227 }break; |
|
228 case 1: |
|
229 { |
|
230 wbyte |= TUint8( headerA.SRC << KConst5 ); |
|
231 wbyte |= TUint8( headerA.I << KConst4 ); |
|
232 wbyte |= TUint8( headerA.U << KConst3 ); |
|
233 wbyte |= TUint8( headerA.S << KConst2 ); |
|
234 wbyte |= TUint8( headerA.A << 1 ); |
|
235 }break; |
|
236 case KConst2: |
|
237 { |
|
238 wbyte |= TUint8( headerA.DBQ << KConst3 ); |
|
239 wbyte |= TUint8( headerA.TRB ); |
|
240 }break; |
|
241 case KConst3: |
|
242 { |
|
243 wbyte = headerA.TR; |
|
244 }break; |
|
245 default: |
|
246 { |
|
247 }break; |
|
248 } |
|
249 //return constructed byte |
|
250 return wbyte; |
|
251 } |
|
252 |
|
253 // ----------------------------------------------------------------------------- |
|
254 // CMccH263OldPayloadEncoder::GetHeaderInfoL() |
|
255 // Get video frame header information |
|
256 // (other items were commented in a header). |
|
257 // ----------------------------------------------------------------------------- |
|
258 // |
|
259 void CMccH263OldPayloadEncoder::GetHeaderInfoL( TDesC8& aFrame ) |
|
260 { |
|
261 __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::GetHeaderInfoL") |
|
262 |
|
263 //fill in default values = 0 |
|
264 headerA.F = 0; |
|
265 headerA.P = 0; |
|
266 headerA.SBIT = 0; |
|
267 headerA.EBIT = 0; |
|
268 headerA.SRC = 0; |
|
269 headerA.I = 0; |
|
270 headerA.U = 0; |
|
271 headerA.S = 0; |
|
272 headerA.A = 0; |
|
273 headerA.R = 0; |
|
274 headerA.DBQ = 0; |
|
275 headerA.TRB = 0; |
|
276 headerA.TR = 0; |
|
277 |
|
278 //A S S U M I N G that aFrame begins with PSC |
|
279 const TUint8 *help; |
|
280 help = aFrame.Ptr(); |
|
281 //goto PTYPE-field |
|
282 help += KConst4; |
|
283 TUint8 test = 0; |
|
284 //get SRC |
|
285 test = TUint8( *help & 0x1c ); |
|
286 test >>= KConst2; |
|
287 headerA.SRC = test; |
|
288 if( headerA.SRC == KConst7 ) |
|
289 { |
|
290 #ifdef LOG |
|
291 IPUL_LOGC( 1, "VSink::GetHeaderInfoL> ERROR: Picture format unsupported" ); |
|
292 #endif |
|
293 } |
|
294 //get I parameter |
|
295 test = 0; |
|
296 test = TUint8( *help & 0x02 ); |
|
297 test >>= 1; |
|
298 headerA.I = test; |
|
299 //get U parameter |
|
300 test = 0; |
|
301 test = TUint8( *help & 0x01 ); |
|
302 headerA.U = test; |
|
303 //get S parameter |
|
304 help++; |
|
305 test = 0; |
|
306 test = TUint8( *help & 0x80 ); |
|
307 test >>= KConst7; |
|
308 headerA.S = test; |
|
309 //get A parameter |
|
310 test = 0; |
|
311 test = TUint8( *help & 0x40 ); |
|
312 test >>= KConst6; |
|
313 headerA.A = test; |
|
314 //get P parameter |
|
315 test = 0; |
|
316 test = TUint8( *help & 0x20 ); |
|
317 test >>= KConst5; |
|
318 headerA.P = test; |
|
319 //check for correct file format |
|
320 if ( headerA.P != 0 ) |
|
321 { |
|
322 #ifdef LOG |
|
323 IPUL_LOGC( 1 , "VSink::GetHeaderInfoL> ERROR: Unsupported file format" ); |
|
324 #endif |
|
325 } |
|
326 } |
|
327 |
|
328 // ----------------------------------------------------------------------------- |
|
329 // CMccH263OldPayloadEncoder::SetPayloadType() |
|
330 // ----------------------------------------------------------------------------- |
|
331 // |
|
332 void CMccH263OldPayloadEncoder::SetPayloadType( TUint8 aPayloadType ) |
|
333 { |
|
334 __H263FORMAT_MEDIA("CMccH263OldPayloadEncoder::SetPayloadType") |
|
335 |
|
336 iSendHeader.iPayloadType = aPayloadType; |
|
337 } |
|
338 |
|
339 // ----------------------------------------------------------------------------- |
|
340 // CMccH263OldPayloadEncoder::CreateNewBufferL() |
|
341 // ----------------------------------------------------------------------------- |
|
342 // |
|
343 void CMccH263OldPayloadEncoder::CreateNewBufferL( |
|
344 CMMFBuffer* aMMFBuffer, |
|
345 RPointerArray<CBufferContainer>& aDesBuffers, |
|
346 const TDesC8& aPacketData, |
|
347 TInt aLength, |
|
348 TInt aMarker ) |
|
349 { |
|
350 CMMFDataBuffer* newBuffer = |
|
351 CMMFDataBuffer::NewL( aLength ); |
|
352 CleanupStack::PushL( newBuffer ); |
|
353 newBuffer->Data().Append( WriteHeaderData( 0 ) ); |
|
354 newBuffer->Data().Append( WriteHeaderData( 1 ) ); |
|
355 newBuffer->Data().Append( WriteHeaderData( KConst2 ) ); |
|
356 newBuffer->Data().Append( WriteHeaderData( KConst3 ) ); |
|
357 newBuffer->Data().Append( aPacketData ); |
|
358 newBuffer->SetTimeToPlay( aMMFBuffer->TimeToPlay() ); |
|
359 newBuffer->SetFrameNumber( aMMFBuffer->FrameNumber() + iSequenceNumIncrementer ); |
|
360 |
|
361 // If frame is divided in several packets, sequence numbers of following |
|
362 // packets have to be modified |
|
363 if ( aMarker == 0 ) |
|
364 { |
|
365 iSequenceNumIncrementer++; |
|
366 } |
|
367 |
|
368 CBufferContainer* cont = new (ELeave) CBufferContainer(); |
|
369 CleanupStack::Pop( newBuffer ); |
|
370 cont->iBuffer = newBuffer; |
|
371 iSendHeader.iMarker = aMarker; |
|
372 cont->iSendHeader = iSendHeader; |
|
373 CleanupStack::PushL( cont ); |
|
374 aDesBuffers.AppendL( cont ); |
|
375 CleanupStack::Pop( cont ); |
|
376 } |
|
377 |