Blame decoder/vaapidecsurfacepool.cpp

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(&params, (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