1/*
2 * buffer_pool.cpp - buffer pool
3 *
4 *  Copyright (c) 2014-2015 Intel Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Wind Yuan <feng.yuan@intel.com>
19 */
20
21#include "buffer_pool.h"
22
23namespace XCam {
24
25BufferProxy::BufferProxy (const VideoBufferInfo &info, const SmartPtr<BufferData> &data)
26    : VideoBuffer (info)
27    , _data (data)
28{
29    XCAM_ASSERT (data.ptr ());
30}
31
32BufferProxy::BufferProxy (const SmartPtr<BufferData> &data)
33    : _data (data)
34{
35    XCAM_ASSERT (data.ptr ());
36}
37
38BufferProxy::~BufferProxy ()
39{
40    if (_pool.ptr ()) {
41        _pool->release (_data);
42    }
43    _data.release ();
44}
45
46uint8_t *
47BufferProxy::map ()
48{
49    XCAM_ASSERT (_data.ptr ());
50    return _data->map ();
51}
52
53bool
54BufferProxy::unmap ()
55{
56    XCAM_ASSERT (_data.ptr ());
57    return _data->unmap ();
58}
59
60int
61BufferProxy::get_fd ()
62{
63    XCAM_ASSERT (_data.ptr ());
64    return _data->get_fd ();
65}
66
67BufferPool::BufferPool ()
68    : _allocated_num (0)
69    , _max_count (0)
70    , _started (false)
71{
72}
73
74BufferPool::~BufferPool ()
75{
76}
77
78bool
79BufferPool::set_video_info (const VideoBufferInfo &info)
80{
81    VideoBufferInfo new_info = info;
82    SmartLock lock (_mutex);
83
84    XCAM_FAIL_RETURN (
85        ERROR,
86        fixate_video_info (new_info),
87        false,
88        "BufferPool fixate video info failed");
89    update_video_info_unsafe (new_info);
90    return true;
91}
92
93void
94BufferPool::update_video_info_unsafe (const VideoBufferInfo &info)
95{
96    _buffer_info = info;
97}
98
99bool
100BufferPool::reserve (uint32_t max_count)
101{
102    uint32_t i = 0;
103
104    XCAM_ASSERT (max_count);
105
106    SmartLock lock (_mutex);
107
108    for (i = _allocated_num; i < max_count; ++i) {
109        SmartPtr<BufferData> new_data = allocate_data (_buffer_info);
110        if (!new_data.ptr ())
111            break;
112        _buf_list.push (new_data);
113    }
114
115    XCAM_FAIL_RETURN (
116        ERROR,
117        i > 0,
118        false,
119        "BufferPool reserve failed with none buffer data allocated");
120
121    if (i != max_count) {
122        XCAM_LOG_WARNING ("BufferPool expect to reserve %d data but only reserved %d", max_count, i);
123    }
124    _max_count = i;
125    _allocated_num = _max_count;
126    _started = true;
127
128    return true;
129}
130
131bool
132BufferPool::add_data_unsafe (const SmartPtr<BufferData> &data)
133{
134    if (!data.ptr ())
135        return false;
136
137    _buf_list.push (data);
138    ++_allocated_num;
139
140    XCAM_ASSERT (_allocated_num <= _max_count || !_max_count);
141    return true;
142}
143
144SmartPtr<VideoBuffer>
145BufferPool::get_buffer (const SmartPtr<BufferPool> &self)
146{
147    SmartPtr<BufferProxy> ret_buf;
148    SmartPtr<BufferData> data;
149
150    {
151        SmartLock lock (_mutex);
152        if (!_started)
153            return NULL;
154    }
155
156    XCAM_ASSERT (self.ptr () == this);
157    XCAM_FAIL_RETURN(
158        WARNING,
159        self.ptr () == this,
160        NULL,
161        "BufferPool get_buffer failed since parameter<self> not this");
162
163    data = _buf_list.pop ();
164    if (!data.ptr ()) {
165        XCAM_LOG_DEBUG ("BufferPool failed to get buffer");
166        return NULL;
167    }
168    ret_buf = create_buffer_from_data (data);
169    ret_buf->set_buf_pool (self);
170
171    return ret_buf;
172}
173
174SmartPtr<VideoBuffer>
175BufferPool::get_buffer ()
176{
177    return get_buffer (SmartPtr<BufferPool>(this));
178}
179
180void
181BufferPool::stop ()
182{
183    {
184        SmartLock lock (_mutex);
185        _started = false;
186    }
187    _buf_list.pause_pop ();
188}
189
190void
191BufferPool::release (SmartPtr<BufferData> &data)
192{
193    {
194        SmartLock lock (_mutex);
195        if (!_started)
196            return;
197    }
198    _buf_list.push (data);
199}
200
201bool
202BufferPool::fixate_video_info (VideoBufferInfo &info)
203{
204    XCAM_UNUSED (info);
205    return true;
206}
207
208SmartPtr<BufferProxy>
209BufferPool::create_buffer_from_data (SmartPtr<BufferData> &data)
210{
211    const VideoBufferInfo &info = get_video_info ();
212
213    XCAM_ASSERT (data.ptr ());
214    return new BufferProxy (info, data);
215}
216
217};
218