/* 
 | 
 * buffer_pool.cpp - buffer pool 
 | 
 * 
 | 
 *  Copyright (c) 2014-2015 Intel Corporation 
 | 
 * 
 | 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 | 
 * you may not use this file except in compliance with the License. 
 | 
 * You may obtain a copy of the License at 
 | 
 * 
 | 
 *      http://www.apache.org/licenses/LICENSE-2.0 
 | 
 * 
 | 
 * Unless required by applicable law or agreed to in writing, software 
 | 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 | 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 | 
 * See the License for the specific language governing permissions and 
 | 
 * limitations under the License. 
 | 
 * 
 | 
 * Author: Wind Yuan <feng.yuan@intel.com> 
 | 
 */ 
 | 
  
 | 
#include "buffer_pool.h" 
 | 
  
 | 
namespace XCam { 
 | 
  
 | 
BufferProxy::BufferProxy (const VideoBufferInfo &info, const SmartPtr<BufferData> &data) 
 | 
    : VideoBuffer (info) 
 | 
    , _data (data) 
 | 
{ 
 | 
    XCAM_ASSERT (data.ptr ()); 
 | 
} 
 | 
  
 | 
BufferProxy::BufferProxy (const SmartPtr<BufferData> &data) 
 | 
    : _data (data) 
 | 
{ 
 | 
    XCAM_ASSERT (data.ptr ()); 
 | 
} 
 | 
  
 | 
BufferProxy::~BufferProxy () 
 | 
{ 
 | 
    if (_pool.ptr ()) { 
 | 
        _pool->release (_data); 
 | 
    } 
 | 
    _data.release (); 
 | 
} 
 | 
  
 | 
uint8_t * 
 | 
BufferProxy::map () 
 | 
{ 
 | 
    XCAM_ASSERT (_data.ptr ()); 
 | 
    return _data->map (); 
 | 
} 
 | 
  
 | 
bool 
 | 
BufferProxy::unmap () 
 | 
{ 
 | 
    XCAM_ASSERT (_data.ptr ()); 
 | 
    return _data->unmap (); 
 | 
} 
 | 
  
 | 
int 
 | 
BufferProxy::get_fd () 
 | 
{ 
 | 
    XCAM_ASSERT (_data.ptr ()); 
 | 
    return _data->get_fd (); 
 | 
} 
 | 
  
 | 
BufferPool::BufferPool () 
 | 
    : _allocated_num (0) 
 | 
    , _max_count (0) 
 | 
    , _started (false) 
 | 
{ 
 | 
} 
 | 
  
 | 
BufferPool::~BufferPool () 
 | 
{ 
 | 
} 
 | 
  
 | 
bool 
 | 
BufferPool::set_video_info (const VideoBufferInfo &info) 
 | 
{ 
 | 
    VideoBufferInfo new_info = info; 
 | 
    SmartLock lock (_mutex); 
 | 
  
 | 
    XCAM_FAIL_RETURN ( 
 | 
        ERROR, 
 | 
        fixate_video_info (new_info), 
 | 
        false, 
 | 
        "BufferPool fixate video info failed"); 
 | 
    update_video_info_unsafe (new_info); 
 | 
    return true; 
 | 
} 
 | 
  
 | 
void 
 | 
BufferPool::update_video_info_unsafe (const VideoBufferInfo &info) 
 | 
{ 
 | 
    _buffer_info = info; 
 | 
} 
 | 
  
 | 
bool 
 | 
BufferPool::reserve (uint32_t max_count) 
 | 
{ 
 | 
    uint32_t i = 0; 
 | 
  
 | 
    XCAM_ASSERT (max_count); 
 | 
  
 | 
    SmartLock lock (_mutex); 
 | 
  
 | 
    for (i = _allocated_num; i < max_count; ++i) { 
 | 
        SmartPtr<BufferData> new_data = allocate_data (_buffer_info); 
 | 
        if (!new_data.ptr ()) 
 | 
            break; 
 | 
        _buf_list.push (new_data); 
 | 
    } 
 | 
  
 | 
    XCAM_FAIL_RETURN ( 
 | 
        ERROR, 
 | 
        i > 0, 
 | 
        false, 
 | 
        "BufferPool reserve failed with none buffer data allocated"); 
 | 
  
 | 
    if (i != max_count) { 
 | 
        XCAM_LOG_WARNING ("BufferPool expect to reserve %d data but only reserved %d", max_count, i); 
 | 
    } 
 | 
    _max_count = i; 
 | 
    _allocated_num = _max_count; 
 | 
    _started = true; 
 | 
  
 | 
    return true; 
 | 
} 
 | 
  
 | 
bool 
 | 
BufferPool::add_data_unsafe (const SmartPtr<BufferData> &data) 
 | 
{ 
 | 
    if (!data.ptr ()) 
 | 
        return false; 
 | 
  
 | 
    _buf_list.push (data); 
 | 
    ++_allocated_num; 
 | 
  
 | 
    XCAM_ASSERT (_allocated_num <= _max_count || !_max_count); 
 | 
    return true; 
 | 
} 
 | 
  
 | 
SmartPtr<VideoBuffer> 
 | 
BufferPool::get_buffer (const SmartPtr<BufferPool> &self) 
 | 
{ 
 | 
    SmartPtr<BufferProxy> ret_buf; 
 | 
    SmartPtr<BufferData> data; 
 | 
  
 | 
    { 
 | 
        SmartLock lock (_mutex); 
 | 
        if (!_started) 
 | 
            return NULL; 
 | 
    } 
 | 
  
 | 
    XCAM_ASSERT (self.ptr () == this); 
 | 
    XCAM_FAIL_RETURN( 
 | 
        WARNING, 
 | 
        self.ptr () == this, 
 | 
        NULL, 
 | 
        "BufferPool get_buffer failed since parameter<self> not this"); 
 | 
  
 | 
    data = _buf_list.pop (); 
 | 
    if (!data.ptr ()) { 
 | 
        XCAM_LOG_DEBUG ("BufferPool failed to get buffer"); 
 | 
        return NULL; 
 | 
    } 
 | 
    ret_buf = create_buffer_from_data (data); 
 | 
    ret_buf->set_buf_pool (self); 
 | 
  
 | 
    return ret_buf; 
 | 
} 
 | 
  
 | 
SmartPtr<VideoBuffer> 
 | 
BufferPool::get_buffer () 
 | 
{ 
 | 
    return get_buffer (SmartPtr<BufferPool>(this)); 
 | 
} 
 | 
  
 | 
void 
 | 
BufferPool::stop () 
 | 
{ 
 | 
    { 
 | 
        SmartLock lock (_mutex); 
 | 
        _started = false; 
 | 
    } 
 | 
    _buf_list.pause_pop (); 
 | 
} 
 | 
  
 | 
void 
 | 
BufferPool::release (SmartPtr<BufferData> &data) 
 | 
{ 
 | 
    { 
 | 
        SmartLock lock (_mutex); 
 | 
        if (!_started) 
 | 
            return; 
 | 
    } 
 | 
    _buf_list.push (data); 
 | 
} 
 | 
  
 | 
bool 
 | 
BufferPool::fixate_video_info (VideoBufferInfo &info) 
 | 
{ 
 | 
    XCAM_UNUSED (info); 
 | 
    return true; 
 | 
} 
 | 
  
 | 
SmartPtr<BufferProxy> 
 | 
BufferPool::create_buffer_from_data (SmartPtr<BufferData> &data) 
 | 
{ 
 | 
    const VideoBufferInfo &info = get_video_info (); 
 | 
  
 | 
    XCAM_ASSERT (data.ptr ()); 
 | 
    return new BufferProxy (info, data); 
 | 
} 
 | 
  
 | 
}; 
 |