|
Packit |
1244b8 |
/*
|
|
Packit |
1244b8 |
* Copyright (C) 2014 Intel Corporation. All rights reserved.
|
|
Packit |
1244b8 |
*
|
|
Packit |
1244b8 |
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
Packit |
1244b8 |
* you may not use this file except in compliance with the License.
|
|
Packit |
1244b8 |
* You may obtain a copy of the License at
|
|
Packit |
1244b8 |
*
|
|
Packit |
1244b8 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit |
1244b8 |
*
|
|
Packit |
1244b8 |
* Unless required by applicable law or agreed to in writing, software
|
|
Packit |
1244b8 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
Packit |
1244b8 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
Packit |
1244b8 |
* See the License for the specific language governing permissions and
|
|
Packit |
1244b8 |
* limitations under the License.
|
|
Packit |
1244b8 |
*/
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
1244b8 |
#include "config.h"
|
|
Packit |
1244b8 |
#endif
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
#include "vaapidecsurfacepool.h"
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
#include "common/log.h"
|
|
Packit |
1244b8 |
#include "vaapi/VaapiSurface.h"
|
|
Packit |
1244b8 |
#include "decoder/vaapidecoder_base.h"
|
|
Packit |
1244b8 |
#include <string.h>
|
|
Packit |
1244b8 |
#include <assert.h>
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
namespace YamiMediaCodec{
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
YamiStatus VaapiDecSurfacePool::getSurface(SurfaceAllocParams* param, intptr_t* surface)
|
|
Packit |
1244b8 |
{
|
|
Packit |
1244b8 |
VaapiDecSurfacePool* p = (VaapiDecSurfacePool*)param->user;
|
|
Packit |
1244b8 |
return p->getSurface(surface);
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
YamiStatus VaapiDecSurfacePool::putSurface(SurfaceAllocParams* param, intptr_t surface)
|
|
Packit |
1244b8 |
{
|
|
Packit |
1244b8 |
VaapiDecSurfacePool* p = (VaapiDecSurfacePool*)param->user;
|
|
Packit |
1244b8 |
return p->putSurface(surface);
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
YamiStatus VaapiDecSurfacePool::getSurface(intptr_t* surface)
|
|
Packit |
1244b8 |
{
|
|
Packit |
1244b8 |
AutoLock lock(m_lock);
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
if (m_freed.empty())
|
|
Packit |
1244b8 |
return YAMI_DECODE_NO_SURFACE;
|
|
Packit |
1244b8 |
*surface = m_freed.front();
|
|
Packit |
1244b8 |
m_used.insert(*surface);
|
|
Packit |
1244b8 |
m_freed.pop_front();
|
|
Packit |
1244b8 |
return YAMI_SUCCESS;
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
YamiStatus VaapiDecSurfacePool::putSurface(intptr_t surface)
|
|
Packit |
1244b8 |
{
|
|
Packit |
1244b8 |
AutoLock lock(m_lock);
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
if (m_used.find(surface) == m_used.end()) {
|
|
Packit |
1244b8 |
ERROR("put wrong surface, id = %p", (void*)surface);
|
|
Packit |
1244b8 |
return YAMI_INVALID_PARAM;
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
m_used.erase(surface);
|
|
Packit |
1244b8 |
m_freed.push_back(surface);
|
|
Packit |
1244b8 |
return YAMI_SUCCESS;
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
DecSurfacePoolPtr VaapiDecSurfacePool::create(VideoConfigBuffer* config,
|
|
Packit |
1244b8 |
const SharedPtr<SurfaceAllocator>& allocator)
|
|
Packit |
1244b8 |
{
|
|
Packit |
1244b8 |
VideoDecoderConfig conf;
|
|
Packit |
1244b8 |
conf.width = config->surfaceWidth;
|
|
Packit |
1244b8 |
conf.height = config->surfaceHeight;
|
|
Packit |
1244b8 |
conf.fourcc = config->fourcc;
|
|
Packit |
1244b8 |
conf.surfaceNumber = config->surfaceNumber;
|
|
Packit |
1244b8 |
return create(&conf, allocator);
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
DecSurfacePoolPtr VaapiDecSurfacePool::create(VideoDecoderConfig* config,
|
|
Packit |
1244b8 |
const SharedPtr<SurfaceAllocator>& allocator)
|
|
Packit |
1244b8 |
{
|
|
Packit |
1244b8 |
DecSurfacePoolPtr pool(new VaapiDecSurfacePool);
|
|
Packit |
1244b8 |
if (!pool->init(config, allocator))
|
|
Packit |
1244b8 |
pool.reset();
|
|
Packit |
1244b8 |
return pool;
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
bool VaapiDecSurfacePool::init(VideoDecoderConfig* config,
|
|
Packit |
1244b8 |
const SharedPtr<SurfaceAllocator>& allocator)
|
|
Packit |
1244b8 |
{
|
|
Packit |
1244b8 |
m_allocator = allocator;
|
|
Packit |
1244b8 |
m_allocParams.width = config->width;
|
|
Packit |
1244b8 |
m_allocParams.height = config->height;
|
|
Packit |
1244b8 |
m_allocParams.fourcc = config->fourcc;
|
|
Packit |
1244b8 |
m_allocParams.size = config->surfaceNumber;
|
|
Packit |
1244b8 |
if (m_allocator->alloc(m_allocator.get(), &m_allocParams) != YAMI_SUCCESS) {
|
|
Packit |
1244b8 |
ERROR("allocate surface failed (%dx%d), size = %d",
|
|
Packit |
1244b8 |
m_allocParams.width, m_allocParams.height , m_allocParams.size);
|
|
Packit |
1244b8 |
return false;
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
uint32_t size = m_allocParams.size;
|
|
Packit |
1244b8 |
uint32_t width = m_allocParams.width;
|
|
Packit |
1244b8 |
uint32_t height = m_allocParams.height;
|
|
Packit |
1244b8 |
uint32_t fourcc = config->fourcc;
|
|
Packit |
1244b8 |
if (!m_allocParams.getSurface || !m_allocParams.putSurface) {
|
|
Packit |
1244b8 |
m_allocParams.getSurface = getSurface;
|
|
Packit |
1244b8 |
m_allocParams.putSurface = putSurface;
|
|
Packit |
1244b8 |
m_allocParams.user = this;
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
for (uint32_t i = 0; i < size; i++) {
|
|
Packit |
1244b8 |
intptr_t s = m_allocParams.surfaces[i];
|
|
Packit |
1244b8 |
SurfacePtr surface(new VaapiSurface(s, width, height, fourcc));
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
m_surfaceMap[s] = surface.get();
|
|
Packit |
1244b8 |
m_surfaces.push_back(surface);
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
m_freed.push_back(s);
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
return true;
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
VaapiDecSurfacePool::VaapiDecSurfacePool()
|
|
Packit |
1244b8 |
{
|
|
Packit |
1244b8 |
memset(&m_allocParams, 0, sizeof(m_allocParams));
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
VaapiDecSurfacePool::~VaapiDecSurfacePool()
|
|
Packit |
1244b8 |
{
|
|
Packit |
1244b8 |
if (m_allocator && m_allocParams.surfaces) {
|
|
Packit |
1244b8 |
m_allocator->free(m_allocator.get(), &m_allocParams);
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
void VaapiDecSurfacePool::getSurfaceIDs(std::vector<VASurfaceID>& ids)
|
|
Packit |
1244b8 |
{
|
|
Packit |
1244b8 |
//no need hold lock, it never changed from start
|
|
Packit |
1244b8 |
assert(!ids.size());
|
|
Packit |
1244b8 |
size_t size = m_surfaces.size();
|
|
Packit |
1244b8 |
ids.reserve(size);
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
for (size_t i = 0; i < size; ++i)
|
|
Packit |
1244b8 |
ids.push_back(m_surfaces[i]->getID());
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
struct VaapiDecSurfacePool::SurfaceRecycler
|
|
Packit |
1244b8 |
{
|
|
Packit |
1244b8 |
SurfaceRecycler(const DecSurfacePoolPtr& pool): m_pool(pool) {}
|
|
Packit |
1244b8 |
void operator()(VaapiSurface* surface)
|
|
Packit |
1244b8 |
{
|
|
Packit |
1244b8 |
SurfaceAllocParams& params = m_pool->m_allocParams;
|
|
Packit |
1244b8 |
params.putSurface(¶ms, (intptr_t)surface->getID());
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
private:
|
|
Packit |
1244b8 |
DecSurfacePoolPtr m_pool;
|
|
Packit |
1244b8 |
};
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
SurfacePtr VaapiDecSurfacePool::acquire()
|
|
Packit |
1244b8 |
{
|
|
Packit |
1244b8 |
SurfacePtr surface;
|
|
Packit |
1244b8 |
intptr_t p;
|
|
Packit |
1244b8 |
YamiStatus status = m_allocParams.getSurface(&m_allocParams, &p);
|
|
Packit |
1244b8 |
if (status != YAMI_SUCCESS)
|
|
Packit |
1244b8 |
return surface;
|
|
Packit |
1244b8 |
//we only hold this lock after getSurface, since getSurface will do the lock
|
|
Packit |
1244b8 |
AutoLock lock(m_lock);
|
|
Packit |
1244b8 |
SurfaceMap::iterator it = m_surfaceMap.find(p);
|
|
Packit |
1244b8 |
if (it == m_surfaceMap.end()) {
|
|
Packit |
1244b8 |
ERROR("surface getter turn a invalid surface ptr, %p", (void*)p);
|
|
Packit |
1244b8 |
return surface;
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
surface.reset(it->second, SurfaceRecycler(shared_from_this()));
|
|
Packit |
1244b8 |
return surface;
|
|
Packit |
1244b8 |
}
|
|
Packit |
1244b8 |
|
|
Packit |
1244b8 |
} //namespace YamiMediaCodec
|