|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "tavsrcStreamer.h" |
|
17 #include "tavsrcUI.h" |
|
18 #include "tavsrcUtils.h" |
|
19 |
|
20 #include <bluetoothav.h> |
|
21 |
|
22 static const TSize KStreamerConsole(55,12); |
|
23 |
|
24 using namespace SymbianBluetoothAV; |
|
25 using namespace SymbianSBC; |
|
26 |
|
27 // |
|
28 // class CSbcTrackInfo |
|
29 // |
|
30 CSbcTrackInfo::~CSbcTrackInfo() |
|
31 { |
|
32 iFrameInfo.Close(); |
|
33 } |
|
34 |
|
35 TInt CSbcTrackInfo::GetLastFrameSize() |
|
36 { |
|
37 TInt frameSize = KErrNotFound; |
|
38 TInt count = iFrameInfo.Count(); |
|
39 |
|
40 if (count > 0) |
|
41 { |
|
42 frameSize = iFrameInfo[count - 1].iFrameSize; |
|
43 } |
|
44 return frameSize; |
|
45 } |
|
46 |
|
47 TInt CSbcTrackInfo::AddNewFrame(TInt aFrameSize) |
|
48 { |
|
49 TInt rerr = KErrNone; |
|
50 TInt count = iFrameInfo.Count(); |
|
51 |
|
52 if ((count > 0) && (iFrameInfo[count - 1].iFrameSize == aFrameSize)) |
|
53 { |
|
54 // another frame of the same size |
|
55 iFrameInfo[count - 1].iFrameCount++; |
|
56 } |
|
57 else |
|
58 { |
|
59 // add new frame info |
|
60 rerr = iFrameInfo.Append(TSbcTrackFrameInfo()); |
|
61 if (rerr == KErrNone) |
|
62 { |
|
63 iFrameInfo[count].iFrameSize = aFrameSize; |
|
64 iFrameInfo[count].iFrameCount = 1; |
|
65 } |
|
66 } |
|
67 return rerr; |
|
68 } |
|
69 |
|
70 TInt CSbcTrackInfo::RemoveLastFrame() |
|
71 { |
|
72 TInt rerr = KErrNotFound; |
|
73 TInt count = iFrameInfo.Count(); |
|
74 |
|
75 if (count > 0) |
|
76 { |
|
77 if (iFrameInfo[count - 1].iFrameCount > 1) |
|
78 { |
|
79 // remove one of the instances of the last frame size |
|
80 iFrameInfo[count - 1].iFrameCount--; |
|
81 } |
|
82 else |
|
83 { |
|
84 // remove the last frame info |
|
85 iFrameInfo.Remove(count - 1); |
|
86 } |
|
87 rerr = KErrNone; |
|
88 } |
|
89 return rerr; |
|
90 } |
|
91 |
|
92 void CSbcTrackInfo::Reset() |
|
93 { |
|
94 iFrameInfo.Reset(); |
|
95 } |
|
96 |
|
97 // |
|
98 // class CActiveStreamer |
|
99 // |
|
100 CActiveStreamer* CActiveStreamer::NewL(RSocketArray aSockets, |
|
101 CConsoleBase& aConsole, |
|
102 MActiveStreamerUser& aUser, |
|
103 TUint aDisplayMode, |
|
104 TBool aPreloadFile) |
|
105 { |
|
106 CActiveStreamer* self = new (ELeave) CActiveStreamer (aConsole, aUser, aDisplayMode, aPreloadFile); |
|
107 CleanupStack::PushL(self); |
|
108 self->ConstructL(aSockets); |
|
109 CleanupStack::Pop(); |
|
110 return self; |
|
111 } |
|
112 |
|
113 CActiveStreamer::CActiveStreamer(CConsoleBase& aConsole, MActiveStreamerUser& aUser, TUint aDisplayMode, TBool aPreloadFile) |
|
114 : iConsole(aConsole), iUser(aUser), iDisplayMode(aDisplayMode), iPreloadFile(aPreloadFile), iSbcFrameRate(1), iDirectionForward(ETrue) |
|
115 { |
|
116 iRTPCanSend = ETrue; |
|
117 } |
|
118 |
|
119 CActiveStreamer::~CActiveStreamer() |
|
120 { |
|
121 delete iTimer; |
|
122 |
|
123 iSendSource.Close(); |
|
124 iSession.Close(); |
|
125 iSockets[0].Close(); |
|
126 delete iFiles; |
|
127 iFile.Close(); |
|
128 iRFs.Close(); |
|
129 |
|
130 delete iProgressBar; |
|
131 DestroyBucket(); |
|
132 delete iStreamingInfoConsole; |
|
133 |
|
134 delete iFileBuf; |
|
135 iFileBuf = NULL; |
|
136 |
|
137 delete iStreamerUI; |
|
138 iStreamerUI = NULL; |
|
139 } |
|
140 |
|
141 void CActiveStreamer::Stream(TBool aIsSink) |
|
142 { |
|
143 |
|
144 if (!aIsSink) |
|
145 { |
|
146 iStartedTime.UniversalTime(); |
|
147 iTimer->Start(iNominalSendClockInterval); |
|
148 Drip(); |
|
149 } |
|
150 else |
|
151 { |
|
152 //as sink, we do want to start up rtp and await its notification of a NewSource |
|
153 //Nothing to do at the moment, because when INT is a SNK, |
|
154 //it just needs to get the RTP packets running and wait for notification. |
|
155 //This has already been done in constructor of the class. |
|
156 } |
|
157 iStreamerUI->Play(); |
|
158 } |
|
159 |
|
160 void CActiveStreamer::Suspend() |
|
161 { |
|
162 iTimer->Cancel(); // stop callbacks to send |
|
163 iStreamerUI->Pause(); |
|
164 } |
|
165 |
|
166 void CActiveStreamer::ReStream() |
|
167 { |
|
168 |
|
169 |
|
170 iTimer->Start(iNominalSendClockInterval); |
|
171 Drip(); |
|
172 iStreamerUI->Play(); |
|
173 } |
|
174 |
|
175 |
|
176 void CActiveStreamer::Stop() |
|
177 { |
|
178 iTimer->Cancel(); |
|
179 iStreamerUI->Stop(); |
|
180 |
|
181 iFillLevel = 0; |
|
182 iPos = 0; |
|
183 } |
|
184 |
|
185 void CActiveStreamer::Pause() |
|
186 { |
|
187 iTimer->Cancel(); |
|
188 iStreamerUI->Pause(); |
|
189 } |
|
190 |
|
191 |
|
192 void CActiveStreamer::NextTrack() |
|
193 { |
|
194 iPos=0; |
|
195 if (iCurrentFile < iFiles->Count() - 1) |
|
196 { |
|
197 iCurrentFile++; |
|
198 iStreamerUI->Next(); |
|
199 } |
|
200 else |
|
201 { |
|
202 iCurrentFile = 0; |
|
203 iStreamerUI->First(); |
|
204 } |
|
205 TRAPD(err, InitL()); |
|
206 if (err) |
|
207 { |
|
208 iConsole.Printf(_L("InitL failed with error: %d"),err); |
|
209 } |
|
210 } |
|
211 |
|
212 void CActiveStreamer::PrevTrack() |
|
213 { |
|
214 iPos=0; |
|
215 if (iCurrentFile>0) |
|
216 { |
|
217 iCurrentFile--; |
|
218 iStreamerUI->Prev(); |
|
219 } |
|
220 TRAPD(err, InitL()); |
|
221 if (err) |
|
222 { |
|
223 iConsole.Printf(_L("InitL failed with error: %d"),err); |
|
224 } |
|
225 } |
|
226 |
|
227 void CActiveStreamer::InitL() |
|
228 { |
|
229 // close current file |
|
230 iFile.Close(); |
|
231 delete iProgressBar; |
|
232 iProgressBar = NULL; |
|
233 |
|
234 // get file details |
|
235 RBuf filename; |
|
236 filename.Create(100); |
|
237 filename.Append(KSBCFileRoot); |
|
238 filename.Append(iFiles->operator[](iCurrentFile).iName); |
|
239 |
|
240 User::LeaveIfError(iFile.Open(iRFs,filename,EFileRead | EFileShareReadersOnly)); |
|
241 |
|
242 TInt numChannels, chMode, numSubbands, blkLen, bitPool, freq, allocMethod; |
|
243 User::LeaveIfError(TTavsrcUtils::GetCodecSettingsFromSBCFile(filename, chMode, numChannels, numSubbands, blkLen, bitPool, freq, allocMethod)); |
|
244 |
|
245 if (iStreamingInfoConsole) |
|
246 { |
|
247 iStreamingInfoConsole->Printf(_L("\nFirst SBC frame info for: %S...\n"), &filename); |
|
248 } |
|
249 |
|
250 filename.Close(); |
|
251 |
|
252 // determine if a re-configuration is required |
|
253 if ((iNumChannels != numChannels) || (iFreq != freq) || |
|
254 (iChMode != chMode) || (iBitPool != bitPool) || |
|
255 (iBlkLen != blkLen) || (iNumSubbands != numSubbands) || |
|
256 (iAllocMethod != allocMethod)) |
|
257 { |
|
258 iNumChannels = numChannels; |
|
259 iChMode = chMode; |
|
260 iNumSubbands = numSubbands; |
|
261 iBlkLen = blkLen; |
|
262 iBitPool = bitPool; |
|
263 iFreq = freq; |
|
264 iAllocMethod = allocMethod; |
|
265 |
|
266 // configuration is set first time around |
|
267 if (iSBCFrameSize != 0) |
|
268 { |
|
269 TSBCCodecCapabilities cfg; |
|
270 |
|
271 TSBCSubbandsBitmask subbands = numSubbands == 8 ? EEightSubbands : EFourSubbands; |
|
272 TSBCAllocationMethodBitmask alloc = allocMethod == 0 ? ELoudness : ESNR; |
|
273 |
|
274 TSBCSamplingFrequencyBitmask freqs(0); |
|
275 if (freq == 48000) freqs = E48kHz; |
|
276 else if (freq == 44100) freqs = E44100Hz; // note else if now as only select one |
|
277 else if (freq == 32000) freqs = E32kHz; |
|
278 else if (freq == 16000) freqs = E16kHz; |
|
279 |
|
280 TSBCChannelModeBitmask chs(0); // set it to anything to prevent warning |
|
281 if (chMode == 0) chs=EMono; |
|
282 else if (chMode == 1) chs=EDualChannel; |
|
283 else if (chMode == 2) chs=EStereo; |
|
284 else if (chMode == 3) chs=EJointStereo; |
|
285 |
|
286 TSBCBlockLengthBitmask blkLens(0); // set it to anything to prevent warning |
|
287 if (blkLen == 4) blkLens = EBlockLenFour; |
|
288 else if (blkLen == 8) blkLens = EBlockLenEight; |
|
289 else if (blkLen == 12) blkLens = EBlockLenTwelve; |
|
290 else if (blkLen == 16) blkLens = EBlockLenSixteen; |
|
291 |
|
292 cfg.SetSamplingFrequencies(freqs); |
|
293 cfg.SetChannelModes(chs); |
|
294 cfg.SetBlockLengths(blkLens); |
|
295 cfg.SetSubbands(subbands); |
|
296 cfg.SetAllocationMethods(alloc); |
|
297 |
|
298 // reconfig required |
|
299 iUser.MediaCodecConfigurationRequired(cfg); |
|
300 |
|
301 // ensure no more timer events until we have finished reconfiguring |
|
302 iTimer->Cancel(); |
|
303 } |
|
304 |
|
305 if (chMode == 0 || chMode == 1) |
|
306 { |
|
307 iSBCFrameSize = 4+TReal((4*numSubbands*numChannels))/8+TTavsrcUtils::CEIL(TReal(blkLen*numChannels*bitPool)/8); |
|
308 } |
|
309 else |
|
310 { |
|
311 TBool join = chMode == 0x03; |
|
312 |
|
313 iSBCFrameSize = 4+TReal((4*numSubbands*numChannels))/8+TTavsrcUtils::CEIL(TReal((join*numSubbands+blkLen*bitPool))/8); |
|
314 } |
|
315 |
|
316 iSBCBitrate = 8*iSBCFrameSize*freq/(numSubbands*blkLen); |
|
317 TUint64 numerator = TUint64(8000000)*iSBCFrameSize; |
|
318 iSBCFrameInterval = (numerator)/iSBCBitrate; //microsecs |
|
319 } |
|
320 |
|
321 iSbcTrackInfo.Reset(); |
|
322 iSbcTrackInfo.AddNewFrame(iSBCFrameSize); |
|
323 |
|
324 iDirectionForward = ETrue; |
|
325 iSbcFrameRate = 1; |
|
326 |
|
327 User::LeaveIfError(iFile.Size(iFileSize)); |
|
328 |
|
329 if (iStreamingInfoConsole) |
|
330 { |
|
331 iStreamingInfoConsole->Printf(_L("Sampling Frequency: %d Hz\n"), iFreq); |
|
332 iStreamingInfoConsole->Printf(_L("Subbands: %d\n"), iNumSubbands); |
|
333 iStreamingInfoConsole->Printf(_L("BlkLen: %d\n"), iBlkLen); |
|
334 iStreamingInfoConsole->Printf(_L("ChannelMode: %d\n"), iChMode); |
|
335 iStreamingInfoConsole->Printf(_L("AllocMethod: %d\n"), iAllocMethod); |
|
336 iStreamingInfoConsole->Printf(_L("Bitpool: %d\n"), iBitPool); |
|
337 iStreamingInfoConsole->Printf(_L("SBC Frame size: %d bytes\n"), iSBCFrameSize); |
|
338 iStreamingInfoConsole->Printf(_L("Bitrate: %d bps\n"), iSBCBitrate); |
|
339 } |
|
340 |
|
341 TInt err = LoadFile(); |
|
342 if(err==KErrNone) |
|
343 { |
|
344 if (iDisplayMode & EProgressBarWindow) |
|
345 { |
|
346 iProgressBar = CProgressBar::NewL(iFileSize); |
|
347 } |
|
348 FillBucket(); |
|
349 } |
|
350 else |
|
351 { |
|
352 User::Leave(err); |
|
353 } |
|
354 // start the timer for this file |
|
355 iStartTime.UniversalTime(); |
|
356 } |
|
357 |
|
358 void CActiveStreamer::UpdateFrameInfo() |
|
359 { |
|
360 TInt numChannels, chMode, numSubbands, blkLen, bitPool, freq, allocMethod; |
|
361 User::LeaveIfError(TTavsrcUtils::GetCodecSettingsFromSBCFile(iFile, iPos, chMode, numChannels, numSubbands, blkLen, bitPool, freq, allocMethod)); |
|
362 |
|
363 // determine if a re-configuration is required |
|
364 if ((iNumChannels != numChannels)|| (iFreq != freq) || |
|
365 (iChMode != chMode) || (iBitPool != bitPool) || |
|
366 (iBlkLen != blkLen) || (iNumSubbands != numSubbands) || |
|
367 (iAllocMethod != allocMethod)) |
|
368 { |
|
369 iNumChannels = numChannels; |
|
370 iChMode = chMode; |
|
371 iNumSubbands = numSubbands; |
|
372 iBlkLen = blkLen; |
|
373 iBitPool = bitPool; |
|
374 iFreq = freq; |
|
375 iAllocMethod = allocMethod; |
|
376 |
|
377 TInt newFrameSize = 0; |
|
378 if (chMode == 0 || chMode == 1) |
|
379 { |
|
380 newFrameSize = 4+TReal((4*numSubbands*numChannels))/8+TTavsrcUtils::CEIL(TReal(blkLen*numChannels*bitPool)/8); |
|
381 } |
|
382 else |
|
383 { |
|
384 TBool join = chMode == 0x03; |
|
385 |
|
386 newFrameSize = 4+TReal((4*numSubbands*numChannels))/8+TTavsrcUtils::CEIL(TReal((join*numSubbands+blkLen*bitPool))/8); |
|
387 } |
|
388 |
|
389 if (newFrameSize != iSBCFrameSize) |
|
390 { |
|
391 // work out timer for SBC frame |
|
392 iSBCBitrate = 8*newFrameSize*freq/(numSubbands*blkLen); |
|
393 |
|
394 TUint64 numerator = TUint64(8000000)*iSBCFrameSize; |
|
395 iSBCFrameInterval = (numerator)/iSBCBitrate; //microsecs |
|
396 } |
|
397 iSBCFrameSize = newFrameSize; |
|
398 } |
|
399 } |
|
400 |
|
401 void CActiveStreamer::TimerEvent(CAdaptiveHighResPeriodic& /*aTimer*/) |
|
402 { |
|
403 if (iRTPCanSend) |
|
404 { |
|
405 iSent++; |
|
406 } |
|
407 else |
|
408 { |
|
409 // move iPos on anyway? |
|
410 iFailedSend++; |
|
411 } |
|
412 DoTimerEvent(); |
|
413 } |
|
414 |
|
415 void CActiveStreamer::TimerError(CAdaptiveHighResPeriodic& /*aTimer*/, TInt aError) |
|
416 { |
|
417 iConsole.Printf(_L("*ERROR %d*\n"), aError); |
|
418 __DEBUGGER(); |
|
419 } |
|
420 |
|
421 |
|
422 void CActiveStreamer::DoTimerEvent() |
|
423 { |
|
424 FillBucket(); |
|
425 Drip(); |
|
426 CheckJammed(); |
|
427 } |
|
428 |
|
429 void CActiveStreamer::FillBucket() |
|
430 { |
|
431 // fill up bucket - it may be fully empty or partially full, but top it up in all cases |
|
432 if (iFillLevel < KLowTidemark) |
|
433 { |
|
434 for (/*iFillLevel*/; iFillLevel < KSendBucketSize; iFillLevel++) |
|
435 { |
|
436 // get the next RTP packet to send |
|
437 RRtpSendPacket& sendPacket = iSendPackets[iFillLevel]; |
|
438 TDes8& payload = sendPacket.WritePayload(); |
|
439 payload.Zero(); |
|
440 payload.Append(0); // update this later with number of frames in packet. |
|
441 |
|
442 TInt spaceInRtpPacket = iSBCFrameBytesPerRTP; |
|
443 TInt framesAdded = 0; |
|
444 TInt packetInterval = 0; |
|
445 |
|
446 TInt nextFrameSize = iDirectionForward ? iSBCFrameSize : iSbcTrackInfo.GetLastFrameSize(); |
|
447 |
|
448 TBool moreFrames = ETrue; |
|
449 while ((nextFrameSize > 0) && (nextFrameSize <= spaceInRtpPacket) && (framesAdded <= 15) && moreFrames) |
|
450 { |
|
451 // add frame |
|
452 if (iPreloadFile) |
|
453 { |
|
454 TPtrC8 ptr(iFileBuf->Des().Ptr()+iPos, nextFrameSize); |
|
455 payload.Append(ptr); |
|
456 } |
|
457 else |
|
458 { |
|
459 TPtr8 ptr(const_cast<TUint8*>(iFileBuf->Des().Ptr()), 0, nextFrameSize); |
|
460 iFile.Read(iPos, ptr); |
|
461 payload.Append(ptr); |
|
462 } |
|
463 framesAdded++; |
|
464 packetInterval+=iSBCFrameInterval; |
|
465 spaceInRtpPacket-=nextFrameSize; |
|
466 |
|
467 // get next frame information |
|
468 for (TInt count = 0; (count != iSbcFrameRate) && moreFrames; count++) |
|
469 { |
|
470 iPos = iDirectionForward ? iPos + nextFrameSize : iPos - nextFrameSize; |
|
471 |
|
472 // determine if we are done with the current file |
|
473 if ((iPos >= iFileSize) || (iPos < 0)) |
|
474 { |
|
475 moreFrames = EFalse; |
|
476 } |
|
477 else |
|
478 { |
|
479 TInt err = KErrNone; |
|
480 if (iDirectionForward) |
|
481 { |
|
482 // keep track of the frame sizes as we go, this is used to rewind, |
|
483 // i.e. iDirectionForward = EFalse |
|
484 if ((err = iSbcTrackInfo.AddNewFrame(iSBCFrameSize)) != KErrNone) |
|
485 { |
|
486 iConsole.Printf(_L("Error adding SBC frame information: %d\n"), err); |
|
487 __DEBUGGER(); |
|
488 } |
|
489 } |
|
490 else |
|
491 { |
|
492 if ((err = iSbcTrackInfo.RemoveLastFrame()) != KErrNone) |
|
493 { |
|
494 // this should never happen as we always check the length first |
|
495 iConsole.Printf(_L("Error removing SBC frame information: %d\n"), err); |
|
496 __DEBUGGER(); |
|
497 } |
|
498 } |
|
499 UpdateFrameInfo(); |
|
500 nextFrameSize = iDirectionForward ? iSBCFrameSize : iSbcTrackInfo.GetLastFrameSize(); |
|
501 } |
|
502 } |
|
503 } |
|
504 |
|
505 // has the interval changed since last time we set the timer |
|
506 if ((iNominalSendClockInterval != packetInterval) && moreFrames) |
|
507 { |
|
508 // adjust timer |
|
509 if (iStreamingInfoConsole) |
|
510 { |
|
511 iStreamingInfoConsole->Printf(_L("Interval change from: %d to %d\n"), iNominalSendClockInterval, packetInterval); |
|
512 } |
|
513 iNominalSendClockInterval = packetInterval; |
|
514 iTimer->SetInterval(iNominalSendClockInterval); |
|
515 } |
|
516 |
|
517 // write number of SBC frames into packet |
|
518 payload[0] = TChar(framesAdded); |
|
519 |
|
520 //DrawBucket(); //<--- to animate the display |
|
521 |
|
522 if (iPos > iFileSize) |
|
523 { |
|
524 // time to do some metrics, and loop back to beginning |
|
525 TTime finTime; |
|
526 finTime.UniversalTime(); |
|
527 |
|
528 TInt64 secs; |
|
529 secs = (finTime.MicroSecondsFrom(iStartTime)).Int64(); |
|
530 |
|
531 TInt bps = (iFileSize*8LL*1000000LL)/secs; |
|
532 iConsole.Printf(_L("Looping. fail=%d, sent=%d, bytes=%d, secs=%Ld"), iFailedSend, iSent, iFileSize, secs); |
|
533 iConsole.Printf(_L(" bps=%d\n"), bps); |
|
534 |
|
535 iFailedSend=0; |
|
536 iSent=0; |
|
537 iPos=0; // loop |
|
538 |
|
539 RDebug::Printf("Looping"); |
|
540 NextTrack(); |
|
541 |
|
542 // restart the timer |
|
543 iTimer->Start(iNominalSendClockInterval); |
|
544 } |
|
545 else if (iPos <= 0) |
|
546 { |
|
547 PrevTrack(); |
|
548 } |
|
549 else if (iProgressBar) |
|
550 { |
|
551 iProgressBar->Increment(iPos-iProgressBarPos); |
|
552 iProgressBarPos = iPos; |
|
553 } |
|
554 } |
|
555 iPreviousFillLevel = iFillLevel; |
|
556 } |
|
557 } |
|
558 |
|
559 void CActiveStreamer::DrawBucket() |
|
560 { |
|
561 if (iStreamingInfoConsole) |
|
562 { |
|
563 iStreamingInfoConsole->SetPos(1,1); |
|
564 |
|
565 TBuf<KSendBucketSize> bar; |
|
566 bar.AppendFill('#',iFillLevel); |
|
567 bar.AppendFill('.',KSendBucketSize-iFillLevel); |
|
568 |
|
569 iStreamingInfoConsole->Printf(bar); |
|
570 } |
|
571 } |
|
572 |
|
573 void CActiveStreamer::Drip() |
|
574 { |
|
575 // take head packet |
|
576 RRtpSendPacket& packet = iSendPackets[0]; //packet=oldpacket |
|
577 |
|
578 // move previous packet to back - it is reusable, so we don't close |
|
579 // instead just move to back so that the packet to send is at head |
|
580 iSendPackets.Remove(0); |
|
581 iSendPackets.Append(packet); |
|
582 |
|
583 if (iRTPCanSend && iFillLevel > 0) |
|
584 { |
|
585 // take oldest packet and give to RTP |
|
586 packet.Send(); |
|
587 iRTPCanSend = EFalse; |
|
588 iFillLevel--; |
|
589 //DrawBucket(); //<--- to animate the display |
|
590 } |
|
591 else |
|
592 { |
|
593 // not ready to send yet but when we are send straight away |
|
594 iBonusDrip = ETrue; |
|
595 |
|
596 // remember this as a fail to measure |
|
597 // let code beneath recycle packet |
|
598 iFailedSend++; |
|
599 } |
|
600 } |
|
601 |
|
602 void CActiveStreamer::ConstructL(RSocketArray aSockets) |
|
603 { |
|
604 iTimer = CAdaptiveHighResPeriodic::NewL(*this); |
|
605 |
|
606 if (iDisplayMode & EStreamerInfoWindow) |
|
607 { |
|
608 iStreamingInfoConsole = Console::NewL(_L("Streamer"), KStreamerConsole); |
|
609 } |
|
610 |
|
611 User::LeaveIfError(iRFs.Connect()); |
|
612 |
|
613 iSockets = aSockets; |
|
614 |
|
615 TPckgBuf<TInt> mruBuf; |
|
616 iSockets[0].GetOpt(EAvdtpMediaGetMaximumReceivePacketSize, KSolBtAVDTPMedia, mruBuf); |
|
617 |
|
618 // donate media socket to rtp |
|
619 iSession.OpenL(iSockets[0], mruBuf()); |
|
620 |
|
621 // we get all RTP events in one place (could have them separately) |
|
622 iSession.RegisterEventCallbackL(ERtpAnyEvent, |
|
623 RTPCallbackL, |
|
624 this); |
|
625 |
|
626 iSendSource = iSession.NewSendSourceL(); |
|
627 |
|
628 iSendSource.RegisterEventCallbackL(ERtpAnyEvent, |
|
629 RTPCallbackL, |
|
630 this); |
|
631 |
|
632 iStreamerUI = CStreamerUI::NewL((iDisplayMode & EPlaylistWindow), (iDisplayMode & EChunkyIconWindow)); |
|
633 |
|
634 TInt err = iRFs.GetDir(KSBCFiles, KEntryAttNormal, ESortByName, iFiles); |
|
635 |
|
636 // set playlist |
|
637 for (TInt i=0; i<iFiles->Count(); i++) |
|
638 { |
|
639 iStreamerUI->AddTitle(iFiles->operator[](i).iName); |
|
640 } |
|
641 |
|
642 err = aSockets[0].GetOpt(EAvdtpMediaGetMaximumPacketSize, KSolBtAVDTPMedia, iMTU); |
|
643 |
|
644 iSBCFrameBytesPerRTP = iMTU - 12 - 1; |
|
645 iSendSource.SetDefaultPayloadSize(iSBCFrameBytesPerRTP+1); |
|
646 |
|
647 CreateBucketL(); |
|
648 InitL(); |
|
649 } |
|
650 |
|
651 void CActiveStreamer::CreateBucketL() |
|
652 { |
|
653 if (iSendPackets.Count() == KSendBucketSize) |
|
654 { |
|
655 RDebug::Printf("Bucket already created"); |
|
656 } |
|
657 else |
|
658 { |
|
659 RDebug::Printf("Creating bucket"); |
|
660 // create all the RTP send packets now |
|
661 for (TInt i=0; i<KSendBucketSize ; i++) |
|
662 { |
|
663 User::LeaveIfError(iSendPackets.Append(iSendSource.NewSendPacketL())); |
|
664 RDebug::Printf("Adding Sendpacket 0x%08x in bucket", &iSendPackets[i]); |
|
665 } |
|
666 } |
|
667 } |
|
668 |
|
669 void CActiveStreamer::DestroyBucket() |
|
670 { |
|
671 RDebug::Printf("Destroying bucket"); |
|
672 |
|
673 // rtp bug closing these packets? |
|
674 iSendPackets.Reset(); |
|
675 } |
|
676 |
|
677 /*static*/ void CActiveStreamer::RTPCallbackL(CActiveStreamer* aStreamer, const TRtpEvent& aEvent) |
|
678 { |
|
679 switch (aEvent.Type()) |
|
680 { |
|
681 case ERtpSendFail: |
|
682 if (aStreamer->iStreamingInfoConsole) |
|
683 { |
|
684 aStreamer->iStreamingInfoConsole->Printf(_L("\n**RTP SEND FAILURE**")); |
|
685 } |
|
686 break; |
|
687 |
|
688 case ERtpSendSucceeded: |
|
689 aStreamer->iRTPCanSend = ETrue; |
|
690 if (aStreamer->iBonusDrip) |
|
691 { |
|
692 aStreamer->Drip(); |
|
693 aStreamer->iBonusDrip = EFalse; |
|
694 } |
|
695 break; |
|
696 |
|
697 case ERtpSourceFail: |
|
698 if (aStreamer->iStreamingInfoConsole) |
|
699 { |
|
700 aStreamer->iStreamingInfoConsole->Printf(_L("\n**RTP SOURCE FAILURE**")); |
|
701 } |
|
702 break; |
|
703 |
|
704 |
|
705 case ERtpNewSource: |
|
706 if (aStreamer->iStreamingInfoConsole) |
|
707 { |
|
708 aStreamer->iStreamingInfoConsole->Printf(_L("\n**NEW SOURCE!\n")); |
|
709 } |
|
710 aStreamer->StartSinkL(); |
|
711 break; |
|
712 |
|
713 case ERtpPacketReceived: |
|
714 RRtpPacket packet = aStreamer->iReceiveSource.Packet(); |
|
715 if (aStreamer->iStreamingInfoConsole) |
|
716 { |
|
717 aStreamer->iStreamingInfoConsole->Printf(_L("SNK Rxd packet ")); |
|
718 aStreamer->iStreamingInfoConsole->Printf(_L("SeqNo %d\n"),packet.SequenceNumber()); |
|
719 } |
|
720 break; |
|
721 } |
|
722 } |
|
723 |
|
724 void CActiveStreamer::StartSinkL() |
|
725 { |
|
726 iReceiveSource = iSession.NewReceiveSourceL(); |
|
727 iReceiveSource.RegisterEventCallbackL(ERtpAnyEvent, |
|
728 RTPCallbackL, |
|
729 this); |
|
730 } |
|
731 |
|
732 TInt CActiveStreamer::LoadFile() |
|
733 { |
|
734 RDebug::Printf("Loading file"); |
|
735 delete iFileBuf; |
|
736 iFileBuf = NULL; |
|
737 |
|
738 TInt err = KErrNone; |
|
739 |
|
740 if (iPreloadFile) |
|
741 { |
|
742 if (iStreamingInfoConsole) |
|
743 { |
|
744 iStreamingInfoConsole->Printf(_L("Preloading SBC file\n")); |
|
745 } |
|
746 |
|
747 // max heap is something or other |
|
748 const TInt KMaxHeap = 4000000; |
|
749 TInt size = iFileSize; |
|
750 size = Min(iFileSize, KMaxHeap); |
|
751 TRAP(err, iFileBuf = HBufC8::NewL(size)); |
|
752 if (err) |
|
753 { |
|
754 return err; |
|
755 } |
|
756 iFileSize = Min(KMaxHeap, iFileSize); |
|
757 |
|
758 TPtr8 ptr(const_cast<TUint8*>(iFileBuf->Des().Ptr()), 0, iFileSize); |
|
759 |
|
760 const TEntry& entry = iFiles->operator[](iCurrentFile); |
|
761 RFile test; |
|
762 test.Open(iRFs, entry.iName, EFileRead); |
|
763 |
|
764 ptr.Zero(); |
|
765 err=iFile.Read(ptr); |
|
766 } |
|
767 else |
|
768 { |
|
769 if (iStreamingInfoConsole) |
|
770 { |
|
771 iStreamingInfoConsole->Printf(_L("Streaming from file\n")); |
|
772 } |
|
773 |
|
774 // read from file to be more "streaming"-like |
|
775 TRAP(err, iFileBuf = HBufC8::NewL(Min(iFileSize, iSBCFrameBytesPerRTP))); |
|
776 } |
|
777 return err; |
|
778 } |
|
779 |
|
780 void CActiveStreamer::Faster() |
|
781 { |
|
782 // limit the speed |
|
783 if (iSbcFrameRate < 5) |
|
784 { |
|
785 iSbcFrameRate++; |
|
786 } |
|
787 } |
|
788 |
|
789 void CActiveStreamer::Slower() |
|
790 { |
|
791 if (iSbcFrameRate > 1) |
|
792 { |
|
793 iSbcFrameRate--; |
|
794 } |
|
795 } |
|
796 |
|
797 void CActiveStreamer::Backward() |
|
798 { |
|
799 iDirectionForward=EFalse; |
|
800 } |
|
801 |
|
802 void CActiveStreamer::Forward() |
|
803 { |
|
804 iDirectionForward=ETrue; |
|
805 } |
|
806 |
|
807 void CActiveStreamer::CheckJammed() |
|
808 { |
|
809 if (iFillLevel==iPreviousFillLevel) |
|
810 { |
|
811 if ((iBucketAppearsJammed++ > 500) && iStreamingInfoConsole) |
|
812 { |
|
813 iStreamingInfoConsole->Printf(_L("BUCKET JAMMED\n")); |
|
814 iStreamingInfoConsole->Printf(_L("iFillLevel %d "),iFillLevel); |
|
815 iStreamingInfoConsole->Printf(_L("iRTPCanSend %d "),iRTPCanSend); |
|
816 iStreamingInfoConsole->Printf(_L("iFailedSend %d "),iFailedSend); |
|
817 iStreamingInfoConsole->Printf(_L("iPos %d "),iPos); |
|
818 |
|
819 TTime now; |
|
820 now.UniversalTime(); |
|
821 |
|
822 TInt millisecs = now.MicroSecondsFrom(iLastPacketSentTime).Int64()/1000; |
|
823 iStreamingInfoConsole->Printf(_L("time since last send %d ms "),millisecs); |
|
824 } |
|
825 } |
|
826 else |
|
827 { |
|
828 iBucketAppearsJammed = 0; |
|
829 } |
|
830 } |