blob: 574fd7e4e2a5ea072ff3829018cdddde078393bd [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
mflodman@webrtc.org1f992802012-01-27 13:42:53 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "file_player_impl.h"
12#include "trace.h"
13
14#ifdef WEBRTC_MODULE_UTILITY_VIDEO
15 #include "cpu_wrapper.h"
16 #include "frame_scaler.h"
17 #include "tick_util.h"
18 #include "video_coder.h"
19#endif
20
21// OS independent case insensitive string comparison.
22#ifdef WIN32
23 #define STR_CASE_CMP(x,y) ::_stricmp(x,y)
24#else
25 #define STR_CASE_CMP(x,y) ::strcasecmp(x,y)
26#endif
27
28namespace webrtc {
29FilePlayer* FilePlayer::CreateFilePlayer(WebRtc_UWord32 instanceID,
30 FileFormats fileFormat)
31{
32 switch(fileFormat)
33 {
34 case kFileFormatWavFile:
35 case kFileFormatCompressedFile:
36 case kFileFormatPreencodedFile:
37 case kFileFormatPcm16kHzFile:
38 case kFileFormatPcm8kHzFile:
39 case kFileFormatPcm32kHzFile:
40 // audio formats
41 return new FilePlayerImpl(instanceID, fileFormat);
niklase@google.com470e71d2011-07-07 08:21:25 +000042 case kFileFormatAviFile:
mflodman@webrtc.orgc80d9d92012-02-06 10:11:25 +000043#ifdef WEBRTC_MODULE_UTILITY_VIDEO
niklase@google.com470e71d2011-07-07 08:21:25 +000044 return new VideoFilePlayerImpl(instanceID, fileFormat);
mflodman@webrtc.orgc80d9d92012-02-06 10:11:25 +000045#else
46 WEBRTC_TRACE(kTraceError, kTraceFile, -1,
47 "Invalid file format: %d", kFileFormatAviFile);
48 assert(false);
niklase@google.com470e71d2011-07-07 08:21:25 +000049 return NULL;
mflodman@webrtc.orgc80d9d92012-02-06 10:11:25 +000050#endif
niklase@google.com470e71d2011-07-07 08:21:25 +000051 }
mflodman@webrtc.org657b2a42012-02-06 11:06:01 +000052 assert(false);
53 return NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +000054}
55
56void FilePlayer::DestroyFilePlayer(FilePlayer* player)
57{
58 delete player;
59}
60
61FilePlayerImpl::FilePlayerImpl(const WebRtc_UWord32 instanceID,
62 const FileFormats fileFormat)
63 : _instanceID(instanceID),
64 _fileFormat(fileFormat),
65 _fileModule(*MediaFile::CreateMediaFile(instanceID)),
66 _decodedLengthInMS(0),
67 _audioDecoder(instanceID),
68 _codec(),
69 _numberOf10MsPerFrame(0),
70 _numberOf10MsInDecoder(0),
henrike@webrtc.org6b9253e2012-02-15 18:48:16 +000071 _resampler(),
niklase@google.com470e71d2011-07-07 08:21:25 +000072 _scaling(1.0)
73{
74 _codec.plfreq = 0;
75}
76
77FilePlayerImpl::~FilePlayerImpl()
78{
79 MediaFile::DestroyMediaFile(&_fileModule);
80}
81
82WebRtc_Word32 FilePlayerImpl::Frequency() const
83{
84 if(_codec.plfreq == 0)
85 {
86 return -1;
87 }
88 // Make sure that sample rate is 8,16 or 32 kHz. E.g. WAVE files may have
89 // other sampling rates.
90 if(_codec.plfreq == 11000)
91 {
92 return 16000;
93 }
94 else if(_codec.plfreq == 22000)
95 {
96 return 32000;
97 }
98 else if(_codec.plfreq == 44000)
99 {
100 return 32000;
101 }
102 else if(_codec.plfreq == 48000)
103 {
104 return 32000;
105 }
106 else
107 {
108 return _codec.plfreq;
109 }
110}
111
112WebRtc_Word32 FilePlayerImpl::AudioCodec(CodecInst& audioCodec) const
113{
114 audioCodec = _codec;
115 return 0;
116}
117
118WebRtc_Word32 FilePlayerImpl::Get10msAudioFromFile(
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +0000119 int16_t* outBuffer,
120 int& lengthInSamples,
121 int frequencyInHz)
niklase@google.com470e71d2011-07-07 08:21:25 +0000122{
123 if(_codec.plfreq == 0)
124 {
125 WEBRTC_TRACE(kTraceWarning, kTraceVoice, _instanceID,
126 "FilePlayerImpl::Get10msAudioFromFile() playing not started!\
127 codecFreq = %d, wantedFreq = %d",
128 _codec.plfreq, frequencyInHz);
129 return -1;
130 }
131
132 AudioFrame unresampledAudioFrame;
133 if(STR_CASE_CMP(_codec.plname, "L16") == 0)
134 {
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000135 unresampledAudioFrame.sample_rate_hz_ = _codec.plfreq;
niklase@google.com470e71d2011-07-07 08:21:25 +0000136
137 // L16 is un-encoded data. Just pull 10 ms.
138 WebRtc_UWord32 lengthInBytes =
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000139 sizeof(unresampledAudioFrame.data_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000140 if (_fileModule.PlayoutAudioData(
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000141 (WebRtc_Word8*)unresampledAudioFrame.data_,
niklase@google.com470e71d2011-07-07 08:21:25 +0000142 lengthInBytes) == -1)
143 {
144 // End of file reached.
145 return -1;
146 }
147 if(lengthInBytes == 0)
148 {
149 lengthInSamples = 0;
150 return 0;
151 }
152 // One sample is two bytes.
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000153 unresampledAudioFrame.samples_per_channel_ =
niklase@google.com470e71d2011-07-07 08:21:25 +0000154 (WebRtc_UWord16)lengthInBytes >> 1;
155
156 }else {
157 // Decode will generate 10 ms of audio data. PlayoutAudioData(..)
158 // expects a full frame. If the frame size is larger than 10 ms,
159 // PlayoutAudioData(..) data should be called proportionally less often.
160 WebRtc_Word16 encodedBuffer[MAX_AUDIO_BUFFER_IN_SAMPLES];
161 WebRtc_UWord32 encodedLengthInBytes = 0;
162 if(++_numberOf10MsInDecoder >= _numberOf10MsPerFrame)
163 {
164 _numberOf10MsInDecoder = 0;
165 WebRtc_UWord32 bytesFromFile = sizeof(encodedBuffer);
166 if (_fileModule.PlayoutAudioData((WebRtc_Word8*)encodedBuffer,
167 bytesFromFile) == -1)
168 {
169 // End of file reached.
170 return -1;
171 }
172 encodedLengthInBytes = bytesFromFile;
173 }
174 if(_audioDecoder.Decode(unresampledAudioFrame,frequencyInHz,
175 (WebRtc_Word8*)encodedBuffer,
176 encodedLengthInBytes) == -1)
177 {
178 return -1;
179 }
180 }
181
182 int outLen = 0;
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000183 if(_resampler.ResetIfNeeded(unresampledAudioFrame.sample_rate_hz_,
niklase@google.com470e71d2011-07-07 08:21:25 +0000184 frequencyInHz, kResamplerSynchronous))
185 {
186 WEBRTC_TRACE(kTraceWarning, kTraceVoice, _instanceID,
187 "FilePlayerImpl::Get10msAudioFromFile() unexpected codec");
188
189 // New sampling frequency. Update state.
190 outLen = frequencyInHz / 100;
191 memset(outBuffer, 0, outLen * sizeof(WebRtc_Word16));
192 return 0;
193 }
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000194 _resampler.Push(unresampledAudioFrame.data_,
195 unresampledAudioFrame.samples_per_channel_,
niklase@google.com470e71d2011-07-07 08:21:25 +0000196 outBuffer,
197 MAX_AUDIO_BUFFER_IN_SAMPLES,
198 outLen);
199
200 lengthInSamples = outLen;
201
202 if(_scaling != 1.0)
203 {
204 for (int i = 0;i < outLen; i++)
205 {
206 outBuffer[i] = (WebRtc_Word16)(outBuffer[i] * _scaling);
207 }
208 }
209 _decodedLengthInMS += 10;
210 return 0;
211}
212
213WebRtc_Word32 FilePlayerImpl::RegisterModuleFileCallback(FileCallback* callback)
214{
215 return _fileModule.SetModuleFileCallback(callback);
216}
217
218WebRtc_Word32 FilePlayerImpl::SetAudioScaling(float scaleFactor)
219{
220 if((scaleFactor >= 0)&&(scaleFactor <= 2.0))
221 {
222 _scaling = scaleFactor;
223 return 0;
224 }
225 WEBRTC_TRACE(kTraceWarning, kTraceVoice, _instanceID,
226 "FilePlayerImpl::SetAudioScaling() not allowed scale factor");
227 return -1;
228}
229
leozwang@webrtc.org2559cbf2012-02-27 19:18:25 +0000230WebRtc_Word32 FilePlayerImpl::StartPlayingFile(const char* fileName,
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 bool loop,
232 WebRtc_UWord32 startPosition,
233 float volumeScaling,
234 WebRtc_UWord32 notification,
235 WebRtc_UWord32 stopPosition,
236 const CodecInst* codecInst)
237{
238 if (_fileFormat == kFileFormatPcm16kHzFile ||
239 _fileFormat == kFileFormatPcm8kHzFile||
240 _fileFormat == kFileFormatPcm32kHzFile )
241 {
242 CodecInst codecInstL16;
243 strncpy(codecInstL16.plname,"L16",32);
244 codecInstL16.pltype = 93;
245 codecInstL16.channels = 1;
246
247 if (_fileFormat == kFileFormatPcm8kHzFile)
248 {
249 codecInstL16.rate = 128000;
250 codecInstL16.plfreq = 8000;
251 codecInstL16.pacsize = 80;
252
253 } else if(_fileFormat == kFileFormatPcm16kHzFile)
254 {
255 codecInstL16.rate = 256000;
256 codecInstL16.plfreq = 16000;
257 codecInstL16.pacsize = 160;
258
259 }else if(_fileFormat == kFileFormatPcm32kHzFile)
260 {
261 codecInstL16.rate = 512000;
262 codecInstL16.plfreq = 32000;
263 codecInstL16.pacsize = 160;
264 } else
265 {
266 WEBRTC_TRACE(kTraceError, kTraceVoice, _instanceID,
267 "FilePlayerImpl::StartPlayingFile() sample frequency\
268 specifed not supported for PCM format.");
269 return -1;
270 }
271
272 if (_fileModule.StartPlayingAudioFile(fileName, notification, loop,
273 _fileFormat, &codecInstL16,
274 startPosition,
275 stopPosition) == -1)
276 {
277 WEBRTC_TRACE(
278 kTraceWarning,
279 kTraceVoice,
280 _instanceID,
281 "FilePlayerImpl::StartPlayingFile() failed to initialize file\
282 %s playout.", fileName);
283 return -1;
284 }
285 SetAudioScaling(volumeScaling);
286 }else if(_fileFormat == kFileFormatPreencodedFile)
287 {
288 if (_fileModule.StartPlayingAudioFile(fileName, notification, loop,
289 _fileFormat, codecInst) == -1)
290 {
291 WEBRTC_TRACE(
292 kTraceWarning,
293 kTraceVoice,
294 _instanceID,
295 "FilePlayerImpl::StartPlayingPreEncodedFile() failed to\
296 initialize pre-encoded file %s playout.",
297 fileName);
298 return -1;
299 }
300 } else
301 {
302 CodecInst* no_inst = NULL;
303 if (_fileModule.StartPlayingAudioFile(fileName, notification, loop,
304 _fileFormat, no_inst,
305 startPosition,
306 stopPosition) == -1)
307 {
308 WEBRTC_TRACE(
309 kTraceWarning,
310 kTraceVoice,
311 _instanceID,
312 "FilePlayerImpl::StartPlayingFile() failed to initialize file\
313 %s playout.", fileName);
314 return -1;
315 }
316 SetAudioScaling(volumeScaling);
317 }
318 if (SetUpAudioDecoder() == -1)
319 {
320 StopPlayingFile();
321 return -1;
322 }
323 return 0;
324}
325
326WebRtc_Word32 FilePlayerImpl::StartPlayingFile(InStream& sourceStream,
327 WebRtc_UWord32 startPosition,
328 float volumeScaling,
329 WebRtc_UWord32 notification,
330 WebRtc_UWord32 stopPosition,
331 const CodecInst* codecInst)
332{
333 if (_fileFormat == kFileFormatPcm16kHzFile ||
334 _fileFormat == kFileFormatPcm32kHzFile ||
335 _fileFormat == kFileFormatPcm8kHzFile)
336 {
337 CodecInst codecInstL16;
338 strncpy(codecInstL16.plname,"L16",32);
339 codecInstL16.pltype = 93;
340 codecInstL16.channels = 1;
341
342 if (_fileFormat == kFileFormatPcm8kHzFile)
343 {
344 codecInstL16.rate = 128000;
345 codecInstL16.plfreq = 8000;
346 codecInstL16.pacsize = 80;
347
348 }else if (_fileFormat == kFileFormatPcm16kHzFile)
349 {
350 codecInstL16.rate = 256000;
351 codecInstL16.plfreq = 16000;
352 codecInstL16.pacsize = 160;
353
354 }else if (_fileFormat == kFileFormatPcm32kHzFile)
355 {
356 codecInstL16.rate = 512000;
357 codecInstL16.plfreq = 32000;
358 codecInstL16.pacsize = 160;
359 }else
360 {
361 WEBRTC_TRACE(
362 kTraceError,
363 kTraceVoice,
364 _instanceID,
365 "FilePlayerImpl::StartPlayingFile() sample frequency specifed\
366 not supported for PCM format.");
367 return -1;
368 }
369 if (_fileModule.StartPlayingAudioStream(sourceStream, notification,
370 _fileFormat, &codecInstL16,
371 startPosition,
372 stopPosition) == -1)
373 {
374 WEBRTC_TRACE(
375 kTraceError,
376 kTraceVoice,
377 _instanceID,
378 "FilePlayerImpl::StartPlayingFile() failed to initialize stream\
379 playout.");
380 return -1;
381 }
382
383 }else if(_fileFormat == kFileFormatPreencodedFile)
384 {
385 if (_fileModule.StartPlayingAudioStream(sourceStream, notification,
386 _fileFormat, codecInst) == -1)
387 {
388 WEBRTC_TRACE(
389 kTraceWarning,
390 kTraceVoice,
391 _instanceID,
392 "FilePlayerImpl::StartPlayingFile() failed to initialize stream\
393 playout.");
394 return -1;
395 }
396 } else {
397 CodecInst* no_inst = NULL;
398 if (_fileModule.StartPlayingAudioStream(sourceStream, notification,
399 _fileFormat, no_inst,
400 startPosition,
401 stopPosition) == -1)
402 {
403 WEBRTC_TRACE(kTraceError, kTraceVoice, _instanceID,
404 "FilePlayerImpl::StartPlayingFile() failed to initialize\
405 stream playout.");
406 return -1;
407 }
408 }
409 SetAudioScaling(volumeScaling);
410
411 if (SetUpAudioDecoder() == -1)
412 {
413 StopPlayingFile();
414 return -1;
415 }
416 return 0;
417}
418
419WebRtc_Word32 FilePlayerImpl::StopPlayingFile()
420{
421 memset(&_codec, 0, sizeof(CodecInst));
422 _numberOf10MsPerFrame = 0;
423 _numberOf10MsInDecoder = 0;
424 return _fileModule.StopPlaying();
425}
426
427bool FilePlayerImpl::IsPlayingFile() const
428{
429 return _fileModule.IsPlaying();
430}
431
432WebRtc_Word32 FilePlayerImpl::GetPlayoutPosition(WebRtc_UWord32& durationMs)
433{
434 return _fileModule.PlayoutPositionMs(durationMs);
435}
436
437WebRtc_Word32 FilePlayerImpl::SetUpAudioDecoder()
438{
439 if ((_fileModule.codec_info(_codec) == -1))
440 {
441 WEBRTC_TRACE(
442 kTraceWarning,
443 kTraceVoice,
444 _instanceID,
445 "FilePlayerImpl::StartPlayingFile() failed to retrieve Codec info\
446 of file data.");
447 return -1;
448 }
449 if( STR_CASE_CMP(_codec.plname, "L16") != 0 &&
450 _audioDecoder.SetDecodeCodec(_codec,AMRFileStorage) == -1)
451 {
452 WEBRTC_TRACE(
453 kTraceWarning,
454 kTraceVoice,
455 _instanceID,
456 "FilePlayerImpl::StartPlayingFile() codec %s not supported",
457 _codec.plname);
458 return -1;
459 }
460 _numberOf10MsPerFrame = _codec.pacsize / (_codec.plfreq / 100);
461 _numberOf10MsInDecoder = 0;
462 return 0;
463}
464
465#ifdef WEBRTC_MODULE_UTILITY_VIDEO
466VideoFilePlayerImpl::VideoFilePlayerImpl(WebRtc_UWord32 instanceID,
467 FileFormats fileFormat)
468 : FilePlayerImpl(instanceID,fileFormat),
469 _videoDecoder(*new VideoCoder(instanceID)),
henrike@webrtc.org6b9253e2012-02-15 18:48:16 +0000470 video_codec_info_(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000471 _decodedVideoFrames(0),
472 _encodedData(*new EncodedVideoData()),
473 _frameScaler(*new FrameScaler()),
henrike@webrtc.org105e0712011-12-16 19:53:46 +0000474 _critSec(CriticalSectionWrapper::CreateCriticalSection()),
henrike@webrtc.org6b9253e2012-02-15 18:48:16 +0000475 _startTime(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000476 _accumulatedRenderTimeMs(0),
henrike@webrtc.org6b9253e2012-02-15 18:48:16 +0000477 _frameLengthMS(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000478 _numberOfFramesRead(0),
479 _videoOnly(false)
480{
481 memset(&video_codec_info_, 0, sizeof(video_codec_info_));
482}
483
484VideoFilePlayerImpl::~VideoFilePlayerImpl()
485{
henrike@webrtc.org105e0712011-12-16 19:53:46 +0000486 delete _critSec;
niklase@google.com470e71d2011-07-07 08:21:25 +0000487 delete &_frameScaler;
488 delete &_videoDecoder;
489 delete &_encodedData;
490}
491
492WebRtc_Word32 VideoFilePlayerImpl::StartPlayingVideoFile(
leozwang@webrtc.org2559cbf2012-02-27 19:18:25 +0000493 const char* fileName,
niklase@google.com470e71d2011-07-07 08:21:25 +0000494 bool loop,
495 bool videoOnly)
496{
497 CriticalSectionScoped lock( _critSec);
498
499 if(_fileModule.StartPlayingVideoFile(fileName, loop, videoOnly,
500 _fileFormat) != 0)
501 {
502 return -1;
503 }
504
505 _decodedVideoFrames = 0;
506 _accumulatedRenderTimeMs = 0;
507 _frameLengthMS = 0;
508 _numberOfFramesRead = 0;
509 _videoOnly = videoOnly;
510
511 // Set up video_codec_info_ according to file,
512 if(SetUpVideoDecoder() != 0)
513 {
514 StopPlayingFile();
515 return -1;
516 }
517 if(!videoOnly)
518 {
519 // Set up _codec according to file,
520 if(SetUpAudioDecoder() != 0)
521 {
522 StopPlayingFile();
523 return -1;
524 }
525 }
526 return 0;
527}
528
529WebRtc_Word32 VideoFilePlayerImpl::StopPlayingFile()
530{
531 CriticalSectionScoped lock( _critSec);
532
533 _decodedVideoFrames = 0;
pwestin@webrtc.org52fd98d2012-02-13 09:03:53 +0000534 _videoDecoder.ResetDecoder();
niklase@google.com470e71d2011-07-07 08:21:25 +0000535
536 return FilePlayerImpl::StopPlayingFile();
537}
538
539WebRtc_Word32 VideoFilePlayerImpl::GetVideoFromFile(VideoFrame& videoFrame,
540 WebRtc_UWord32 outWidth,
541 WebRtc_UWord32 outHeight)
542{
543 CriticalSectionScoped lock( _critSec);
544
545 WebRtc_Word32 retVal = GetVideoFromFile(videoFrame);
546 if(retVal != 0)
547 {
548 return retVal;
549 }
550 if( videoFrame.Length() > 0)
551 {
mflodman@webrtc.org1f992802012-01-27 13:42:53 +0000552 retVal = _frameScaler.ResizeFrameIfNeeded(&videoFrame, outWidth,
niklase@google.com470e71d2011-07-07 08:21:25 +0000553 outHeight);
554 }
555 return retVal;
556}
557
558WebRtc_Word32 VideoFilePlayerImpl::GetVideoFromFile(VideoFrame& videoFrame)
559{
560 CriticalSectionScoped lock( _critSec);
561 // No new video data read from file.
562 if(_encodedData.payloadSize == 0)
563 {
564 videoFrame.SetLength(0);
565 return -1;
566 }
567 WebRtc_Word32 retVal = 0;
568 if(strncmp(video_codec_info_.plName, "I420", 5) == 0)
569 {
570 videoFrame.CopyFrame(_encodedData.payloadSize,_encodedData.payloadData);
571 videoFrame.SetLength(_encodedData.payloadSize);
572 videoFrame.SetWidth(video_codec_info_.width);
573 videoFrame.SetHeight(video_codec_info_.height);
574 }else
575 {
576 // Set the timestamp manually since there is no timestamp in the file.
577 // Update timestam according to 90 kHz stream.
578 _encodedData.timeStamp += (90000 / video_codec_info_.maxFramerate);
579 retVal = _videoDecoder.Decode(videoFrame, _encodedData);
580 }
581
582 WebRtc_Word64 renderTimeMs = TickTime::MillisecondTimestamp();
583 videoFrame.SetRenderTime(renderTimeMs);
584
585 // Indicate that the current frame in the encoded buffer is old/has
586 // already been read.
587 _encodedData.payloadSize = 0;
588 if( retVal == 0)
589 {
590 _decodedVideoFrames++;
591 }
592 return retVal;
593}
594
595WebRtc_Word32 VideoFilePlayerImpl::video_codec_info(
596 VideoCodec& videoCodec) const
597{
598 if(video_codec_info_.plName[0] == 0)
599 {
600 return -1;
601 }
602 memcpy(&videoCodec, &video_codec_info_, sizeof(VideoCodec));
603 return 0;
604}
605
606WebRtc_Word32 VideoFilePlayerImpl::TimeUntilNextVideoFrame()
607{
608 if(_fileFormat != kFileFormatAviFile)
609 {
610 return -1;
611 }
612 if(!_fileModule.IsPlaying())
613 {
614 return -1;
615 }
616 if(_encodedData.payloadSize <= 0)
617 {
618 // Read next frame from file.
619 CriticalSectionScoped lock( _critSec);
620
621 if(_fileFormat == kFileFormatAviFile)
622 {
623 // Get next video frame
624 WebRtc_UWord32 encodedBufferLengthInBytes = _encodedData.bufferSize;
625 if(_fileModule.PlayoutAVIVideoData(
626 reinterpret_cast< WebRtc_Word8*>(_encodedData.payloadData),
627 encodedBufferLengthInBytes) != 0)
628 {
629 WEBRTC_TRACE(
630 kTraceWarning,
631 kTraceVideo,
632 _instanceID,
633 "FilePlayerImpl::TimeUntilNextVideoFrame() error reading\
634 video data");
635 return -1;
636 }
637 _encodedData.payloadSize = encodedBufferLengthInBytes;
638 _encodedData.codec = video_codec_info_.codecType;
639 _numberOfFramesRead++;
640
641 if(_accumulatedRenderTimeMs == 0)
642 {
643 _startTime = TickTime::Now();
644 // This if-statement should only trigger once.
645 _accumulatedRenderTimeMs = 1;
646 } else {
647 // A full seconds worth of frames have been read.
648 if(_numberOfFramesRead % video_codec_info_.maxFramerate == 0)
649 {
650 // Frame rate is in frames per seconds. Frame length is
651 // calculated as an integer division which means it may
652 // be rounded down. Compensate for this every second.
653 WebRtc_UWord32 rest = 1000%_frameLengthMS;
654 _accumulatedRenderTimeMs += rest;
655 }
656 _accumulatedRenderTimeMs += _frameLengthMS;
657 }
658 }
659 }
660
661 WebRtc_Word64 timeToNextFrame;
662 if(_videoOnly)
663 {
664 timeToNextFrame = _accumulatedRenderTimeMs -
665 (TickTime::Now() - _startTime).Milliseconds();
666
667 } else {
668 // Synchronize with the audio stream instead of system clock.
669 timeToNextFrame = _accumulatedRenderTimeMs - _decodedLengthInMS;
670 }
671 if(timeToNextFrame < 0)
672 {
673 return 0;
674
675 } else if(timeToNextFrame > 0x0fffffff)
676 {
677 // Wraparound or audio stream has gone to far ahead of the video stream.
678 return -1;
679 }
680 return static_cast<WebRtc_Word32>(timeToNextFrame);
681}
682
683WebRtc_Word32 VideoFilePlayerImpl::SetUpVideoDecoder()
684{
685 if (_fileModule.VideoCodecInst(video_codec_info_) != 0)
686 {
687 WEBRTC_TRACE(
688 kTraceWarning,
689 kTraceVideo,
690 _instanceID,
691 "FilePlayerImpl::SetVideoDecoder() failed to retrieve Codec info of\
692 file data.");
693 return -1;
694 }
695
696 WebRtc_Word32 useNumberOfCores = 1;
697 if(_videoDecoder.SetDecodeCodec(video_codec_info_, useNumberOfCores) != 0)
698 {
699 WEBRTC_TRACE(
700 kTraceWarning,
701 kTraceVideo,
702 _instanceID,
703 "FilePlayerImpl::SetUpVideoDecoder() codec %s not supported",
704 video_codec_info_.plName);
705 return -1;
706 }
707
niklase@google.com470e71d2011-07-07 08:21:25 +0000708 _frameLengthMS = 1000/video_codec_info_.maxFramerate;
709
710 // Size of unencoded data (I420) should be the largest possible frame size
711 // in a file.
712 const WebRtc_UWord32 KReadBufferSize = 3 * video_codec_info_.width *
713 video_codec_info_.height / 2;
714 _encodedData.VerifyAndAllocate(KReadBufferSize);
715 _encodedData.encodedHeight = video_codec_info_.height;
716 _encodedData.encodedWidth = video_codec_info_.width;
717 _encodedData.payloadType = video_codec_info_.plType;
718 _encodedData.timeStamp = 0;
719 return 0;
720}
721#endif // WEBRTC_MODULE_UTILITY_VIDEO
722} // namespace webrtc