/*
* Copyright (c) 2011 Intel Corporation. All Rights Reserved.
* Copyright (c) Imagination Technologies Limited, UK
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Waldo Bastian <waldo.bastian@intel.com>
*
*/
#include <sys/types.h>
#include "psb_buffer.h"
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <wsbm/wsbm_manager.h>
#ifdef ANDROID
#ifdef BAYTRAIL
#include <linux/vxd_drm.h>
#else
#include <drm/ttm/ttm_placement.h>
#include <linux/psb_drm.h>
#endif
#else
#include <psb_drm.h>
#endif
#include "psb_def.h"
#include "psb_drv_debug.h"
#include "tng_cmdbuf.h"
#ifndef BAYTRAIL
#include <pnw_cmdbuf.h>
#include "pnw_jpeg.h"
#include "pnw_H264ES.h"
#include "tng_jpegES.h"
#endif
#include "vsp_fw.h"
/*
* Create buffer
*/
VAStatus psb_buffer_create(psb_driver_data_p driver_data,
unsigned int size,
psb_buffer_type_t type,
psb_buffer_p buf
)
{
VAStatus vaStatus = VA_STATUS_SUCCESS;
int allignment;
uint32_t placement;
int ret;
/* reset rar_handle to NULL */
buf->rar_handle = 0;
buf->buffer_ofs = 0;
buf->type = type;
buf->driver_data = driver_data; /* only for RAR buffers */
buf->size = size;
/* TODO: Mask values are a guess */
switch (type) {
case psb_bt_cpu_vpu:
allignment = 1;
placement = DRM_PSB_FLAG_MEM_MMU;
break;
case psb_bt_cpu_vpu_shared:
allignment = 1;
placement = DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_SHARED;
break;
case psb_bt_surface:
allignment = 0;
placement = DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_SHARED;
if (IS_CTP(driver_data)) /* CTP support cache snoop */
placement |= WSBM_PL_FLAG_CACHED;
break;
case psb_bt_surface_tt:
allignment = 0;
placement = WSBM_PL_FLAG_TT | WSBM_PL_FLAG_NO_EVICT | WSBM_PL_FLAG_SHARED;
break;
#ifdef PSBVIDEO_MSVDX_DEC_TILING
case psb_bt_surface_tiling:
drv_debug_msg(VIDEO_DEBUG_GENERAL, "Allocate tiled surface from TT heap\n");
placement = WSBM_PL_FLAG_TT | WSBM_PL_FLAG_SHARED;
allignment = 2048 * 16; /* Tiled row aligned */
break;
case psb_bt_mmu_tiling:
placement = DRM_PSB_FLAG_MEM_MMU_TILING | WSBM_PL_FLAG_SHARED;
allignment = 2048 * 16; /* Tiled row aligned */
break;
#endif
case psb_bt_cpu_vpu_cached:
allignment = 1;
placement = DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_CACHED;
break;
case psb_bt_vpu_only:
allignment = 1;
placement = DRM_PSB_FLAG_MEM_MMU;
break;
case psb_bt_cpu_only:
allignment = 1;
placement = WSBM_PL_FLAG_SYSTEM | WSBM_PL_FLAG_CACHED;
break;
#if PSB_MFLD_DUMMY_CODE
case psb_bt_camera:
allignment = 1;
placement = WSBM_PL_FLAG_SHARED;
break;
#endif
#ifdef ANDROID
#ifndef BAYTRAIL
case psb_bt_imr:
allignment = 1;
placement = TTM_PL_FLAG_IMR | WSBM_PL_FLAG_SHARED;
break;
#endif
#endif
default:
vaStatus = VA_STATUS_ERROR_UNKNOWN;
DEBUG_FAILURE;
return vaStatus;
}
ret = LOCK_HARDWARE(driver_data);
if (ret) {
UNLOCK_HARDWARE(driver_data);
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
DEBUG_FAILURE_RET;
return vaStatus;
}
#ifdef VA_EMULATOR
placement |= WSBM_PL_FLAG_SHARED;
#endif
#ifndef ANDROID
if(!(placement & WSBM_PL_FLAG_SYSTEM)) {
//drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: buffer->pl_flags 0x%08x\n", __func__, placement);
placement &= ~WSBM_PL_MASK_MEM;
placement &= ~WSBM_PL_FLAG_NO_EVICT;
placement |= TTM_PL_FLAG_VRAM;
//drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: repleace buffer->pl_flags 0x%08x\n", __func__, placement);
}
#endif
#ifdef MSVDX_VA_EMULATOR
placement |= WSBM_PL_FLAG_SHARED;
#endif
if(allignment < 4096)
allignment = 4096; /* temporily more safe */
//drv_debug_msg(VIDEO_DEBUG_ERROR, "FIXME: should use geetpagesize() ?\n");
ret = wsbmGenBuffers(driver_data->main_pool, 1, &buf->drm_buf,
allignment, placement);
if (!buf->drm_buf) {
drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to gen wsbm buffers\n");
UNLOCK_HARDWARE(driver_data);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
/* here use the placement when gen buffer setted */
ret = wsbmBOData(buf->drm_buf, size, NULL, NULL, 0);
UNLOCK_HARDWARE(driver_data);
if (ret) {
drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to alloc wsbm buffers\n");
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
if (placement & WSBM_PL_FLAG_TT)
drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create BO with TT placement (%d byte),BO GPU offset hint=0x%08x\n",
size, wsbmBOOffsetHint(buf->drm_buf));
buf->pl_flags = placement;
buf->status = psb_bs_ready;
buf->wsbm_synccpu_flag = 0;
return VA_STATUS_SUCCESS;
}
/*
* Create buffer
*/
VAStatus psb_buffer_create_from_ub(psb_driver_data_p driver_data,
unsigned int size,
psb_buffer_type_t type,
psb_buffer_p buf,
void * vaddr,
int fd,
unsigned int flags
)
{
VAStatus vaStatus = VA_STATUS_SUCCESS;
int allignment;
uint32_t placement;
int ret;
/* reset rar_handle to NULL */
buf->rar_handle = 0;
buf->buffer_ofs = 0;
buf->type = type;
buf->driver_data = driver_data; /* only for RAR buffers */
buf->user_ptr = vaddr;
buf->fd = fd;
/* Xvideo will share surface buffer, set SHARED flag
*/
placement = DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_SHARED ;
ret = LOCK_HARDWARE(driver_data);
if (ret) {
UNLOCK_HARDWARE(driver_data);
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
DEBUG_FAILURE_RET;
return vaStatus;
}
allignment = 4096; /* temporily more safe */
#ifdef PSBVIDEO_MSVDX_DEC_TILING
if (type == psb_bt_mmu_tiling) {
placement = DRM_PSB_FLAG_MEM_MMU_TILING | WSBM_PL_FLAG_SHARED ;
allignment = 2048 * 16; /* Tiled row aligned */
}
#endif
if (flags & PSB_USER_BUFFER_WC)
placement |= WSBM_PL_FLAG_WC;
else if (flags & PSB_USER_BUFFER_UNCACHED)
placement |= WSBM_PL_FLAG_UNCACHED;
else
placement |= WSBM_PL_FLAG_CACHED;
//drv_debug_msg(VIDEO_DEBUG_ERROR, "FIXME: should use geetpagesize() ?\n");
ret = wsbmGenBuffers(driver_data->main_pool, 1, &buf->drm_buf,
allignment, placement);
if (!buf->drm_buf) {
drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to gen wsbm buffers\n");
UNLOCK_HARDWARE(driver_data);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
/* here use the placement when gen buffer setted */
drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create BO from user buffer %p, size=%d, fd = %d\n", vaddr, size, fd);
ret = wsbmBODataUB(buf->drm_buf, size, NULL, NULL, 0, vaddr, fd);
if (ret) {
drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to alloc wsbm buffers, buf->drm_buf is 0x%x, size is %d, vaddr is 0x%x, fd=%d\n", buf->drm_buf, size, vaddr, fd);
return 1;
}
drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create BO from user buffer 0x%08x (%d byte), fd=%d, BO GPU offset hint=0x%08x\n",
vaddr, size, fd, wsbmBOOffsetHint(buf->drm_buf));
buf->pl_flags = placement;
buf->status = psb_bs_ready;
buf->wsbm_synccpu_flag = 0;
return VA_STATUS_SUCCESS;
}
#if 0
/*
* buffer setstatus
*
* Returns 0 on success
*/
int psb_buffer_setstatus(psb_buffer_p buf, uint32_t set_placement, uint32_t clr_placement)
{
int ret = 0;
ASSERT(buf);
ASSERT(buf->driver_data);
ret = wsbmBOSetStatus(buf->drm_buf, set_placement, clr_placement);
if (ret == 0)
buf->pl_flags = set_placement;
return ret;
}
#endif
VAStatus psb_buffer_reference(psb_driver_data_p driver_data,
psb_buffer_p buf,
psb_buffer_p reference_buf
)
{
int ret = 0;
VAStatus vaStatus = VA_STATUS_SUCCESS;
memcpy(buf, reference_buf, sizeof(*buf));
buf->drm_buf = NULL;
ret = LOCK_HARDWARE(driver_data);
if (ret) {
UNLOCK_HARDWARE(driver_data);
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
DEBUG_FAILURE_RET;
return vaStatus;
}
ret = wsbmGenBuffers(driver_data->main_pool,
1,
&buf->drm_buf,
4096, /* page alignment */
0);
if (!buf->drm_buf) {
drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to gen wsbm buffers\n");
UNLOCK_HARDWARE(driver_data);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
ret = wsbmBOSetReferenced(buf->drm_buf, wsbmKBufHandle(wsbmKBuf(reference_buf->drm_buf)));
UNLOCK_HARDWARE(driver_data);
if (ret) {
drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to alloc wsbm buffers\n");
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
return VA_STATUS_SUCCESS;
}
VAStatus psb_kbuffer_reference(psb_driver_data_p driver_data,
psb_buffer_p buf,
int kbuf_handle
)
{
int ret = 0;
VAStatus vaStatus = VA_STATUS_SUCCESS;
buf->drm_buf = NULL;
ret = LOCK_HARDWARE(driver_data);
if (ret) {
UNLOCK_HARDWARE(driver_data);
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
DEBUG_FAILURE_RET;
return vaStatus;
}
ret = wsbmGenBuffers(driver_data->main_pool,
1,
&buf->drm_buf,
4096, /* page alignment */
0);
if (!buf->drm_buf) {
drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to gen wsbm buffers\n");
UNLOCK_HARDWARE(driver_data);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
ret = wsbmBOSetReferenced(buf->drm_buf, kbuf_handle);
UNLOCK_HARDWARE(driver_data);
if (ret) {
drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to alloc wsbm buffers\n");
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
buf->pl_flags = wsbmBOPlacementHint(buf->drm_buf);
buf->type = psb_bt_surface;
buf->status = psb_bs_ready;
return VA_STATUS_SUCCESS;
}
/*
* Destroy buffer
*/
void psb_buffer_destroy(psb_buffer_p buf)
{
ASSERT(buf);
if (buf->drm_buf == NULL)
return;
if (psb_bs_unfinished != buf->status) {
ASSERT(buf->driver_data);
wsbmBOUnreference(&buf->drm_buf);
if (buf->rar_handle)
buf->rar_handle = 0;
buf->driver_data = NULL;
buf->status = psb_bs_unfinished;
}
}
/*
* Map buffer
*
* Returns 0 on success
*/
int psb_buffer_map(psb_buffer_p buf, unsigned char **address /* out */)
{
int ret;
ASSERT(buf);
ASSERT(buf->driver_data);
/* multiple mapping not allowed */
if (buf->wsbm_synccpu_flag) {
drv_debug_msg(VIDEO_DEBUG_GENERAL, "Multiple mapping request detected, unmap previous mapping\n");
drv_debug_msg(VIDEO_DEBUG_GENERAL, "Need to fix application to unmap at first, then request second mapping request\n");
psb_buffer_unmap(buf);
}
/* don't think TG deal with READ/WRITE differently */
buf->wsbm_synccpu_flag = WSBM_SYNCCPU_READ | WSBM_SYNCCPU_WRITE;
if (psb_video_trace_fp) {
wsbmBOWaitIdle(buf->drm_buf, 0);
} else {
ret = wsbmBOSyncForCpu(buf->drm_buf, buf->wsbm_synccpu_flag);
if (ret) {
drv_debug_msg(VIDEO_DEBUG_ERROR, "faild to sync bo for cpu\n");
return ret;
}
}
if (buf->user_ptr) /* user mode buffer */
*address = buf->user_ptr;
else
*address = wsbmBOMap(buf->drm_buf, buf->wsbm_synccpu_flag);
if (*address == NULL) {
drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to map buffer\n");
return -1;
}
return 0;
}
/*
* Unmap buffer
*
* Returns 0 on success
*/
int psb_buffer_unmap(psb_buffer_p buf)
{
ASSERT(buf);
ASSERT(buf->driver_data);
if (buf->wsbm_synccpu_flag)
(void) wsbmBOReleaseFromCpu(buf->drm_buf, buf->wsbm_synccpu_flag);
buf->wsbm_synccpu_flag = 0;
if ((buf->type != psb_bt_user_buffer) && !buf->handle)
wsbmBOUnmap(buf->drm_buf);
return 0;
}
#define _MRFL_DEBUG_CODED_
#ifdef _MRFL_DEBUG_CODED_
static void psb__trace_coded(VACodedBufferSegment *vaCodedBufSeg)
{
int i, j;
int uiPipeIndex = -1;
unsigned int *pBuf = NULL;
do {
++uiPipeIndex;
drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: pipe num %d, size = %d\n", __FUNCTION__, uiPipeIndex, vaCodedBufSeg[uiPipeIndex].size);
pBuf = (unsigned int *)(vaCodedBufSeg[uiPipeIndex].buf);
pBuf -= 16;
for (i = 0; i < 6; i++) {
for (j = 0; j < 4; j++) {
drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: 0x%08x\n", __FUNCTION__, pBuf[(i*4) + j]);
}
}
drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: \n", __FUNCTION__);
} while (vaCodedBufSeg[uiPipeIndex].next);
return ;
}
#endif
#define PROFILE_H264(profile) ((profile>=VAProfileH264Baseline && profile <=VAProfileH264High) || \
(profile == VAProfileH264ConstrainedBaseline))
static void tng_get_coded_data(
object_buffer_p obj_buffer,
unsigned char *raw_codedbuf
)
{
object_context_p obj_context = obj_buffer->context;
VACodedBufferSegment *vaCodedBufSeg = &obj_buffer->codedbuf_mapinfo[0];
int iPipeIndex = 0;
unsigned int uiPipeNum = tng_get_pipe_number(obj_context);
unsigned int uiBufOffset = tng_align_KB(obj_buffer->size >> 1);
unsigned long *ptmp = NULL;
int tmp;
drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s pipenum = 0x%x\n", __FUNCTION__, uiPipeNum);
drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s offset = 0x%x\n", __FUNCTION__, uiBufOffset);
tmp = vaCodedBufSeg[iPipeIndex].size = *(unsigned int *)((unsigned long)raw_codedbuf);
/*
* This is used for DRM over WiDi which only uses H264 BP
* Tangier IED encryption operates on the chunks with 16bytes, and we must include
* the extra bytes beyond slice data as a whole chunk for decrption
* We simply include the padding bytes regardless of IED enable or disable
*/
if (PROFILE_H264(obj_context->profile) && (tmp % 16 != 0)) {
tmp = (tmp + 15) & (~15);
drv_debug_msg(VIDEO_DEBUG_GENERAL, "Force slice size from %d to %d\n",
vaCodedBufSeg[iPipeIndex].size, tmp);
vaCodedBufSeg[iPipeIndex].size = tmp;
}
vaCodedBufSeg[iPipeIndex].buf = (unsigned char *)(((unsigned int *)((unsigned long)raw_codedbuf)) + 16); /* skip 4DWs */
ptmp = (unsigned long *)((unsigned long)raw_codedbuf);
vaCodedBufSeg[iPipeIndex].reserved = (ptmp[1] >> 6) & 0xf;
vaCodedBufSeg[iPipeIndex].next = NULL;
if (uiPipeNum == 2) {
/*The second part of coded buffer which generated by core 2 is the
* first part of encoded clip, while the first part of coded buffer
* is the second part of encoded clip.*/
++iPipeIndex;
vaCodedBufSeg[iPipeIndex - 1].next = &vaCodedBufSeg[iPipeIndex];
tmp = vaCodedBufSeg[iPipeIndex].size = *(unsigned int *)((unsigned long)raw_codedbuf + uiBufOffset);
/*
* This is used for DRM over WiDi which only uses H264 BP
* Tangier IED encryption operates on the chunks with 16bytes, and we must include
* the extra bytes beyond slice data as a whole chunk for decryption
* We simply include the padding bytes regardless of IED enable or disable
*/
if (PROFILE_H264(obj_context->profile) && (tmp % 16 != 0)) {
tmp = (tmp + 15) & (~15);
drv_debug_msg(VIDEO_DEBUG_GENERAL,"Force slice size from %d to %d\n",
vaCodedBufSeg[iPipeIndex].size, tmp);
vaCodedBufSeg[iPipeIndex].size = tmp;
}
vaCodedBufSeg[iPipeIndex].buf = (unsigned char *)(((unsigned int *)((unsigned long)raw_codedbuf + uiBufOffset)) + 16); /* skip 4DWs */
vaCodedBufSeg[iPipeIndex].reserved = vaCodedBufSeg[iPipeIndex - 1].reserved;
vaCodedBufSeg[iPipeIndex].next = NULL;
}
#ifdef _MRFL_DEBUG_CODED_
psb__trace_coded(vaCodedBufSeg);
#endif
return ;
}
/*
* Return special data structure for codedbuffer
*
* Returns 0 on success
*/
#define CONFIG(id) ((object_config_p) object_heap_lookup( &driver_data->config_heap, id ))
#define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
int psb_codedbuf_map_mangle(
VADriverContextP ctx,
object_buffer_p obj_buffer,
void **pbuf /* out */
)
{
object_context_p obj_context = obj_buffer->context;
INIT_DRIVER_DATA;
VACodedBufferSegment *p = &obj_buffer->codedbuf_mapinfo[0];
unsigned char *raw_codedbuf;
VAStatus vaStatus = VA_STATUS_SUCCESS;
unsigned int next_buf_off;
uint32_t i;
CHECK_INVALID_PARAM(pbuf == NULL);
if (NULL == obj_context) {
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
DEBUG_FAILURE;
psb_buffer_unmap(obj_buffer->psb_buffer);
obj_buffer->buffer_data = NULL;
return vaStatus;
}
raw_codedbuf = *pbuf;
/* reset the mapinfo */
memset(obj_buffer->codedbuf_mapinfo, 0, sizeof(obj_buffer->codedbuf_mapinfo));
*pbuf = p = &obj_buffer->codedbuf_mapinfo[0];
#ifdef PSBVIDEO_MRFL
if (IS_MRFL(driver_data)) {
object_config_p obj_config = CONFIG(obj_context->config_id);
if (NULL == obj_config) {
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
DEBUG_FAILURE;
psb_buffer_unmap(obj_buffer->psb_buffer);
obj_buffer->buffer_data = NULL;
return vaStatus;
}
if (VAProfileJPEGBaseline != obj_config->profile
&& (*((unsigned long *) raw_codedbuf + 1) & SKIP_NEXT_FRAME) != 0) {
/*Set frame skip flag*/
tng_set_frame_skip_flag(obj_context);
}
switch (obj_config->profile) {
case VAProfileMPEG4Simple:
case VAProfileMPEG4AdvancedSimple:
case VAProfileMPEG4Main:
case VAProfileH264Baseline:
case VAProfileH264Main:
case VAProfileH264High:
case VAProfileH264StereoHigh:
case VAProfileH264ConstrainedBaseline:
case VAProfileH263Baseline:
/* 1st segment */
tng_get_coded_data(obj_buffer, raw_codedbuf);
#if 0
p->size = *((unsigned long *) raw_codedbuf);
p->buf = (unsigned char *)((unsigned long *) raw_codedbuf + 16); /* skip 16DWs */
p->next = NULL;
#ifdef _MRFL_DEBUG_CODED_
psb__trace_coded((unsigned int*)raw_codedbuf);
psb__trace_coded(p);
#endif
#endif
break;
case VAProfileVP8Version0_3:
{
/* multi segments*/
struct VssVp8encEncodedFrame *t = (struct VssVp8encEncodedFrame *) (raw_codedbuf);
int concatenate = 1;
#if 0
for (i = 0; i < t->partitions - 1; i++) {
if (t->partition_start[i+1] != t->partition_start[i] + t->partition_size[i])
concatenate = 0;
}
#endif
/* reference frame surface_id */
/* default is recon_buffer_mode ==0 */
p->reserved = t->surfaceId_of_ref_frame[3];
if (concatenate) {
/* partitions are concatenate */
p->buf = t->coded_data;
p->size = t->frame_size;
if(t->frame_size == 0){
drv_debug_msg(VIDEO_DEBUG_ERROR,"Frame size is zero, Force it to 3, encoder status is 0x%x\n", t->status);
p->size = 3;
t->coded_data[0]=0;
}
p->next = NULL;
} else {
for (i = 0; i < t->partitions; i++) {
/* partition not consecutive */
p->buf = t->coded_data + t->partition_start[i] - t->partition_start[0];
p->size += t->partition_size[i];
p->next = &p[1];
p++;
}
p--;
p->next = NULL;
}
break;
}
case VAProfileJPEGBaseline:
/* 3~6 segment */
tng_jpeg_AppendMarkers(obj_context, raw_codedbuf);
next_buf_off = 0;
/*Max resolution 4096x4096 use 6 segments*/
for (i = 0; i < PTG_JPEG_MAX_SCAN_NUM + 1; i++) {
p->size = *(unsigned long *)((unsigned long)raw_codedbuf + next_buf_off); /* ui32BytesUsed in HEADER_BUFFER*/
p->buf = (unsigned char *)((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off) + 4); /* skip 4DWs (HEADER_BUFFER) */
next_buf_off = *((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off) + 3); /* ui32Reserved3 in HEADER_BUFFER*/
drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG coded buffer segment %d size: %d\n", i, p->size);
drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG coded buffer next segment %d offset: %d\n", i + 1, next_buf_off);
if (next_buf_off == 0) {
p->next = NULL;
break;
} else
p->next = &p[1];
p++;
}
break;
default:
drv_debug_msg(VIDEO_DEBUG_ERROR, "unexpected case\n");
psb_buffer_unmap(obj_buffer->psb_buffer);
obj_buffer->buffer_data = NULL;
break;
}
}
#endif
#ifdef PSBVIDEO_MFLD
if (IS_MFLD(driver_data)){ /* MFLD */
object_config_p obj_config = CONFIG(obj_context->config_id);
if (NULL == obj_config) {
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
DEBUG_FAILURE;
psb_buffer_unmap(obj_buffer->psb_buffer);
obj_buffer->buffer_data = NULL;
return vaStatus;
}
if (VAProfileJPEGBaseline != obj_config->profile
&& (*((unsigned long *) raw_codedbuf + 1) & SKIP_NEXT_FRAME) != 0) {
/*Set frame skip flag*/
pnw_set_frame_skip_flag(obj_context);
}
switch (obj_config->profile) {
case VAProfileMPEG4Simple:
case VAProfileMPEG4AdvancedSimple:
case VAProfileMPEG4Main:
/* one segment */
p->size = *((unsigned long *) raw_codedbuf);
p->buf = (unsigned char *)((unsigned long *) raw_codedbuf + 4); /* skip 4DWs */
drv_debug_msg(VIDEO_DEBUG_GENERAL, "coded buffer size %d\n", p->size);
break;
case VAProfileH264Baseline:
case VAProfileH264Main:
case VAProfileH264High:
case VAProfileH264ConstrainedBaseline:
i = 0;
next_buf_off = ~0xf & (obj_buffer->size / pnw_get_parallel_core_number(obj_context));
if (pnw_get_parallel_core_number(obj_context) == 2) {
/*The second part of coded buffer which generated by core 2 is the
* first part of encoded clip, while the first part of coded buffer
* is the second part of encoded clip.*/
p[i].next = &p[i + 1];
p[i].size = *(unsigned long *)((unsigned long)raw_codedbuf + next_buf_off);
p[i].buf = (unsigned char *)(((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off)) + 4); /* skip 4DWs */
if (GET_CODEDBUF_INFO(SLICE_NUM, obj_buffer->codedbuf_aux_info) <= 2 &&
GET_CODEDBUF_INFO(NONE_VCL_NUM, obj_buffer->codedbuf_aux_info) == 0) {
p[i].status = VA_CODED_BUF_STATUS_SINGLE_NALU;
drv_debug_msg(VIDEO_DEBUG_GENERAL, "Only VCL NAL in this segment %i of coded buffer\n",
i);
}
drv_debug_msg(VIDEO_DEBUG_GENERAL, "2nd segment coded buffer offset: 0x%08x, size: %d\n",
next_buf_off, p[i].size);
i++;
}
/* 1st segment */
p[i].size = *((unsigned long *) raw_codedbuf);
p[i].buf = (unsigned char *)((unsigned long *) raw_codedbuf + 4); /* skip 4DWs */
drv_debug_msg(VIDEO_DEBUG_GENERAL, "1st segment coded buffer size %d\n", p[i].size);
if (GET_CODEDBUF_INFO(SLICE_NUM, obj_buffer->codedbuf_aux_info) <= 2 &&
GET_CODEDBUF_INFO(NONE_VCL_NUM, obj_buffer->codedbuf_aux_info) == 0) {
p[i].status = VA_CODED_BUF_STATUS_SINGLE_NALU;
drv_debug_msg(VIDEO_DEBUG_GENERAL, "Only VCL NAL in this segment %i of coded buffer\n",
i);
}
for (i = 0; i < pnw_get_parallel_core_number(obj_context); i++) {
if (p[i].size > (next_buf_off - sizeof(unsigned long) * 4)) {
drv_debug_msg(VIDEO_DEBUG_ERROR, "Coded segment %d is too large(%d)"
" and exceed segment boundary(offset %d)", i, p[i].size, next_buf_off);
p[i].size = next_buf_off - sizeof(unsigned long) * 4;
}
}
break;
case VAProfileH263Baseline:
/* one segment */
p->size = *((unsigned long *) raw_codedbuf);
p->buf = (unsigned char *)((unsigned long *) raw_codedbuf + 4); /* skip 4DWs */
drv_debug_msg(VIDEO_DEBUG_GENERAL, "coded buffer size %d\n", p->size);
break;
case VAProfileJPEGBaseline:
/* 3~6 segment
*/
pnw_jpeg_AppendMarkers(obj_context, raw_codedbuf);
next_buf_off = 0;
/*Max resolution 4096x4096 use 6 segments*/
for (i = 0; i < PNW_JPEG_MAX_SCAN_NUM + 1; i++) {
p->size = *(unsigned long *)((unsigned long)raw_codedbuf + next_buf_off);
p->buf = (unsigned char *)((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off) + 4); /* skip 4DWs */
next_buf_off = *((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off) + 3);
drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG coded buffer segment %d size: %d\n", i, p->size);
drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG coded buffer next segment %d offset: %d\n", i + 1, next_buf_off);
if (next_buf_off == 0) {
p->next = NULL;
break;
} else
p->next = &p[1];
p++;
}
break;
default:
drv_debug_msg(VIDEO_DEBUG_ERROR, "unexpected case\n");
psb_buffer_unmap(obj_buffer->psb_buffer);
obj_buffer->buffer_data = NULL;
break;
}
}
#endif
return 0;
}