<commit_before>/*
 *  decodeoutput.cpp - decode outputs
 *
 *  Copyright (C) 2011-2014 Intel Corporation
 *    Author: <NAME><<EMAIL>>
 *            <NAME><<EMAIL>>
 *            <NAME><<EMAIL>>
 *            <NAME><<EMAIL>>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2.1
 *  of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301 USA
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "decodeoutput.h"
#include "common/log.h"
#include "common/utils.h"
#include "vaapi/vaapiutils.h"
#include "vaapi/vaapiimageutils.h"

#if __ENABLE_MD5__
#include <openssl/md5.h>
#endif

#ifdef __ENABLE_X11__
#include <X11/Xlib.h>
#include <va/va_x11.h>
#endif

#ifdef __ENABLE_TESTS_GLES__
#include "./egl/gles2_help.h"
#include "egl/egl_util.h"
#include "egl/egl_vaapi_image.h"
#endif

#include <va/va.h>
#include <va/va_drmcommon.h>
#include <vector>
#include <sys/stat.h>
#include <sstream>
#include <stdio.h>
#include <assert.h>

using namespace YamiMediaCodec;
using std::vector;

bool DecodeOutput::init()
{
    m_nativeDisplay.reset(new NativeDisplay);
    m_nativeDisplay->type = NATIVE_DISPLAY_VA;
    m_nativeDisplay->handle = (intptr_t)*m_vaDisplay;
    if (!m_vaDisplay || !m_nativeDisplay) {
        ERROR("init display error");
        return false;
    }
    return true;
}

SharedPtr<NativeDisplay> DecodeOutput::nativeDisplay()
{
    return m_nativeDisplay;
}

bool DecodeOutput::setVideoSize(uint32_t with, uint32_t height)
{
    m_width = with;
    m_height = height;
    return true;
}

class DecodeOutputNull : public DecodeOutput {
public:
    DecodeOutputNull() {}
    ~DecodeOutputNull() {}
    bool init();
    bool output(const SharedPtr<VideoFrame>& frame);
};

bool DecodeOutputNull::init()
{
    m_vaDisplay = createVADisplay();
    if (!m_vaDisplay)
        return false;
    return DecodeOutput::init();
}

bool DecodeOutputNull::output(const SharedPtr<VideoFrame>& frame)
{
    VAStatus status = vaSyncSurface(*m_vaDisplay, (VASurfaceID)frame->surface);
    return checkVaapiStatus(status, "vaSyncSurface");
}

class ColorConvert {
public:
    ColorConvert(const SharedPtr<VADisplay>& display, uint32_t fourcc)
        : m_width(0)
        , m_height(0)
        , m_destFourcc(fourcc)
        , m_display(display)

    {
        m_allocator.reset(new PooledFrameAllocator(m_display, 3));
    }
    SharedPtr<VideoFrame> convert(const SharedPtr<VideoFrame>& src)
    {

        SharedPtr<VideoFrame> dest;
        uint32_t width = src->crop.width;
        uint32_t height = src->crop.height;

        if (!init(width, height)) {
            return dest;
        }
        dest = m_allocator->alloc();
        YamiStatus status = m_vpp->process(src, dest);
        if (status != YAMI_SUCCESS) {
            ERROR("vpp process return %d", status);
            dest.reset();
        }
        return dest;
    }
    //opensource libva driver can't makesure nv12 to i420 is bit match
    //so we need software converter.
    bool convert(vector<uint8_t>& dest, const SharedPtr<VideoFrame>& src)
    {
        dest.clear();
        if (src->fourcc != YAMI_FOURCC_NV12
            || m_destFourcc != YAMI_FOURCC('I', '4', '2', '0')) {
            ERROR("only support nv12 to i420 convert");
            return false;
        }
        VAImage image;
        uint8_t* p = mapSurfaceToImage(*m_display, src->surface, image);
        if (!p) {
            ERROR("failed to map VAImage");
            return false;
        }
        //TODO: hanld no zero x, y for crop;
        ASSERT("can't support no zero x,y for crop" && !src->crop.x && !src->crop.y);
        uint32_t width = src->crop.width;
        uint32_t height = src->crop.height;
        copyY(dest, p, image.offsets[0], width, height, image.pitches[0]);
        copyUV(dest, p, image.offsets[1], width, height, image.pitches[1]);
        copyUV(dest, p, image.offsets[1] + 1, width, height, image.pitches[1]);
        unmapImage(*m_display, image);
        return true;
    }

private:
    static void copyY(std::vector<uint8_t>& v, uint8_t* data, uint32_t offset, uint32_t width,
        uint32_t height, uint32_t pitch)
    {
        data += offset;
        for (uint32_t h = 0; h < height; h++) {
            v.insert(v.end(), data, data + width);
            data += pitch;
        }

    }

    static void copyUV(std::vector<uint8_t>& v, uint8_t* data, uint32_t offset, uint32_t width,
        uint32_t height, uint32_t pitch)
    {
        data += offset;
        for (uint32_t h = 0; h < height / 2; h++) {
            uint8_t* start = data;
            uint8_t* end = data + width;
            while (start < end) {
                v.push_back(*start);
                start += 2 ;
            }
            data += pitch;
        }

    }

    bool init(uint32_t width, uint32_t height)
    {
        if (m_width != width || m_height != height) {
            m_width = width;
            m_height = height;
            if (!m_allocator->setFormat(m_destFourcc, width, height)) {
                fprintf(stderr, "m_allocator setFormat failed\n");
                return false;
            }
        }
        if (!m_vpp) {
            m_vpp.reset(createVideoPostProcess(YAMI_VPP_SCALER), releaseVideoPostProcess);
            NativeDisplay nativeDisplay;
            nativeDisplay.type = NATIVE_DISPLAY_VA;
            nativeDisplay.handle = (intptr_t)*m_display;
            m_vpp->setNativeDisplay(nativeDisplay);
        }
        return true;
    }
<commit_msg>tests/decode: fix bug, NV12 to I420<commit_after>/*
 *  decodeoutput.cpp - decode outputs
 *
 *  Copyright (C) 2011-2014 Intel Corporation
 *    Author: <NAME><<EMAIL>>
 *            <NAME><<EMAIL>>
 *            <NAME><<EMAIL>>
 *            <NAME><<EMAIL>>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2.1
 *  of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301 USA
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "decodeoutput.h"
#include "common/log.h"
#include "common/utils.h"
#include "vaapi/vaapiutils.h"
#include "vaapi/vaapiimageutils.h"

#if __ENABLE_MD5__
#include <openssl/md5.h>
#endif

#ifdef __ENABLE_X11__
#include <X11/Xlib.h>
#include <va/va_x11.h>
#endif

#ifdef __ENABLE_TESTS_GLES__
#include "./egl/gles2_help.h"
#include "egl/egl_util.h"
#include "egl/egl_vaapi_image.h"
#endif

#include <va/va.h>
#include <va/va_drmcommon.h>
#include <vector>
#include <sys/stat.h>
#include <sstream>
#include <stdio.h>
#include <assert.h>

using namespace YamiMediaCodec;
using std::vector;

bool DecodeOutput::init()
{
    m_nativeDisplay.reset(new NativeDisplay);
    m_nativeDisplay->type = NATIVE_DISPLAY_VA;
    m_nativeDisplay->handle = (intptr_t)*m_vaDisplay;
    if (!m_vaDisplay || !m_nativeDisplay) {
        ERROR("init display error");
        return false;
    }
    return true;
}

SharedPtr<NativeDisplay> DecodeOutput::nativeDisplay()
{
    return m_nativeDisplay;
}

bool DecodeOutput::setVideoSize(uint32_t with, uint32_t height)
{
    m_width = with;
    m_height = height;
    return true;
}

class DecodeOutputNull : public DecodeOutput {
public:
    DecodeOutputNull() {}
    ~DecodeOutputNull() {}
    bool init();
    bool output(const SharedPtr<VideoFrame>& frame);
};

bool DecodeOutputNull::init()
{
    m_vaDisplay = createVADisplay();
    if (!m_vaDisplay)
        return false;
    return DecodeOutput::init();
}

bool DecodeOutputNull::output(const SharedPtr<VideoFrame>& frame)
{
    VAStatus status = vaSyncSurface(*m_vaDisplay, (VASurfaceID)frame->surface);
    return checkVaapiStatus(status, "vaSyncSurface");
}

class ColorConvert {
public:
    ColorConvert(const SharedPtr<VADisplay>& display, uint32_t fourcc)
        : m_width(0)
        , m_height(0)
        , m_destFourcc(fourcc)
        , m_display(display)

    {
        m_allocator.reset(new PooledFrameAllocator(m_display, 3));
    }
    SharedPtr<VideoFrame> convert(const SharedPtr<VideoFrame>& src)
    {

        SharedPtr<VideoFrame> dest;
        uint32_t width = src->crop.width;
        uint32_t height = src->crop.height;

        if (!init(width, height)) {
            return dest;
        }
        dest = m_allocator->alloc();
        YamiStatus status = m_vpp->process(src, dest);
        if (status != YAMI_SUCCESS) {
            ERROR("vpp process return %d", status);
            dest.reset();
        }
        return dest;
    }
    //opensource libva driver can't makesure nv12 to i420 is bit match
    //so we need software converter.
    bool convert(vector<uint8_t>& dest, const SharedPtr<VideoFrame>& src)
    {
        dest.clear();
        if (src->fourcc != YAMI_FOURCC_NV12
            || m_destFourcc != YAMI_FOURCC('I', '4', '2', '0')) {
            ERROR("only support nv12 to i420 convert");
            return false;
        }
        VAImage image;
        uint8_t* p = mapSurfaceToImage(*m_display, src->surface, image);
        if (!p) {
            ERROR("failed to map VAImage");
            return false;
        }
        //TODO: hanld no zero x, y for crop;
        ASSERT("can't support no zero x,y for crop" && !src->crop.x && !src->crop.y);

        uint32_t planes, width[3], height[3];
        if (!getPlaneResolution(src->fourcc, src->crop.width, src->crop.height, width, height, planes)) {
            ERROR("get plane reoslution failed");
            return false;
        }

        copyY(dest, p, image.offsets[0], width[0], height[0], image.pitches[0]);
        copyUV(dest, p, image.offsets[1], width[1], height[1], image.pitches[1]);
        copyUV(dest, p, image.offsets[1] + 1, width[1], height[1], image.pitches[1]);
        unmapImage(*m_display, image);
        return true;
    }

private:
    static void copyY(std::vector<uint8_t>& v, uint8_t* data, uint32_t offset, uint32_t width,
        uint32_t height, uint32_t pitch)
    {
        data += offset;
        for (uint32_t h = 0; h < height; h++) {
            v.insert(v.end(), data, data + width);
            data += pitch;
        }

    }

    static void copyUV(std::vector<uint8_t>& v, uint8_t* data, uint32_t offset, uint32_t width,
        uint32_t height, uint32_t pitch)
    {
        data += offset;
        for (uint32_t h = 0; h < height; h++) {
            uint8_t* start = data;
            uint8_t* end = data + width;
            while (start < end) {
                v.push_back(*start);
                start += 2 ;
            }
            data += pitch;
        }

    }

    bool init(uint32_t width, uint32_t height)
    {
        if (m_width != width || m_height != height) {
            m_width = width;
            m_height = height;
            if (!m_allocator->setFormat(m_destFourcc, width, height)) {
                fprintf(stderr, "m_allocator setFormat failed\n");
                return false;
            }
        }
        if (!m_vpp) {
            m_vpp.reset(createVideoPostProcess(YAMI_VPP_SCALER), releaseVideoPostProcess);
            NativeDisplay nativeDisplay;
            nativeDisplay.type = NATIVE_DISPLAY_VA;
            nativeDisplay.handle = (intptr_t)*m_display;
            m_vpp->setNativeDisplay(nativeDisplay);
        }
        return true;
    }

{'fraction_non_alphanumeric': 0.11804098757463288, 'fraction_numerical': 0.017750524447313214, 'mean_word_length': 2.5948375870069604, 'pattern_counts': {'":': 0, '<': 75, '<?xml version=': 0, '>': 100, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3791286', 'n_tokens_mistral': 4155, 'n_tokens_neox': 3999, 'n_words': 1029}