• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3  *
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 "webrtc/modules/utility/source/video_frames_queue.h"
12 
13 #ifdef WEBRTC_MODULE_UTILITY_VIDEO
14 
15 #include <assert.h>
16 
17 #include "webrtc/common_video/interface/texture_video_frame.h"
18 #include "webrtc/modules/interface/module_common_types.h"
19 #include "webrtc/system_wrappers/interface/logging.h"
20 #include "webrtc/system_wrappers/interface/tick_util.h"
21 
22 namespace webrtc {
VideoFramesQueue()23 VideoFramesQueue::VideoFramesQueue()
24     : _renderDelayMs(10)
25 {
26 }
27 
~VideoFramesQueue()28 VideoFramesQueue::~VideoFramesQueue() {
29   for (FrameList::iterator iter = _incomingFrames.begin();
30        iter != _incomingFrames.end(); ++iter) {
31       delete *iter;
32   }
33   for (FrameList::iterator iter = _emptyFrames.begin();
34        iter != _emptyFrames.end(); ++iter) {
35       delete *iter;
36   }
37 }
38 
AddFrame(const I420VideoFrame & newFrame)39 int32_t VideoFramesQueue::AddFrame(const I420VideoFrame& newFrame) {
40   if (newFrame.native_handle() != NULL) {
41     _incomingFrames.push_back(newFrame.CloneFrame());
42     return 0;
43   }
44 
45   I420VideoFrame* ptrFrameToAdd = NULL;
46   // Try to re-use a VideoFrame. Only allocate new memory if it is necessary.
47   if (!_emptyFrames.empty()) {
48     ptrFrameToAdd = _emptyFrames.front();
49     _emptyFrames.pop_front();
50   }
51   if (!ptrFrameToAdd) {
52     if (_emptyFrames.size() + _incomingFrames.size() >
53         KMaxNumberOfFrames) {
54       LOG(LS_WARNING) << "Too many frames, limit: " << KMaxNumberOfFrames;
55       return -1;
56     }
57     ptrFrameToAdd = new I420VideoFrame();
58   }
59   ptrFrameToAdd->CopyFrame(newFrame);
60   _incomingFrames.push_back(ptrFrameToAdd);
61   return 0;
62 }
63 
64 // Find the most recent frame that has a VideoFrame::RenderTimeMs() that is
65 // lower than current time in ms (TickTime::MillisecondTimestamp()).
66 // Note _incomingFrames is sorted so that the oldest frame is first.
67 // Recycle all frames that are older than the most recent frame.
FrameToRecord()68 I420VideoFrame* VideoFramesQueue::FrameToRecord() {
69   I420VideoFrame* ptrRenderFrame = NULL;
70   for (FrameList::iterator iter = _incomingFrames.begin();
71        iter != _incomingFrames.end(); ++iter) {
72     I420VideoFrame* ptrOldestFrameInList = *iter;
73     if (ptrOldestFrameInList->render_time_ms() <=
74         TickTime::MillisecondTimestamp() + _renderDelayMs) {
75       // List is traversed beginning to end. If ptrRenderFrame is not
76       // NULL it must be the first, and thus oldest, VideoFrame in the
77       // queue. It can be recycled.
78       if (ptrRenderFrame) {
79         ReturnFrame(ptrRenderFrame);
80        _incomingFrames.pop_front();
81       }
82       ptrRenderFrame = ptrOldestFrameInList;
83     } else {
84       // All VideoFrames following this one will be even newer. No match
85       // will be found.
86       break;
87     }
88   }
89   return ptrRenderFrame;
90 }
91 
ReturnFrame(I420VideoFrame * ptrOldFrame)92 int32_t VideoFramesQueue::ReturnFrame(I420VideoFrame* ptrOldFrame) {
93   // No need to reuse texture frames because they do not allocate memory.
94   if (ptrOldFrame->native_handle() == NULL) {
95     ptrOldFrame->set_timestamp(0);
96     ptrOldFrame->set_width(0);
97     ptrOldFrame->set_height(0);
98     ptrOldFrame->set_render_time_ms(0);
99     ptrOldFrame->ResetSize();
100     _emptyFrames.push_back(ptrOldFrame);
101   } else {
102     delete ptrOldFrame;
103   }
104   return 0;
105 }
106 
SetRenderDelay(uint32_t renderDelay)107 int32_t VideoFramesQueue::SetRenderDelay(uint32_t renderDelay) {
108   _renderDelayMs = renderDelay;
109   return 0;
110 }
111 }  // namespace webrtc
112 #endif // WEBRTC_MODULE_UTILITY_VIDEO
113