Blame v4l2/v4l2_decode.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
#define __STDC_FORMAT_MACROS
Packit 1244b8
Packit 1244b8
#include <inttypes.h>
Packit 1244b8
#include <linux/videodev2.h>
Packit 1244b8
#include <unistd.h>
Packit 1244b8
#include <errno.h>
Packit 1244b8
#include <stdlib.h>
Packit 1244b8
#include <sys/mman.h>
Packit 1244b8
#include <string.h>
Packit 1244b8
#include <vector>
Packit 1244b8
#include <map>
Packit 1244b8
#include <deque>
Packit 1244b8
#include <set>
Packit 1244b8
#include <va/va_drmcommon.h>
Packit 1244b8
#if defined(__ENABLE_WAYLAND__)
Packit 1244b8
#include <va/va_wayland.h>
Packit 1244b8
#endif
Packit 1244b8
#include "v4l2_decode.h"
Packit 1244b8
#include "VideoDecoderHost.h"
Packit 1244b8
#include "common/log.h"
Packit 1244b8
#include "common/common_def.h"
Packit 1244b8
#include "common/basesurfaceallocator.h"
Packit 1244b8
#include "vaapi/vaapidisplay.h"
Packit 1244b8
#include "vaapi/VaapiUtils.h"
Packit 1244b8
Packit 1244b8
#define INT64_TO_TIMEVAL(i64, time_val)                 \
Packit 1244b8
    do {                                                \
Packit 1244b8
        time_val.tv_sec = (int32_t)(i64 >> 31);         \
Packit 1244b8
        time_val.tv_usec = (int32_t)(i64 & 0x7fffffff); \
Packit 1244b8
    } while (0)
Packit 1244b8
#define TIMEVAL_TO_INT64(i64, time_val)       \
Packit 1244b8
    do {                                      \
Packit 1244b8
        i64 = time_val.tv_sec;                \
Packit 1244b8
        i64 = (i64 << 31) + time_val.tv_usec; \
Packit 1244b8
    } while (0)
Packit 1244b8
Packit 1244b8
//return if we have error
Packit 1244b8
#define ERROR_RETURN(no) \
Packit 1244b8
    do {                 \
Packit 1244b8
        if (no) {        \
Packit 1244b8
            errno = no;  \
Packit 1244b8
            return -1;   \
Packit 1244b8
        }                \
Packit 1244b8
    } while (0)
Packit 1244b8
Packit 1244b8
#define CHECK(cond)                      \
Packit 1244b8
    do {                                 \
Packit 1244b8
        if (!(cond)) {                   \
Packit 1244b8
            ERROR("%s is false", #cond); \
Packit 1244b8
            ERROR_RETURN(EINVAL);        \
Packit 1244b8
        }                                \
Packit 1244b8
    } while (0)
Packit 1244b8
Packit 1244b8
//check condition in post messsage.
Packit 1244b8
#define PCHECK(cond)                     \
Packit 1244b8
    do {                                 \
Packit 1244b8
        if (!(cond)) {                   \
Packit 1244b8
            m_state = kError;            \
Packit 1244b8
            ERROR("%s is false", #cond); \
Packit 1244b8
            return;                      \
Packit 1244b8
        }                                \
Packit 1244b8
    } while (0)
Packit 1244b8
Packit 1244b8
#define SEND(func)                     \
Packit 1244b8
    do {                               \
Packit 1244b8
        int32_t ret_ = sendTask(func); \
Packit 1244b8
        ERROR_RETURN(ret_);            \
Packit 1244b8
    } while (0)
Packit 1244b8
Packit 1244b8
const static uint32_t kDefaultInputSize = 1024 * 1024;
Packit 1244b8
Packit 1244b8
//#undef DEBUG
Packit 1244b8
//#define DEBUG ERROR
Packit 1244b8
Packit 1244b8
using namespace std;
Packit 1244b8
Packit 1244b8
struct FrameInfo {
Packit 1244b8
    int64_t timeStamp;
Packit 1244b8
};
Packit 1244b8
Packit 1244b8
class V4l2Decoder::Output {
Packit 1244b8
public:
Packit 1244b8
    Output(V4l2Decoder* decoder)
Packit 1244b8
        : m_decoder(decoder)
Packit 1244b8
    {
Packit 1244b8
        memset(&m_lastFormat, 0, sizeof(m_lastFormat));
Packit 1244b8
    }
Packit 1244b8
    virtual void setDecodeAllocator(DecoderPtr decoder)
Packit 1244b8
    {
Packit 1244b8
        /* nothing */
Packit 1244b8
    }
Packit 1244b8
    virtual int32_t requestBuffers(uint32_t count) = 0;
Packit 1244b8
    virtual void output(SharedPtr<VideoFrame>& frame) = 0;
Packit 1244b8
    virtual bool isAllocationDone() = 0;
Packit 1244b8
    virtual bool isOutputReady() = 0;
Packit 1244b8
    virtual int32_t deque(struct v4l2_buffer* buf) = 0;
Packit 1244b8
    virtual int32_t queue(struct v4l2_buffer* buf)
Packit 1244b8
    {
Packit 1244b8
        m_decoder->m_out.queue(buf->index);
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
    virtual int32_t createBuffers(struct v4l2_create_buffers* createBuffers)
Packit 1244b8
    {
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
    virtual void streamOff()
Packit 1244b8
    {
Packit 1244b8
        //nothing for base
Packit 1244b8
    }
Packit 1244b8
    void flush()
Packit 1244b8
    {
Packit 1244b8
        //forget pending format change on flush
Packit 1244b8
        m_pendingFormat.reset();
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    bool setFormat(const VideoFormatInfo* format)
Packit 1244b8
    {
Packit 1244b8
        DEBUG("last format = %dx%dx%d@%x",
Packit 1244b8
             m_lastFormat.surfaceWidth, m_lastFormat.surfaceHeight,
Packit 1244b8
             m_lastFormat.surfaceNumber, m_lastFormat.fourcc);
Packit 1244b8
        if (m_pendingFormat) {
Packit 1244b8
            DEBUG("pending format = %dx%dx%d@%x",
Packit 1244b8
                m_pendingFormat->surfaceWidth, m_pendingFormat->surfaceHeight,
Packit 1244b8
                m_pendingFormat->surfaceNumber, m_pendingFormat->fourcc);
Packit 1244b8
        }
Packit 1244b8
        bool changed = m_lastFormat.surfaceWidth != format->surfaceWidth
Packit 1244b8
            || m_lastFormat.surfaceHeight != format->surfaceHeight
Packit 1244b8
            || m_lastFormat.surfaceNumber != format->surfaceNumber
Packit 1244b8
            || m_lastFormat.fourcc != format->fourcc;
Packit 1244b8
        if (changed) {
Packit 1244b8
            DEBUG("format changed to %dx%dx%d@%x",
Packit 1244b8
                format->surfaceWidth, format->surfaceHeight,
Packit 1244b8
                format->surfaceNumber, format->fourcc);
Packit 1244b8
            m_pendingFormat.reset(new VideoFormatInfo);
Packit 1244b8
            *m_pendingFormat = *format;
Packit 1244b8
        }
Packit 1244b8
        return changed;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
protected:
Packit 1244b8
    void requestFrameInfo(uint32_t count)
Packit 1244b8
    {
Packit 1244b8
        m_frameInfo.resize(count);
Packit 1244b8
    }
Packit 1244b8
    void outputFrame(uint32_t index, SharedPtr<VideoFrame>& frame)
Packit 1244b8
    {
Packit 1244b8
        setTimeStamp(index, frame->timeStamp);
Packit 1244b8
        m_decoder->m_out.put(index);
Packit 1244b8
        m_decoder->setDeviceEvent(0);
Packit 1244b8
    }
Packit 1244b8
    void getTimeStamp(uint32_t index, struct timeval& timeStamp)
Packit 1244b8
    {
Packit 1244b8
        DEBUG("index = %d, size = %d", (int)index, (int)m_frameInfo.size());
Packit 1244b8
        ASSERT(index < m_frameInfo.size());
Packit 1244b8
        INT64_TO_TIMEVAL(m_frameInfo[index].timeStamp, timeStamp);
Packit 1244b8
    }
Packit 1244b8
    void setTimeStamp(uint32_t index, int64_t timeStamp)
Packit 1244b8
    {
Packit 1244b8
        ASSERT(index < m_frameInfo.size());
Packit 1244b8
        m_frameInfo[index].timeStamp = timeStamp;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    void getBufferInfo(struct v4l2_buffer* buf, uint32_t index)
Packit 1244b8
    {
Packit 1244b8
Packit 1244b8
        buf->index = index;
Packit 1244b8
        //chrome will use this value.
Packit 1244b8
        buf->m.planes[0].bytesused = 1;
Packit 1244b8
        buf->m.planes[1].bytesused = 1;
Packit 1244b8
        getTimeStamp(index, buf->timestamp);
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    void finishFormatChangeIfNeeded()
Packit 1244b8
    {
Packit 1244b8
        DEBUG("m_pendingFormat = %d", !!m_pendingFormat);
Packit 1244b8
        if (m_pendingFormat) {
Packit 1244b8
            m_lastFormat = *m_pendingFormat;
Packit 1244b8
            m_pendingFormat.reset();
Packit 1244b8
        }
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    V4l2Decoder* m_decoder;
Packit 1244b8
    vector<FrameInfo> m_frameInfo;
Packit 1244b8
    Lock m_lock;
Packit 1244b8
    VideoFormatInfo m_lastFormat;
Packit 1244b8
    //format changed but caller did not allocate buffer for us.
Packit 1244b8
    SharedPtr<VideoFormatInfo> m_pendingFormat;
Packit 1244b8
};
Packit 1244b8
Packit 1244b8
class SurfaceGetter {
Packit 1244b8
    typedef map<intptr_t, uint32_t> UsedMap;
Packit 1244b8
    const static uint32_t kHoldByRenderer = 1;
Packit 1244b8
    const static uint32_t kHoldByDecoder = 2;
Packit 1244b8
Packit 1244b8
public:
Packit 1244b8
    static YamiStatus getSurface(SurfaceAllocParams* param, intptr_t* surface)
Packit 1244b8
    {
Packit 1244b8
        SurfaceGetter* p = (SurfaceGetter*)param->user;
Packit 1244b8
        return p->getSurface(surface);
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    static YamiStatus putSurface(SurfaceAllocParams* param, intptr_t surface)
Packit 1244b8
    {
Packit 1244b8
        SurfaceGetter* p = (SurfaceGetter*)param->user;
Packit 1244b8
        return p->putSurface(surface);
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    YamiStatus getSurface(intptr_t* surface)
Packit 1244b8
    {
Packit 1244b8
        AutoLock l(m_lock);
Packit 1244b8
        if (!takeOneFree(surface, kHoldByDecoder))
Packit 1244b8
            return YAMI_DECODE_NO_SURFACE;
Packit 1244b8
        DEBUG("getSurface: %x", (uint32_t)*surface);
Packit 1244b8
        return YAMI_SUCCESS;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    YamiStatus putSurface(intptr_t surface)
Packit 1244b8
    {
Packit 1244b8
        AutoLock l(m_lock);
Packit 1244b8
Packit 1244b8
        clearFlag(surface, kHoldByDecoder);
Packit 1244b8
        DEBUG("putSurface: %x", (uint32_t)surface);
Packit 1244b8
        return YAMI_SUCCESS;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    bool holdByRenderer(intptr_t surface)
Packit 1244b8
    {
Packit 1244b8
        AutoLock l(m_lock);
Packit 1244b8
        return setFlag(surface, kHoldByRenderer);
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    bool freeByRenderer(intptr_t surface)
Packit 1244b8
    {
Packit 1244b8
        AutoLock l(m_lock);
Packit 1244b8
        return clearFlag(surface, kHoldByRenderer);
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    void holdAllByRenderer()
Packit 1244b8
    {
Packit 1244b8
        DEBUG("hold all by renderer");
Packit 1244b8
Packit 1244b8
        AutoLock l(m_lock);
Packit 1244b8
        m_freed.clear();
Packit 1244b8
Packit 1244b8
        UsedMap::iterator it = m_used.begin();
Packit 1244b8
        while (it != m_used.end()) {
Packit 1244b8
            it->second = kHoldByRenderer;
Packit 1244b8
            ++it;
Packit 1244b8
        }
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    bool takeOneFreeByRenderer(intptr_t* surface)
Packit 1244b8
    {
Packit 1244b8
        AutoLock l(m_lock);
Packit 1244b8
        return takeOneFree(surface, kHoldByRenderer);
Packit 1244b8
    }
Packit 1244b8
    bool addNewSurface(intptr_t surface)
Packit 1244b8
    {
Packit 1244b8
        AutoLock l(m_lock);
Packit 1244b8
        UsedMap::iterator it = m_used.find(surface);
Packit 1244b8
        if (it != m_used.end()) {
Packit 1244b8
            ERROR("add duplicate surface %x, it's hold by %s", (uint32_t)surface, getOwnerName(it->second));
Packit 1244b8
        }
Packit 1244b8
        m_freed.push_back(surface);
Packit 1244b8
        m_used[surface] = 0;
Packit 1244b8
        return true;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    void removeAllSurfaces()
Packit 1244b8
    {
Packit 1244b8
        m_used.clear();
Packit 1244b8
        m_freed.clear();
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
private:
Packit 1244b8
    bool takeOneFree(intptr_t* surface, uint32_t flag)
Packit 1244b8
    {
Packit 1244b8
        if (m_freed.empty()) {
Packit 1244b8
            DEBUG("no free surface");
Packit 1244b8
            UsedMap::iterator it = m_used.begin();
Packit 1244b8
            while (it != m_used.end()) {
Packit 1244b8
                DEBUG("surface %x, it's hold by %s", (uint32_t)it->first, getOwnerName(it->second));
Packit 1244b8
                ++it;
Packit 1244b8
            }
Packit 1244b8
            return false;
Packit 1244b8
        }
Packit 1244b8
        *surface = m_freed.front();
Packit 1244b8
        m_used[*surface] = flag;
Packit 1244b8
        m_freed.pop_front();
Packit 1244b8
        return true;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    bool setFlag(intptr_t surface, uint32_t flag)
Packit 1244b8
    {
Packit 1244b8
        UsedMap::iterator it = m_used.find(surface);
Packit 1244b8
        DEBUG("%s takes %x", getOwnerName(flag), (uint32_t)surface);
Packit 1244b8
        if (it == m_used.end()) {
Packit 1244b8
            ERROR("set owner to %s failed for %x", getOwnerName(flag), (uint32_t)surface);
Packit 1244b8
            return false;
Packit 1244b8
        }
Packit 1244b8
        it->second |= flag;
Packit 1244b8
        return true;
Packit 1244b8
    }
Packit 1244b8
    YamiStatus clearFlag(intptr_t surface, uint32_t flag)
Packit 1244b8
    {
Packit 1244b8
        UsedMap::iterator it = m_used.find(surface);
Packit 1244b8
        DEBUG("return %x from %s", (uint32_t)surface, getOwnerName(flag));
Packit 1244b8
Packit 1244b8
        if (it == m_used.end()) {
Packit 1244b8
            ERROR("clear wrong surface id = %x", (uint32_t)surface);
Packit 1244b8
            return YAMI_INVALID_PARAM;
Packit 1244b8
        }
Packit 1244b8
        if (!(it->second & flag)) {
Packit 1244b8
            ERROR("%x is not hold by %s, it hold by %s", (uint32_t)surface, getOwnerName(flag), getOwnerName(it->second));
Packit 1244b8
            return YAMI_INVALID_PARAM;
Packit 1244b8
        }
Packit 1244b8
        it->second &= ~flag;
Packit 1244b8
        if (!it->second) {
Packit 1244b8
            m_freed.push_back(surface);
Packit 1244b8
        }
Packit 1244b8
        return YAMI_SUCCESS;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
private:
Packit 1244b8
    const char* getOwnerName(uint32_t flag)
Packit 1244b8
    {
Packit 1244b8
        if (flag == kHoldByRenderer)
Packit 1244b8
            return "renderer";
Packit 1244b8
        if (flag == kHoldByDecoder)
Packit 1244b8
            return "decoder";
Packit 1244b8
        if (flag == (kHoldByRenderer | kHoldByDecoder))
Packit 1244b8
            return "decoder and render";
Packit 1244b8
        if (!flag)
Packit 1244b8
            return "no one";
Packit 1244b8
        return "unknow";
Packit 1244b8
    }
Packit 1244b8
    Lock m_lock;
Packit 1244b8
    UsedMap m_used;
Packit 1244b8
    deque<intptr_t> m_freed;
Packit 1244b8
};
Packit 1244b8
Packit 1244b8
//the buffer resource is created from V4L2's user
Packit 1244b8
class ExternalBufferOutput : public V4l2Decoder::Output, BaseSurfaceAllocator {
Packit 1244b8
    typedef map<intptr_t, uint32_t> SurfaceMap;
Packit 1244b8
Packit 1244b8
public:
Packit 1244b8
    ExternalBufferOutput(V4l2Decoder* decoder)
Packit 1244b8
        : V4l2Decoder::Output(decoder)
Packit 1244b8
        , m_getter(new SurfaceGetter)
Packit 1244b8
    {
Packit 1244b8
    }
Packit 1244b8
    virtual void setDecodeAllocator(DecoderPtr decoder)
Packit 1244b8
    {
Packit 1244b8
        decoder->setAllocator(this);
Packit 1244b8
        /* nothing */
Packit 1244b8
    }
Packit 1244b8
    virtual int32_t requestBuffers(uint32_t count)
Packit 1244b8
    {
Packit 1244b8
        AutoLock l(m_lock);
Packit 1244b8
        m_count = count;
Packit 1244b8
        if (!count) {
Packit 1244b8
            for (size_t i = 0; i < m_surfaces.size(); i++) {
Packit 1244b8
                if (m_surfaces[i] != (intptr_t)VA_INVALID_SURFACE) {
Packit 1244b8
                    destorySurface(m_surfaces[i]);
Packit 1244b8
                }
Packit 1244b8
            }
Packit 1244b8
            m_getter->removeAllSurfaces();
Packit 1244b8
            m_surfaceMap.clear();
Packit 1244b8
        } else {
Packit 1244b8
            finishFormatChangeIfNeeded();
Packit 1244b8
        }
Packit 1244b8
        m_surfaces.resize(count, VA_INVALID_SURFACE);
Packit 1244b8
        requestFrameInfo(count);
Packit 1244b8
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
    virtual void output(SharedPtr<VideoFrame>& frame)
Packit 1244b8
    {
Packit 1244b8
        ASSERT(m_getter.get());
Packit 1244b8
        m_getter->holdByRenderer(frame->surface);
Packit 1244b8
Packit 1244b8
        AutoLock l(m_lock);
Packit 1244b8
Packit 1244b8
        SurfaceMap::iterator it = m_surfaceMap.find(frame->surface);
Packit 1244b8
        ASSERT(it != m_surfaceMap.end());
Packit 1244b8
        outputFrame(it->second, frame);
Packit 1244b8
    }
Packit 1244b8
    virtual bool isAllocationDone()
Packit 1244b8
    {
Packit 1244b8
        bool ret = !m_pendingFormat && m_surfaceMap.size() == m_count;
Packit 1244b8
        DEBUG("is allocation done = %d, pending format = %d, size = %d, count = %d",
Packit 1244b8
            ret, !!m_pendingFormat, (int)m_surfaceMap.size(), m_count);
Packit 1244b8
        return ret;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    virtual bool isOutputReady()
Packit 1244b8
    {
Packit 1244b8
        return true;
Packit 1244b8
    }
Packit 1244b8
    int32_t queue(struct v4l2_buffer* buf)
Packit 1244b8
    {
Packit 1244b8
        uint32_t index;
Packit 1244b8
        bool streamOn;
Packit 1244b8
        //create and update index
Packit 1244b8
        intptr_t surface;
Packit 1244b8
        {
Packit 1244b8
            //we need hold lock in freeVideoFrame, so we keep the lock in {}
Packit 1244b8
            AutoLock l(m_lock);
Packit 1244b8
            index = buf->index;
Packit 1244b8
Packit 1244b8
            CHECK(index < m_surfaces.size());
Packit 1244b8
            streamOn = m_decoder->m_outputOn;
Packit 1244b8
            if (!m_decoder->m_outputOn) {
Packit 1244b8
                CHECK(createSurface(surface, buf));
Packit 1244b8
                m_surfaces[index] = surface;
Packit 1244b8
                m_surfaceMap[surface] = index;
Packit 1244b8
            }
Packit 1244b8
            surface = m_surfaces[index];
Packit 1244b8
        }
Packit 1244b8
Packit 1244b8
        ASSERT(m_getter.get());
Packit 1244b8
        if (!streamOn)
Packit 1244b8
            m_getter->addNewSurface(surface);
Packit 1244b8
        else
Packit 1244b8
            m_getter->freeByRenderer(surface);
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
    virtual int32_t deque(struct v4l2_buffer* buf)
Packit 1244b8
    {
Packit 1244b8
        AutoLock l(m_lock);
Packit 1244b8
        uint32_t index;
Packit 1244b8
        if (m_decoder->m_outputOn) {
Packit 1244b8
            if (!m_decoder->m_out.deque(index)) {
Packit 1244b8
                ERROR_RETURN(EAGAIN);
Packit 1244b8
            }
Packit 1244b8
        }
Packit 1244b8
        else {
Packit 1244b8
            CHECK(m_getter);
Packit 1244b8
            intptr_t p;
Packit 1244b8
            //this mean we need deque the surface from free list
Packit 1244b8
            CHECK(m_getter->takeOneFreeByRenderer(&p);;
Packit 1244b8
            SurfaceMap::iterator it = m_surfaceMap.find(p);
Packit 1244b8
            CHECK(it != m_surfaceMap.end());
Packit 1244b8
            index = it->second;
Packit 1244b8
        }
Packit 1244b8
        getBufferInfo(buf, index);
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
    virtual void streamOff()
Packit 1244b8
    {
Packit 1244b8
        m_getter->holdAllByRenderer();
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
protected:
Packit 1244b8
    virtual YamiStatus doAlloc(SurfaceAllocParams* params)
Packit 1244b8
    {
Packit 1244b8
        AutoLock l(m_lock);
Packit 1244b8
        if (m_surfaces.size() != m_surfaceMap.size()) {
Packit 1244b8
            ERROR("surfaces size did not match map size (%d != %d)", (int)m_surfaces.size(), (int)m_surfaceMap.size());
Packit 1244b8
            return YAMI_FAIL;
Packit 1244b8
        }
Packit 1244b8
        if (params->size > m_surfaces.size()) {
Packit 1244b8
            DEBUG("ATTENTION!!! require size > surface size (%d > %d), m_isThumbnailMode = %d", (int)params->size, (int)m_surfaces.size(), m_decoder->m_isThumbnailMode);
Packit 1244b8
        }
Packit 1244b8
Packit 1244b8
        params->surfaces = &m_surfaces[0];
Packit 1244b8
        params->size = m_surfaces.size();
Packit 1244b8
        params->user = m_getter.get();
Packit 1244b8
        params->getSurface = SurfaceGetter::getSurface;
Packit 1244b8
        params->putSurface = SurfaceGetter::putSurface;
Packit 1244b8
        return YAMI_SUCCESS;
Packit 1244b8
    }
Packit 1244b8
    virtual YamiStatus doFree(SurfaceAllocParams* params)
Packit 1244b8
    {
Packit 1244b8
        /* nothing */
Packit 1244b8
        return YAMI_SUCCESS;
Packit 1244b8
    }
Packit 1244b8
    virtual void doUnref()
Packit 1244b8
    {
Packit 1244b8
        /* nothing */
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    virtual bool createExternalSurface(intptr_t& surface, uint32_t rtFormat, VASurfaceAttribExternalBuffers& external)
Packit 1244b8
    {
Packit 1244b8
        VASurfaceAttrib attribs[2];
Packit 1244b8
        attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
Packit 1244b8
        attribs[0].type = VASurfaceAttribMemoryType;
Packit 1244b8
        attribs[0].value.type = VAGenericValueTypeInteger;
Packit 1244b8
        attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
Packit 1244b8
Packit 1244b8
        attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
Packit 1244b8
        attribs[1].type = VASurfaceAttribExternalBufferDescriptor;
Packit 1244b8
        attribs[1].value.type = VAGenericValueTypePointer;
Packit 1244b8
        attribs[1].value.value.p = &external;
Packit 1244b8
Packit 1244b8
        VASurfaceID id;
Packit 1244b8
        VAStatus vaStatus = vaCreateSurfaces(m_decoder->m_display->getID(), rtFormat, external.width, external.height,
Packit 1244b8
            &id, 1, attribs, N_ELEMENTS(attribs));
Packit 1244b8
        if (!checkVaapiStatus(vaStatus, "vaCreateSurfaces"))
Packit 1244b8
            return false;
Packit 1244b8
        surface = static_cast<intptr_t>(id);
Packit 1244b8
        return true;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    virtual bool createSurface(intptr_t& surface, struct v4l2_buffer* buf) = 0;
Packit 1244b8
    virtual bool destorySurface(intptr_t& surface) = 0;
Packit 1244b8
Packit 1244b8
    uint32_t m_count;
Packit 1244b8
    vector<intptr_t> m_surfaces;
Packit 1244b8
    SurfaceMap m_surfaceMap;
Packit 1244b8
    SharedPtr<SurfaceGetter> m_getter;
Packit 1244b8
};
Packit 1244b8
Packit 1244b8
class ExternalDmaBufOutput : public ExternalBufferOutput {
Packit 1244b8
public:
Packit 1244b8
    ExternalDmaBufOutput(V4l2Decoder* decoder)
Packit 1244b8
        : ExternalBufferOutput(decoder)
Packit 1244b8
    {
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    virtual int32_t createBuffers(struct v4l2_create_buffers* createBuffers)
Packit 1244b8
    {
Packit 1244b8
        m_createBuffers.reset(new v4l2_create_buffers);
Packit 1244b8
        *m_createBuffers = *createBuffers;
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    virtual bool createSurface(intptr_t& surface, struct v4l2_buffer* buf)
Packit 1244b8
    {
Packit 1244b8
        if (!m_createBuffers) {
Packit 1244b8
            ERROR("you need create buffer first");
Packit 1244b8
            return false;
Packit 1244b8
        }
Packit 1244b8
Packit 1244b8
        v4l2_pix_format_mplane& format = m_createBuffers->format.fmt.pix_mp;
Packit 1244b8
        VASurfaceAttribExternalBuffers external;
Packit 1244b8
        memset(&external, 0, sizeof(external));
Packit 1244b8
        external.pixel_format = format.pixelformat;
Packit 1244b8
        uint32_t rtFormat = getRtFormat(format.pixelformat);
Packit 1244b8
        if (!rtFormat) {
Packit 1244b8
            ERROR("failed get rtformat for %.4s", (char*)&format.pixelformat);
Packit 1244b8
            return false;
Packit 1244b8
        }
Packit 1244b8
        external.width = format.width;
Packit 1244b8
        external.height = format.height;
Packit 1244b8
        external.num_planes = format.num_planes;
Packit 1244b8
        for (uint32_t i = 0; i < format.num_planes; i++) {
Packit 1244b8
            external.pitches[i] = format.plane_fmt[i].bytesperline;
Packit 1244b8
            //not really right, but we use sizeimage to deliver offset
Packit 1244b8
            external.offsets[i] = format.plane_fmt[i].sizeimage;
Packit 1244b8
        }
Packit 1244b8
        external.buffers = (uintptr_t *)&buf->m.userptr;
Packit 1244b8
        external.num_buffers = 1;
Packit 1244b8
Packit 1244b8
        return createExternalSurface(surface, rtFormat, external);
Packit 1244b8
    }
Packit 1244b8
    virtual bool destorySurface(intptr_t& surface)
Packit 1244b8
    {
Packit 1244b8
        VASurfaceID s = (VASurfaceID)surface;
Packit 1244b8
        return checkVaapiStatus(vaDestroySurfaces(m_decoder->m_display->getID(), &s, 1), "vaDestroySurfaces");
Packit 1244b8
    }
Packit 1244b8
    SharedPtr<v4l2_create_buffers> m_createBuffers;
Packit 1244b8
};
Packit 1244b8
Packit 1244b8
#ifdef __ENABLE_EGL__
Packit 1244b8
#include "egl/egl_vaapi_image.h"
Packit 1244b8
class EglOutput : public V4l2Decoder::Output {
Packit 1244b8
public:
Packit 1244b8
    EglOutput(V4l2Decoder* decoder, VideoDataMemoryType memory_type)
Packit 1244b8
        : V4l2Decoder::Output(decoder)
Packit 1244b8
        , m_memoryType(memory_type)
Packit 1244b8
    {
Packit 1244b8
    }
Packit 1244b8
    virtual int32_t requestBuffers(uint32_t count)
Packit 1244b8
    {
Packit 1244b8
        v4l2_pix_format_mplane& format = m_decoder->m_outputFormat.fmt.pix_mp;
Packit 1244b8
        DisplayPtr& display = m_decoder->m_display;
Packit 1244b8
        CHECK(bool(display));
Packit 1244b8
        CHECK(format.width && format.height);
Packit 1244b8
        m_eglVaapiImages.clear();
Packit 1244b8
        for (uint32_t i = 0; i < count; i++) {
Packit 1244b8
            SharedPtr<EglVaapiImage> image(new EglVaapiImage(display->getID(), format.width, format.height));
Packit 1244b8
            if (!image->init()) {
Packit 1244b8
                ERROR("Create egl vaapi image failed");
Packit 1244b8
                m_eglVaapiImages.clear();
Packit 1244b8
                return EINVAL;
Packit 1244b8
            }
Packit 1244b8
            m_eglVaapiImages.push_back(image);
Packit 1244b8
        }
Packit 1244b8
        requestFrameInfo(count);
Packit 1244b8
        if (count) {
Packit 1244b8
            finishFormatChangeIfNeeded();
Packit 1244b8
        }
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
    int32_t useEglImage(EGLDisplay eglDisplay, EGLContext eglContext, uint32_t bufferIndex, void* eglImage)
Packit 1244b8
    {
Packit 1244b8
        CHECK(m_memoryType == VIDEO_DATA_MEMORY_TYPE_DRM_NAME || m_memoryType == VIDEO_DATA_MEMORY_TYPE_DMA_BUF);
Packit 1244b8
        CHECK(bufferIndex < m_eglVaapiImages.size());
Packit 1244b8
        *(EGLImageKHR*)eglImage = m_eglVaapiImages[bufferIndex]->createEglImage(eglDisplay, eglContext, m_memoryType);
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
    void output(SharedPtr<VideoFrame>& frame)
Packit 1244b8
    {
Packit 1244b8
        uint32_t index;
Packit 1244b8
        if (!m_decoder->m_out.get(index)) {
Packit 1244b8
            ERROR("bug: can't get index");
Packit 1244b8
            return;
Packit 1244b8
        }
Packit 1244b8
        if (!(index < m_eglVaapiImages.size())) {
Packit 1244b8
            ERROR("index = %d, size = %d", (int)index, (int)m_eglVaapiImages.size());
Packit 1244b8
            ASSERT(index < m_eglVaapiImages.size());
Packit 1244b8
        }
Packit 1244b8
        m_eglVaapiImages[index]->blt(frame);
Packit 1244b8
        outputFrame(index, frame);
Packit 1244b8
    }
Packit 1244b8
    bool isAllocationDone()
Packit 1244b8
    {
Packit 1244b8
        bool ret = !m_pendingFormat && !m_eglVaapiImages.empty();
Packit 1244b8
        DEBUG("is allocation done = %d, pending format = %d, is empty = %d",
Packit 1244b8
            ret, !!m_pendingFormat, m_eglVaapiImages.empty());
Packit 1244b8
Packit 1244b8
        return ret;
Packit 1244b8
    }
Packit 1244b8
    bool isOutputReady()
Packit 1244b8
    {
Packit 1244b8
        uint32_t index;
Packit 1244b8
        return m_decoder->m_out.peek(index);
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    int32_t deque(struct v4l2_buffer* buf)
Packit 1244b8
    {
Packit 1244b8
        uint32_t index;
Packit 1244b8
        if (!m_decoder->m_out.deque(index)) {
Packit 1244b8
            ERROR_RETURN(EAGAIN);
Packit 1244b8
        }
Packit 1244b8
        getBufferInfo(buf, index);
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
private:
Packit 1244b8
    std::vector<SharedPtr<EglVaapiImage> > m_eglVaapiImages;
Packit 1244b8
    VideoDataMemoryType m_memoryType;
Packit 1244b8
};
Packit 1244b8
#endif
Packit 1244b8
Packit 1244b8
V4l2Decoder::V4l2Decoder()
Packit 1244b8
    : m_inputOn(false)
Packit 1244b8
    , m_outputOn(false)
Packit 1244b8
    , m_state(kUnStarted)
Packit 1244b8
{
Packit 1244b8
    memset(&m_inputFormat, 0, sizeof(m_inputFormat));
Packit 1244b8
    memset(&m_outputFormat, 0, sizeof(m_outputFormat));
Packit 1244b8
    m_output.reset(new ExternalDmaBufOutput(this));
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
V4l2Decoder::~V4l2Decoder()
Packit 1244b8
{
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
void V4l2Decoder::releaseCodecLock(bool lockable)
Packit 1244b8
{
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
bool V4l2Decoder::start()
Packit 1244b8
{
Packit 1244b8
    return false;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
bool V4l2Decoder::stop()
Packit 1244b8
{
Packit 1244b8
    return true;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
bool V4l2Decoder::inputPulse(uint32_t index)
Packit 1244b8
{
Packit 1244b8
Packit 1244b8
    return true; // always return true for decode; simply ignored unsupported nal
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
bool V4l2Decoder::outputPulse(uint32_t& index)
Packit 1244b8
{
Packit 1244b8
    return true;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
bool V4l2Decoder::recycleOutputBuffer(int32_t index)
Packit 1244b8
{
Packit 1244b8
    // FIXME, after we remove the extra vpp, renderDone() should come here
Packit 1244b8
    return true;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
bool V4l2Decoder::recycleInputBuffer(struct v4l2_buffer* dqbuf)
Packit 1244b8
{
Packit 1244b8
Packit 1244b8
    return true;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
bool V4l2Decoder::acceptInputBuffer(struct v4l2_buffer* qbuf)
Packit 1244b8
{
Packit 1244b8
Packit 1244b8
    return true;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
bool V4l2Decoder::giveOutputBuffer(struct v4l2_buffer* dqbuf)
Packit 1244b8
{
Packit 1244b8
Packit 1244b8
    return true;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
#ifndef V4L2_PIX_FMT_VP9
Packit 1244b8
#define V4L2_PIX_FMT_VP9 YAMI_FOURCC('V', 'P', '9', '0')
Packit 1244b8
#endif
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::ioctl(int command, void* arg)
Packit 1244b8
{
Packit 1244b8
    DEBUG("fd: %d, ioctl command: %s", m_fd[0], IoctlCommandString(command));
Packit 1244b8
    switch (command) {
Packit 1244b8
    case VIDIOC_QBUF: {
Packit 1244b8
        struct v4l2_buffer* qbuf = static_cast<struct v4l2_buffer*>(arg);
Packit 1244b8
        return onQueueBuffer(qbuf);
Packit 1244b8
    }
Packit 1244b8
    case VIDIOC_DQBUF: {
Packit 1244b8
        struct v4l2_buffer* dqbuf = static_cast<struct v4l2_buffer*>(arg);
Packit 1244b8
        return onDequeBuffer(dqbuf);
Packit 1244b8
    }
Packit 1244b8
    case VIDIOC_STREAMON: {
Packit 1244b8
        __u32 type = *((__u32*)arg);
Packit 1244b8
        return onStreamOn(type);
Packit 1244b8
    }
Packit 1244b8
    case VIDIOC_STREAMOFF: {
Packit 1244b8
        __u32 type = *((__u32*)arg);
Packit 1244b8
        return onStreamOff(type);
Packit 1244b8
    }
Packit 1244b8
    case VIDIOC_QUERYCAP: {
Packit 1244b8
        return V4l2CodecBase::ioctl(command, arg);
Packit 1244b8
    }
Packit 1244b8
    case VIDIOC_REQBUFS: {
Packit 1244b8
        struct v4l2_requestbuffers* reqbufs = static_cast<struct v4l2_requestbuffers*>(arg);
Packit 1244b8
        return onRequestBuffers(reqbufs);
Packit 1244b8
    }
Packit 1244b8
    case VIDIOC_S_FMT: {
Packit 1244b8
        struct v4l2_format* format = static_cast<struct v4l2_format*>(arg);
Packit 1244b8
        return onSetFormat(format);
Packit 1244b8
    }
Packit 1244b8
    case VIDIOC_QUERYBUF: {
Packit 1244b8
        struct v4l2_buffer* buf = static_cast<struct v4l2_buffer*>(arg);
Packit 1244b8
        return onQueryBuffer(buf);
Packit 1244b8
    }
Packit 1244b8
    case VIDIOC_SUBSCRIBE_EVENT: {
Packit 1244b8
        struct v4l2_event_subscription* sub = static_cast<struct v4l2_event_subscription*>(arg);
Packit 1244b8
        return onSubscribeEvent(sub);
Packit 1244b8
    }
Packit 1244b8
    case VIDIOC_DQEVENT: {
Packit 1244b8
        // ::DequeueEvents
Packit 1244b8
        struct v4l2_event* ev = static_cast<struct v4l2_event*>(arg);
Packit 1244b8
        return onDequeEvent(ev);
Packit 1244b8
    }
Packit 1244b8
    case VIDIOC_G_FMT: {
Packit 1244b8
        // ::GetFormatInfo
Packit 1244b8
        struct v4l2_format* format = static_cast<struct v4l2_format*>(arg);
Packit 1244b8
        return onGetFormat(format);
Packit 1244b8
    }
Packit 1244b8
    case VIDIOC_G_CTRL: {
Packit 1244b8
        // ::CreateOutputBuffers
Packit 1244b8
        struct v4l2_control* ctrl = static_cast<struct v4l2_control*>(arg);
Packit 1244b8
        return onGetCtrl(ctrl);
Packit 1244b8
    }
Packit 1244b8
    case VIDIOC_ENUM_FMT: {
Packit 1244b8
        struct v4l2_fmtdesc* fmtdesc = static_cast<struct v4l2_fmtdesc*>(arg);
Packit 1244b8
        return onEnumFormat(fmtdesc);
Packit 1244b8
    }
Packit 1244b8
    case VIDIOC_G_CROP: {
Packit 1244b8
        struct v4l2_crop* crop = static_cast<struct v4l2_crop*>(arg);
Packit 1244b8
        return onGetCrop(crop);
Packit 1244b8
    }
Packit 1244b8
    case VIDIOC_CREATE_BUFS: {
Packit 1244b8
        struct v4l2_create_buffers* req = static_cast<struct v4l2_create_buffers*>(arg);
Packit 1244b8
        return onCreateBuffers(req);
Packit 1244b8
    }
Packit 1244b8
    default: {
Packit 1244b8
        ERROR("unknown ioctrl command: %d", command);
Packit 1244b8
        return -1;
Packit 1244b8
    }
Packit 1244b8
    }
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
VideoDecodeBuffer* V4l2Decoder::peekInput()
Packit 1244b8
{
Packit 1244b8
    uint32_t index;
Packit 1244b8
    if (!m_in.peek(index))
Packit 1244b8
        return NULL;
Packit 1244b8
    ASSERT(index < m_inputFrames.size());
Packit 1244b8
    VideoDecodeBuffer* inputBuffer = &(m_inputFrames[index]);
Packit 1244b8
    return inputBuffer;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
void V4l2Decoder::consumeInput()
Packit 1244b8
{
Packit 1244b8
    PCHECK(m_thread.isCurrent());
Packit 1244b8
    uint32_t index;
Packit 1244b8
    if (!m_in.get(index)) {
Packit 1244b8
        ERROR("bug: can't get from input");
Packit 1244b8
        return;
Packit 1244b8
    }
Packit 1244b8
    m_in.put(index);
Packit 1244b8
    setDeviceEvent(0);
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
void V4l2Decoder::getInputJob()
Packit 1244b8
{
Packit 1244b8
    PCHECK(m_thread.isCurrent());
Packit 1244b8
    PCHECK(bool(m_decoder));
Packit 1244b8
    if (m_state != kGetInput) {
Packit 1244b8
        DEBUG("early out, state = %d", m_state);
Packit 1244b8
        return;
Packit 1244b8
    }
Packit 1244b8
    VideoDecodeBuffer* inputBuffer = peekInput();
Packit 1244b8
    if (!inputBuffer) {
Packit 1244b8
        DEBUG("early out, no input buffer");
Packit 1244b8
        m_state = kWaitInput;
Packit 1244b8
        return;
Packit 1244b8
    }
Packit 1244b8
    YamiStatus status = m_decoder->decode(inputBuffer);
Packit 1244b8
    DEBUG("decode %d, return %d", (int)inputBuffer->size, (int)status);
Packit 1244b8
    if (status == YAMI_DECODE_FORMAT_CHANGE) {
Packit 1244b8
        DEBUG("decoder return format change");
Packit 1244b8
        m_state = kFormatChanged;
Packit 1244b8
        //now we need this format in output.
Packit 1244b8
        const VideoFormatInfo* outFormat = m_decoder->getFormatInfo();
Packit 1244b8
        PCHECK(outFormat);
Packit 1244b8
        m_output->setFormat(outFormat);
Packit 1244b8
        //drain output
Packit 1244b8
        getOutputJob();
Packit 1244b8
        return;
Packit 1244b8
    }
Packit 1244b8
    if (status == YAMI_DECODE_NO_SURFACE) {
Packit 1244b8
        if (m_output->isAllocationDone()) {
Packit 1244b8
            m_state = kGetOutput;
Packit 1244b8
            getOutputJob();
Packit 1244b8
            m_state = kWaitSurface;
Packit 1244b8
            DEBUG("early out, no surface");
Packit 1244b8
            return;
Packit 1244b8
        } else {
Packit 1244b8
            DEBUG("need relocation");
Packit 1244b8
            m_state = kWaitAllocation;
Packit 1244b8
            setCodecEvent();
Packit 1244b8
            return;
Packit 1244b8
        }
Packit 1244b8
    }
Packit 1244b8
    consumeInput();
Packit 1244b8
    if (!m_decoder->getFormatInfo()) {
Packit 1244b8
        DEBUG("need more data to detect output format");
Packit 1244b8
        post(bind(&V4l2Decoder::getInputJob, this));
Packit 1244b8
        return;
Packit 1244b8
    }
Packit 1244b8
    m_state = kGetOutput;
Packit 1244b8
    post(bind(&V4l2Decoder::getOutputJob, this));
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
void V4l2Decoder::inputReadyJob()
Packit 1244b8
{
Packit 1244b8
    PCHECK(m_thread.isCurrent());
Packit 1244b8
    if (m_state != kWaitInput) {
Packit 1244b8
        DEBUG("early out, state = %d", m_state);
Packit 1244b8
        return;
Packit 1244b8
    }
Packit 1244b8
    m_state = kGetInput;
Packit 1244b8
    getInputJob();
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
void V4l2Decoder::getOutputJob()
Packit 1244b8
{
Packit 1244b8
    PCHECK(m_thread.isCurrent());
Packit 1244b8
    PCHECK(bool(m_decoder));
Packit 1244b8
    if (m_state != kGetOutput && m_state != kFormatChanged) {
Packit 1244b8
        DEBUG("early out, state = %d, change = %d", m_state, kFormatChanged);
Packit 1244b8
        return;
Packit 1244b8
    }
Packit 1244b8
    while (m_output->isOutputReady()) {
Packit 1244b8
        SharedPtr<VideoFrame> frame = m_decoder->getOutput();
Packit 1244b8
        if (!frame) {
Packit 1244b8
            if (m_state == kFormatChanged && !m_output->isAllocationDone()) {
Packit 1244b8
                DEBUG("need relocation");
Packit 1244b8
                m_state = kWaitAllocation;
Packit 1244b8
                setCodecEvent();
Packit 1244b8
                return;
Packit 1244b8
            } else {
Packit 1244b8
                DEBUG("early out, no frame");
Packit 1244b8
                m_state = kGetInput;
Packit 1244b8
                post(bind(&V4l2Decoder::getInputJob, this));
Packit 1244b8
                return;
Packit 1244b8
            }
Packit 1244b8
        }
Packit 1244b8
        m_output->output(frame);
Packit 1244b8
    }
Packit 1244b8
    if (m_state == kGetOutput) {
Packit 1244b8
        m_state = kWaitOutput;
Packit 1244b8
    }
Packit 1244b8
    else {
Packit 1244b8
        ASSERT(m_state == kFormatChanged);
Packit 1244b8
        DEBUG("format change, wait more output buffers");
Packit 1244b8
    }
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
void V4l2Decoder::outputReadyJob()
Packit 1244b8
{
Packit 1244b8
    PCHECK(m_thread.isCurrent());
Packit 1244b8
    if (m_state == kWaitOutput) {
Packit 1244b8
        m_state = kGetOutput;
Packit 1244b8
        getOutputJob();
Packit 1244b8
    } else if (m_state == kFormatChanged) {
Packit 1244b8
        //try to drain output
Packit 1244b8
        getOutputJob();
Packit 1244b8
    }
Packit 1244b8
    else if (m_state == kWaitSurface) {
Packit 1244b8
        m_state = kGetInput;
Packit 1244b8
        getInputJob();
Packit 1244b8
    }
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
void V4l2Decoder::checkAllocationJob()
Packit 1244b8
{
Packit 1244b8
    PCHECK(m_thread.isCurrent());
Packit 1244b8
    if (m_state == kWaitAllocation) {
Packit 1244b8
        if (m_output->isAllocationDone()) {
Packit 1244b8
            m_state = kGetInput;
Packit 1244b8
            getInputJob();
Packit 1244b8
        }
Packit 1244b8
    }
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::onQueueBuffer(v4l2_buffer* buf)
Packit 1244b8
{
Packit 1244b8
    CHECK(buf);
Packit 1244b8
    uint32_t type = buf->type;
Packit 1244b8
    CHECK(type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
Packit 1244b8
        || type == (unsigned int)V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
Packit 1244b8
Packit 1244b8
    if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
Packit 1244b8
        CHECK(buf->memory == V4L2_MEMORY_MMAP);
Packit 1244b8
        CHECK(buf->length == 1);
Packit 1244b8
        CHECK(buf->index < m_inputFrames.size());
Packit 1244b8
        DEBUG("queue input size = %d", buf->m.planes[0].bytesused);
Packit 1244b8
Packit 1244b8
        VideoDecodeBuffer& inputBuffer = m_inputFrames[buf->index];
Packit 1244b8
        inputBuffer.size = buf->m.planes[0].bytesused; // one plane only
Packit 1244b8
        if (!inputBuffer.size) // EOS
Packit 1244b8
            inputBuffer.data = NULL;
Packit 1244b8
        TIMEVAL_TO_INT64(inputBuffer.timeStamp, buf->timestamp);
Packit 1244b8
Packit 1244b8
        m_in.queue(buf->index);
Packit 1244b8
        post(bind(&V4l2Decoder::inputReadyJob, this));
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
    DEBUG("queue output index = %d", buf->index);
Packit 1244b8
Packit 1244b8
    m_output->queue(buf);
Packit 1244b8
    post(bind(&V4l2Decoder::outputReadyJob, this));
Packit 1244b8
    return 0;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::onDequeBuffer(v4l2_buffer* buf)
Packit 1244b8
{
Packit 1244b8
    CHECK(buf);
Packit 1244b8
    uint32_t type = buf->type;
Packit 1244b8
    CHECK(type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
Packit 1244b8
        || type == (unsigned int)V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
Packit 1244b8
    if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
Packit 1244b8
        CHECK(m_inputOn);
Packit 1244b8
        uint32_t index;
Packit 1244b8
        if (!m_in.deque(index)) {
Packit 1244b8
            ERROR_RETURN(EAGAIN);
Packit 1244b8
        }
Packit 1244b8
        buf->index = index;
Packit 1244b8
        DEBUG("dequeue input index = %d", buf->index);
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    int32_t ret = m_output->deque(buf);
Packit 1244b8
    if (!ret)
Packit 1244b8
        DEBUG("dequeue output index = %d", buf->index);
Packit 1244b8
Packit 1244b8
    return ret;
Packit 1244b8
}
Packit 1244b8
int32_t V4l2Decoder::onStreamOn(uint32_t type)
Packit 1244b8
{
Packit 1244b8
    CHECK(type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
Packit 1244b8
        || type == (unsigned int)V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
Packit 1244b8
Packit 1244b8
    if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
Packit 1244b8
Packit 1244b8
        if (!m_display) {
Packit 1244b8
            m_display = VaapiDisplay::create(m_nativeDisplay);
Packit 1244b8
            CHECK(bool(m_display));
Packit 1244b8
        }
Packit 1244b8
Packit 1244b8
        CHECK(!m_inputOn);
Packit 1244b8
        m_inputOn = true;
Packit 1244b8
        CHECK(m_thread.start());
Packit 1244b8
Packit 1244b8
        post(bind(&V4l2Decoder::startDecoderJob, this));
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
    CHECK(!m_outputOn);
Packit 1244b8
    m_outputOn = true;
Packit 1244b8
    post(bind(&V4l2Decoder::checkAllocationJob, this));
Packit 1244b8
    return 0;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
void V4l2Decoder::flushDecoderJob()
Packit 1244b8
{
Packit 1244b8
    if (m_decoder)
Packit 1244b8
        m_decoder->flush();
Packit 1244b8
    m_output->flush();
Packit 1244b8
    m_state = kStopped;
Packit 1244b8
}
Packit 1244b8
int32_t V4l2Decoder::onStreamOff(uint32_t type)
Packit 1244b8
{
Packit 1244b8
    CHECK(type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
Packit 1244b8
        || type == (unsigned int)V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
Packit 1244b8
    if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
Packit 1244b8
        if (m_inputOn) {
Packit 1244b8
            post(bind(&V4l2Decoder::flushDecoderJob, this));
Packit 1244b8
            m_thread.stop();
Packit 1244b8
            m_in.clearPipe();
Packit 1244b8
            m_inputOn = false;
Packit 1244b8
            m_state = kUnStarted;
Packit 1244b8
        }
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
    m_outputOn = false;
Packit 1244b8
    m_output->streamOff();
Packit 1244b8
    m_out.clearPipe();
Packit 1244b8
Packit 1244b8
    return 0;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::requestInputBuffers(uint32_t count)
Packit 1244b8
{
Packit 1244b8
    CHECK(m_thread.isCurrent());
Packit 1244b8
Packit 1244b8
    uint32_t size = m_inputFormat.fmt.pix_mp.plane_fmt[0].sizeimage;
Packit 1244b8
Packit 1244b8
    m_inputFrames.resize(count);
Packit 1244b8
    if (count) {
Packit 1244b8
        //this means we really need allocate space
Packit 1244b8
        if (!size)
Packit 1244b8
            m_inputFormat.fmt.pix_mp.plane_fmt[0].sizeimage = kDefaultInputSize;
Packit 1244b8
    }
Packit 1244b8
    m_inputSpace.resize(count * size);
Packit 1244b8
    m_inputFrames.resize(count);
Packit 1244b8
    for (uint32_t i = 0; i < count; i++) {
Packit 1244b8
        VideoDecodeBuffer& frame = m_inputFrames[i];
Packit 1244b8
        memset(&frame, 0, sizeof(frame));
Packit 1244b8
        frame.data = &m_inputSpace[i * size];
Packit 1244b8
    }
Packit 1244b8
    return 0;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::onRequestBuffers(const v4l2_requestbuffers* req)
Packit 1244b8
{
Packit 1244b8
    CHECK(req);
Packit 1244b8
    uint32_t type = req->type;
Packit 1244b8
    uint32_t count = req->count;
Packit 1244b8
    CHECK(type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
Packit 1244b8
        || type == (unsigned int)V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
Packit 1244b8
    if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
Packit 1244b8
        CHECK(req->memory == V4L2_MEMORY_MMAP);
Packit 1244b8
        return sendTask(bind(&V4l2Decoder::requestInputBuffers, this, count));
Packit 1244b8
    }
Packit 1244b8
    CHECK(req->memory == V4L2_MEMORY_MMAP);
Packit 1244b8
    return sendTask(bind(&Output::requestBuffers, m_output, count));
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::onSetFormat(v4l2_format* format)
Packit 1244b8
{
Packit 1244b8
    CHECK(format);
Packit 1244b8
    CHECK(!m_inputOn && !m_outputOn);
Packit 1244b8
Packit 1244b8
    if (format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
Packit 1244b8
        uint32_t size;
Packit 1244b8
        memcpy(&size, format->fmt.raw_data, sizeof(uint32_t));
Packit 1244b8
Packit 1244b8
        CHECK(size <= (sizeof(format->fmt.raw_data) - sizeof(uint32_t)));
Packit 1244b8
Packit 1244b8
        uint8_t* ptr = format->fmt.raw_data;
Packit 1244b8
        ptr += sizeof(uint32_t);
Packit 1244b8
        m_codecData.assign(ptr, ptr + size);
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    if (format->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
Packit 1244b8
        CHECK(format->fmt.pix_mp.num_planes == 1);
Packit 1244b8
        CHECK(format->fmt.pix_mp.plane_fmt[0].sizeimage);
Packit 1244b8
        memcpy(&m_inputFormat, format, sizeof(*format));
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    ERROR("unknow type: %d of setting format VIDIOC_S_FMT", format->type);
Packit 1244b8
    return -1;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::onQueryBuffer(v4l2_buffer* buf)
Packit 1244b8
{
Packit 1244b8
    CHECK(buf);
Packit 1244b8
    CHECK(buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
Packit 1244b8
    CHECK(buf->memory == V4L2_MEMORY_MMAP);
Packit 1244b8
    CHECK(m_inputFormat.fmt.pix_mp.num_planes == 1);
Packit 1244b8
Packit 1244b8
    uint32_t idx = buf->index;
Packit 1244b8
    uint32_t size = m_inputFormat.fmt.pix_mp.plane_fmt[0].sizeimage;
Packit 1244b8
    CHECK(size);
Packit 1244b8
    buf->m.planes[0].length = size;
Packit 1244b8
    buf->m.planes[0].m.mem_offset = size * idx;
Packit 1244b8
Packit 1244b8
    return 0;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::onSubscribeEvent(v4l2_event_subscription* sub)
Packit 1244b8
{
Packit 1244b8
    CHECK(sub->type == V4L2_EVENT_RESOLUTION_CHANGE);
Packit 1244b8
    /// resolution change event is must, we always do so
Packit 1244b8
    return 0;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::onDequeEvent(v4l2_event* ev)
Packit 1244b8
{
Packit 1244b8
    CHECK(ev);
Packit 1244b8
    if (hasCodecEvent()) {
Packit 1244b8
        ev->type = V4L2_EVENT_RESOLUTION_CHANGE;
Packit 1244b8
        clearCodecEvent();
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
    return -1;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::onGetFormat(v4l2_format* format)
Packit 1244b8
{
Packit 1244b8
    CHECK(format && format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
Packit 1244b8
    CHECK(m_inputOn);
Packit 1244b8
Packit 1244b8
    SEND(bind(&V4l2Decoder::getFormatTask, this, format));
Packit 1244b8
Packit 1244b8
    //save it.
Packit 1244b8
    m_outputFormat = *format;
Packit 1244b8
    return 0;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::onGetCtrl(v4l2_control* ctrl)
Packit 1244b8
{
Packit 1244b8
    CHECK(ctrl);
Packit 1244b8
    CHECK(ctrl->id == V4L2_CID_MIN_BUFFERS_FOR_CAPTURE);
Packit 1244b8
Packit 1244b8
    SEND(bind(&V4l2Decoder::getCtrlTask, this, ctrl));
Packit 1244b8
    return 0;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::onEnumFormat(v4l2_fmtdesc* fmtdesc)
Packit 1244b8
{
Packit 1244b8
    uint32_t type = fmtdesc->type;
Packit 1244b8
    uint32_t index = fmtdesc->index;
Packit 1244b8
    if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
Packit 1244b8
        CHECK(!index);
Packit 1244b8
        fmtdesc->pixelformat = V4L2_PIX_FMT_NV12M;
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
Packit 1244b8
        //TODO: query from libyami when capablity api is ready.
Packit 1244b8
        const static uint32_t supported[] = {
Packit 1244b8
            V4L2_PIX_FMT_H264,
Packit 1244b8
            V4L2_PIX_FMT_VC1,
Packit 1244b8
            V4L2_PIX_FMT_MPEG2,
Packit 1244b8
            V4L2_PIX_FMT_JPEG,
Packit 1244b8
            V4L2_PIX_FMT_VP8,
Packit 1244b8
            V4L2_PIX_FMT_VP9,
Packit 1244b8
        };
Packit 1244b8
        CHECK(index < N_ELEMENTS(supported));
Packit 1244b8
        fmtdesc->pixelformat = supported[index];
Packit 1244b8
        return 0;
Packit 1244b8
    }
Packit 1244b8
    return -1;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::onGetCrop(v4l2_crop* crop)
Packit 1244b8
{
Packit 1244b8
    CHECK(crop->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
Packit 1244b8
    ASSERT(0);
Packit 1244b8
    return 0;
Packit 1244b8
    //return sendTask(m_decoderThread, std::bind(getCrop,crop)));
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::onCreateBuffers(v4l2_create_buffers* req)
Packit 1244b8
{
Packit 1244b8
    return m_output->createBuffers(req);
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
void V4l2Decoder::startDecoderJob()
Packit 1244b8
{
Packit 1244b8
    PCHECK(m_state == kUnStarted);
Packit 1244b8
Packit 1244b8
    if (m_decoder) {
Packit 1244b8
        m_state = kGetInput;
Packit 1244b8
        getInputJob();
Packit 1244b8
        return;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    const char* mime = mimeFromV4l2PixelFormat(m_inputFormat.fmt.pix_mp.pixelformat);
Packit 1244b8
Packit 1244b8
    m_decoder.reset(
Packit 1244b8
        createVideoDecoder(mime), releaseVideoDecoder);
Packit 1244b8
    if (!m_decoder) {
Packit 1244b8
        ERROR("create display failed");
Packit 1244b8
        m_display.reset();
Packit 1244b8
        return;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    m_output->setDecodeAllocator(m_decoder);
Packit 1244b8
Packit 1244b8
    YamiStatus status;
Packit 1244b8
    VideoConfigBuffer config;
Packit 1244b8
    memset(&config, 0, sizeof(config));
Packit 1244b8
    config.width = m_inputFormat.fmt.pix_mp.width;
Packit 1244b8
    config.height = m_inputFormat.fmt.pix_mp.height;
Packit 1244b8
    config.data = &m_codecData[0];
Packit 1244b8
    config.size = m_codecData.size();
Packit 1244b8
    if (m_isThumbnailMode) {
Packit 1244b8
        DEBUG("enable lowlatency mode");
Packit 1244b8
        config.enableLowLatency = true;
Packit 1244b8
    }
Packit 1244b8
Packit 1244b8
    status = m_decoder->start(&config);
Packit 1244b8
    if (status != YAMI_SUCCESS) {
Packit 1244b8
        ERROR("start decoder failed");
Packit 1244b8
        return;
Packit 1244b8
    }
Packit 1244b8
    const VideoFormatInfo* outFormat = m_decoder->getFormatInfo();
Packit 1244b8
    if (outFormat && outFormat->width && outFormat->height) {
Packit 1244b8
        //we got format now, we are waiting for surface allocation.
Packit 1244b8
        m_state = kWaitAllocation;
Packit 1244b8
    }
Packit 1244b8
    else {
Packit 1244b8
        m_state = kGetInput;
Packit 1244b8
        getInputJob();
Packit 1244b8
    }
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
void V4l2Decoder::post(Job job)
Packit 1244b8
{
Packit 1244b8
    m_thread.post(job);
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
static void taskWrapper(int32_t& ret, Task& task)
Packit 1244b8
{
Packit 1244b8
    ret = task();
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::sendTask(Task task)
Packit 1244b8
{
Packit 1244b8
    //if send fail, we will return EINVAL;
Packit 1244b8
    int32_t ret = EINVAL;
Packit 1244b8
    m_thread.send(bind(taskWrapper, ref(ret), ref(task)));
Packit 1244b8
    return ret;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::getFormatTask(v4l2_format* format)
Packit 1244b8
{
Packit 1244b8
    CHECK(m_thread.isCurrent());
Packit 1244b8
    CHECK(format);
Packit 1244b8
    CHECK(bool(m_decoder));
Packit 1244b8
Packit 1244b8
    const VideoFormatInfo* outFormat = m_decoder->getFormatInfo();
Packit 1244b8
    if (!outFormat)
Packit 1244b8
        return EINVAL;
Packit 1244b8
Packit 1244b8
    memset(format, 0, sizeof(*format));
Packit 1244b8
    format->fmt.pix_mp.width = outFormat->width;
Packit 1244b8
    format->fmt.pix_mp.height = outFormat->height;
Packit 1244b8
Packit 1244b8
    //TODO: add support for P010
Packit 1244b8
    format->fmt.pix_mp.num_planes = 2; //for NV12
Packit 1244b8
    format->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M;
Packit 1244b8
Packit 1244b8
    //we can't fill format->fmt.pix_mp.plane_fmt[0].bytesperline
Packit 1244b8
    //yet, since we did not creat surface.
Packit 1244b8
    return 0;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::getCtrlTask(v4l2_control* ctrl)
Packit 1244b8
{
Packit 1244b8
    CHECK(m_thread.isCurrent());
Packit 1244b8
    CHECK(ctrl);
Packit 1244b8
    CHECK(bool(m_decoder));
Packit 1244b8
Packit 1244b8
    const VideoFormatInfo* outFormat = m_decoder->getFormatInfo();
Packit 1244b8
    if (!outFormat)
Packit 1244b8
        return EINVAL;
Packit 1244b8
Packit 1244b8
    if (m_isThumbnailMode) {
Packit 1244b8
        ctrl->value = 1;
Packit 1244b8
    } else {
Packit 1244b8
        //TODO: query this from outFormat;
Packit 1244b8
        ctrl->value = outFormat->surfaceNumber;
Packit 1244b8
    }
Packit 1244b8
    return 0;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
#define MCHECK(cond)                     \
Packit 1244b8
    do {                                 \
Packit 1244b8
        if (!(cond)) {                   \
Packit 1244b8
            ERROR("%s is false", #cond); \
Packit 1244b8
            return NULL;                 \
Packit 1244b8
        }                                \
Packit 1244b8
    } while (0)
Packit 1244b8
Packit 1244b8
void* V4l2Decoder::mmap(void* addr, size_t length,
Packit 1244b8
    int prot, int flags, unsigned int offset)
Packit 1244b8
{
Packit 1244b8
    MCHECK(prot == (PROT_READ | PROT_WRITE));
Packit 1244b8
    MCHECK(flags == MAP_SHARED);
Packit 1244b8
    uint32_t size = m_inputFormat.fmt.pix_mp.plane_fmt[0].sizeimage;
Packit 1244b8
    MCHECK(size);
Packit 1244b8
    MCHECK(length == size);
Packit 1244b8
    MCHECK(!(offset % size));
Packit 1244b8
    MCHECK(offset / size < m_inputFrames.size());
Packit 1244b8
    MCHECK(offset + size <= m_inputSpace.size());
Packit 1244b8
Packit 1244b8
    return &m_inputSpace[offset];
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
#undef MCHECK
Packit 1244b8
Packit 1244b8
int32_t V4l2Decoder::setFrameMemoryType(VideoDataMemoryType memory_type)
Packit 1244b8
{
Packit 1244b8
    if (memory_type == VIDEO_DATA_MEMORY_TYPE_EXTERNAL_DMA_BUF)
Packit 1244b8
        m_output.reset(new ExternalDmaBufOutput(this));
Packit 1244b8
#ifdef __ENABLE_EGL__
Packit 1244b8
    if (memory_type == VIDEO_DATA_MEMORY_TYPE_DRM_NAME
Packit 1244b8
        || memory_type == VIDEO_DATA_MEMORY_TYPE_DMA_BUF)
Packit 1244b8
        m_output.reset(new EglOutput(this, memory_type));
Packit 1244b8
#endif
Packit 1244b8
    if (!m_output) {
Packit 1244b8
        ERROR("unspported memory type %d", memory_type);
Packit 1244b8
        return -1;
Packit 1244b8
    }
Packit 1244b8
    return 0;
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
void V4l2Decoder::flush()
Packit 1244b8
{
Packit 1244b8
}
Packit 1244b8
Packit 1244b8
#ifdef __ENABLE_EGL__
Packit 1244b8
int32_t V4l2Decoder::useEglImage(EGLDisplay eglDisplay, EGLContext eglContext, uint32_t bufferIndex, void* eglImage)
Packit 1244b8
{
Packit 1244b8
    SharedPtr<EglOutput> output = DynamicPointerCast<EglOutput>(m_output);
Packit 1244b8
    if (!output) {
Packit 1244b8
        ERROR("can't cast m_output to EglOutput");
Packit 1244b8
        return -1;
Packit 1244b8
    }
Packit 1244b8
    return output->useEglImage(eglDisplay, eglContext, bufferIndex, eglImage);
Packit 1244b8
}
Packit 1244b8
#endif