Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/drivers/media/platform/st/sti/delta/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 12 kB image not shown  

Quelle  delta-mjpeg-dec.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) STMicroelectronics SA 2013
 * Author: Hugues Fruchet <hugues.fruchet@st.com> for STMicroelectronics.
 */


#include <linux/slab.h>

#include "delta.h"
#include "delta-ipc.h"
#include "delta-mjpeg.h"
#include "delta-mjpeg-fw.h"

#define DELTA_MJPEG_MAX_RESO DELTA_MAX_RESO

struct delta_mjpeg_ctx {
 /* jpeg header */
 struct mjpeg_header header_struct;
 struct mjpeg_header *header;

 /* ipc */
 void *ipc_hdl;
 struct delta_buf *ipc_buf;

 /* decoded output frame */
 struct delta_frame *out_frame;

 unsigned char str[3000];
};

#define to_ctx(ctx) ((struct delta_mjpeg_ctx *)(ctx)->priv)

static char *ipc_open_param_str(struct jpeg_video_decode_init_params_t *p,
    char *str, unsigned int len)
{
 char *b = str;

 if (!p)
  return "";

 b += snprintf(b, len,
        "jpeg_video_decode_init_params_t\n"
        "circular_buffer_begin_addr_p 0x%x\n"
        "circular_buffer_end_addr_p 0x%x\n",
        p->circular_buffer_begin_addr_p,
        p->circular_buffer_end_addr_p);

 return str;
}

static char *ipc_decode_param_str(struct jpeg_decode_params_t *p,
      char *str, unsigned int len)
{
 char *b = str;

 if (!p)
  return "";

 b += snprintf(b, len,
        "jpeg_decode_params_t\n"
        "picture_start_addr_p 0x%x\n"
        "picture_end_addr_p 0x%x\n"
        "decoding_mode %d\n"
        "display_buffer_addr.display_decimated_luma_p 0x%x\n"
        "display_buffer_addr.display_decimated_chroma_p 0x%x\n"
        "main_aux_enable %d\n"
        "additional_flags 0x%x\n"
        "field_flag %x\n"
        "is_jpeg_image %x\n",
        p->picture_start_addr_p,
        p->picture_end_addr_p,
        p->decoding_mode,
        p->display_buffer_addr.display_decimated_luma_p,
        p->display_buffer_addr.display_decimated_chroma_p,
        p->main_aux_enable, p->additional_flags,
        p->field_flag,
        p->is_jpeg_image);

 return str;
}

static inline bool is_stream_error(enum jpeg_decoding_error_t err)
{
 switch (err) {
 case JPEG_DECODER_UNDEFINED_HUFF_TABLE:
 case JPEG_DECODER_BAD_RESTART_MARKER:
 case JPEG_DECODER_BAD_SOS_SPECTRAL:
 case JPEG_DECODER_BAD_SOS_SUCCESSIVE:
 case JPEG_DECODER_BAD_HEADER_LENGTH:
 case JPEG_DECODER_BAD_COUNT_VALUE:
 case JPEG_DECODER_BAD_DHT_MARKER:
 case JPEG_DECODER_BAD_INDEX_VALUE:
 case JPEG_DECODER_BAD_NUMBER_HUFFMAN_TABLES:
 case JPEG_DECODER_BAD_QUANT_TABLE_LENGTH:
 case JPEG_DECODER_BAD_NUMBER_QUANT_TABLES:
 case JPEG_DECODER_BAD_COMPONENT_COUNT:
  return true;
 default:
  return false;
 }
}

static inline const char *err_str(enum jpeg_decoding_error_t err)
{
 switch (err) {
 case JPEG_DECODER_NO_ERROR:
  return "JPEG_DECODER_NO_ERROR";
 case JPEG_DECODER_UNDEFINED_HUFF_TABLE:
  return "JPEG_DECODER_UNDEFINED_HUFF_TABLE";
 case JPEG_DECODER_UNSUPPORTED_MARKER:
  return "JPEG_DECODER_UNSUPPORTED_MARKER";
 case JPEG_DECODER_UNABLE_ALLOCATE_MEMORY:
  return "JPEG_DECODER_UNABLE_ALLOCATE_MEMORY";
 case JPEG_DECODER_NON_SUPPORTED_SAMP_FACTORS:
  return "JPEG_DECODER_NON_SUPPORTED_SAMP_FACTORS";
 case JPEG_DECODER_BAD_PARAMETER:
  return "JPEG_DECODER_BAD_PARAMETER";
 case JPEG_DECODER_DECODE_ERROR:
  return "JPEG_DECODER_DECODE_ERROR";
 case JPEG_DECODER_BAD_RESTART_MARKER:
  return "JPEG_DECODER_BAD_RESTART_MARKER";
 case JPEG_DECODER_UNSUPPORTED_COLORSPACE:
  return "JPEG_DECODER_UNSUPPORTED_COLORSPACE";
 case JPEG_DECODER_BAD_SOS_SPECTRAL:
  return "JPEG_DECODER_BAD_SOS_SPECTRAL";
 case JPEG_DECODER_BAD_SOS_SUCCESSIVE:
  return "JPEG_DECODER_BAD_SOS_SUCCESSIVE";
 case JPEG_DECODER_BAD_HEADER_LENGTH:
  return "JPEG_DECODER_BAD_HEADER_LENGTH";
 case JPEG_DECODER_BAD_COUNT_VALUE:
  return "JPEG_DECODER_BAD_COUNT_VALUE";
 case JPEG_DECODER_BAD_DHT_MARKER:
  return "JPEG_DECODER_BAD_DHT_MARKER";
 case JPEG_DECODER_BAD_INDEX_VALUE:
  return "JPEG_DECODER_BAD_INDEX_VALUE";
 case JPEG_DECODER_BAD_NUMBER_HUFFMAN_TABLES:
  return "JPEG_DECODER_BAD_NUMBER_HUFFMAN_TABLES";
 case JPEG_DECODER_BAD_QUANT_TABLE_LENGTH:
  return "JPEG_DECODER_BAD_QUANT_TABLE_LENGTH";
 case JPEG_DECODER_BAD_NUMBER_QUANT_TABLES:
  return "JPEG_DECODER_BAD_NUMBER_QUANT_TABLES";
 case JPEG_DECODER_BAD_COMPONENT_COUNT:
  return "JPEG_DECODER_BAD_COMPONENT_COUNT";
 case JPEG_DECODER_DIVIDE_BY_ZERO_ERROR:
  return "JPEG_DECODER_DIVIDE_BY_ZERO_ERROR";
 case JPEG_DECODER_NOT_JPG_IMAGE:
  return "JPEG_DECODER_NOT_JPG_IMAGE";
 case JPEG_DECODER_UNSUPPORTED_ROTATION_ANGLE:
  return "JPEG_DECODER_UNSUPPORTED_ROTATION_ANGLE";
 case JPEG_DECODER_UNSUPPORTED_SCALING:
  return "JPEG_DECODER_UNSUPPORTED_SCALING";
 case JPEG_DECODER_INSUFFICIENT_OUTPUTBUFFER_SIZE:
  return "JPEG_DECODER_INSUFFICIENT_OUTPUTBUFFER_SIZE";
 case JPEG_DECODER_BAD_HWCFG_GP_VERSION_VALUE:
  return "JPEG_DECODER_BAD_HWCFG_GP_VERSION_VALUE";
 case JPEG_DECODER_BAD_VALUE_FROM_RED:
  return "JPEG_DECODER_BAD_VALUE_FROM_RED";
 case JPEG_DECODER_BAD_SUBREGION_PARAMETERS:
  return "JPEG_DECODER_BAD_SUBREGION_PARAMETERS";
 case JPEG_DECODER_PROGRESSIVE_DECODE_NOT_SUPPORTED:
  return "JPEG_DECODER_PROGRESSIVE_DECODE_NOT_SUPPORTED";
 case JPEG_DECODER_ERROR_TASK_TIMEOUT:
  return "JPEG_DECODER_ERROR_TASK_TIMEOUT";
 case JPEG_DECODER_ERROR_FEATURE_NOT_SUPPORTED:
  return "JPEG_DECODER_ERROR_FEATURE_NOT_SUPPORTED";
 default:
  return "!unknown MJPEG error!";
 }
}

static bool delta_mjpeg_check_status(struct delta_ctx *pctx,
         struct jpeg_decode_return_params_t *status)
{
 struct delta_dev *delta = pctx->dev;
 bool dump = false;

 if (status->error_code == JPEG_DECODER_NO_ERROR)
  goto out;

 if (is_stream_error(status->error_code)) {
  dev_warn_ratelimited(delta->dev,
         "%s firmware: stream error @ frame %d (%s)\n",
         pctx->name, pctx->decoded_frames,
         err_str(status->error_code));
  pctx->stream_errors++;
 } else {
  dev_warn_ratelimited(delta->dev,
         "%s firmware: decode error @ frame %d (%s)\n",
         pctx->name, pctx->decoded_frames,
         err_str(status->error_code));
  pctx->decode_errors++;
  dump = true;
 }

out:
 dev_dbg(delta->dev,
  "%s firmware: decoding time(us)=%d\n", pctx->name,
  status->decode_time_in_us);

 return dump;
}

static int delta_mjpeg_ipc_open(struct delta_ctx *pctx)
{
 struct delta_dev *delta = pctx->dev;
 struct delta_mjpeg_ctx *ctx = to_ctx(pctx);
 int ret = 0;
 struct jpeg_video_decode_init_params_t params_struct;
 struct jpeg_video_decode_init_params_t *params = ¶ms_struct;
 struct delta_buf *ipc_buf;
 u32 ipc_buf_size;
 struct delta_ipc_param ipc_param;
 void *hdl;

 memset(params, 0, sizeof(*params));
 params->circular_buffer_begin_addr_p = 0x00000000;
 params->circular_buffer_end_addr_p = 0xffffffff;

 dev_vdbg(delta->dev,
   "%s %s\n", pctx->name,
   ipc_open_param_str(params, ctx->str, sizeof(ctx->str)));

 ipc_param.size = sizeof(*params);
 ipc_param.data = params;
 ipc_buf_size = sizeof(struct jpeg_decode_params_t) +
     sizeof(struct jpeg_decode_return_params_t);
 ret = delta_ipc_open(pctx, "JPEG_DECODER_HW0", &ipc_param,
        ipc_buf_size, &ipc_buf, &hdl);
 if (ret) {
  dev_err(delta->dev,
   "%s dumping command %s\n", pctx->name,
   ipc_open_param_str(params, ctx->str, sizeof(ctx->str)));
  return ret;
 }

 ctx->ipc_buf = ipc_buf;
 ctx->ipc_hdl = hdl;

 return 0;
}

static int delta_mjpeg_ipc_decode(struct delta_ctx *pctx, dma_addr_t pstart, dma_addr_t pend)
{
 struct delta_dev *delta = pctx->dev;
 struct delta_mjpeg_ctx *ctx = to_ctx(pctx);
 int ret = 0;
 struct jpeg_decode_params_t *params = ctx->ipc_buf->vaddr;
 struct jpeg_decode_return_params_t *status =
     ctx->ipc_buf->vaddr + sizeof(*params);
 struct delta_frame *frame;
 struct delta_ipc_param ipc_param, ipc_status;

 ret = delta_get_free_frame(pctx, &frame);
 if (ret)
  return ret;

 memset(params, 0, sizeof(*params));

 params->picture_start_addr_p = pstart;
 params->picture_end_addr_p = pend;

 /*
 * !WARNING!
 * the NV12 decoded frame is only available
 * on decimated output when enabling flag
 * "JPEG_ADDITIONAL_FLAG_420MB"...
 * the non decimated output gives YUV422SP
 */

 params->main_aux_enable = JPEG_DISP_AUX_EN;
 params->additional_flags = JPEG_ADDITIONAL_FLAG_420MB;
 params->horizontal_decimation_factor = JPEG_HDEC_1;
 params->vertical_decimation_factor = JPEG_VDEC_1;
 params->decoding_mode = JPEG_NORMAL_DECODE;

 params->display_buffer_addr.struct_size =
     sizeof(struct jpeg_display_buffer_address_t);
 params->display_buffer_addr.display_decimated_luma_p =
     (u32)frame->paddr;
 params->display_buffer_addr.display_decimated_chroma_p =
     (u32)(frame->paddr
    + frame->info.aligned_width * frame->info.aligned_height);

 dev_vdbg(delta->dev,
   "%s %s\n", pctx->name,
   ipc_decode_param_str(params, ctx->str, sizeof(ctx->str)));

 /* status */
 memset(status, 0, sizeof(*status));
 status->error_code = JPEG_DECODER_NO_ERROR;

 ipc_param.size = sizeof(*params);
 ipc_param.data = params;
 ipc_status.size = sizeof(*status);
 ipc_status.data = status;
 ret = delta_ipc_decode(ctx->ipc_hdl, &ipc_param, &ipc_status);
 if (ret) {
  dev_err(delta->dev,
   "%s dumping command %s\n", pctx->name,
   ipc_decode_param_str(params, ctx->str,
          sizeof(ctx->str)));
  return ret;
 }

 pctx->decoded_frames++;

 /* check firmware decoding status */
 if (delta_mjpeg_check_status(pctx, status)) {
  dev_err(delta->dev,
   "%s dumping command %s\n", pctx->name,
   ipc_decode_param_str(params, ctx->str,
          sizeof(ctx->str)));
 }

 frame->field = V4L2_FIELD_NONE;
 frame->flags = V4L2_BUF_FLAG_KEYFRAME;
 frame->state |= DELTA_FRAME_DEC;

 ctx->out_frame = frame;

 return 0;
}

static int delta_mjpeg_open(struct delta_ctx *pctx)
{
 struct delta_mjpeg_ctx *ctx;

 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 if (!ctx)
  return -ENOMEM;
 pctx->priv = ctx;

 return 0;
}

static int delta_mjpeg_close(struct delta_ctx *pctx)
{
 struct delta_mjpeg_ctx *ctx = to_ctx(pctx);

 if (ctx->ipc_hdl) {
  delta_ipc_close(ctx->ipc_hdl);
  ctx->ipc_hdl = NULL;
 }

 kfree(ctx);

 return 0;
}

static int delta_mjpeg_get_streaminfo(struct delta_ctx *pctx,
          struct delta_streaminfo *streaminfo)
{
 struct delta_mjpeg_ctx *ctx = to_ctx(pctx);

 if (!ctx->header)
  goto nodata;

 streaminfo->streamformat = V4L2_PIX_FMT_MJPEG;
 streaminfo->width = ctx->header->frame_width;
 streaminfo->height = ctx->header->frame_height;

 /* progressive stream */
 streaminfo->field = V4L2_FIELD_NONE;

 streaminfo->dpb = 1;

 return 0;

nodata:
 return -ENODATA;
}

static int delta_mjpeg_decode(struct delta_ctx *pctx, struct delta_au *pau)
{
 struct delta_dev *delta = pctx->dev;
 struct delta_mjpeg_ctx *ctx = to_ctx(pctx);
 int ret;
 void *au_vaddr = pau->vaddr;
 dma_addr_t au_dma = pau->paddr;
 size_t au_size = pau->size;
 unsigned int data_offset = 0;
 struct mjpeg_header *header = &ctx->header_struct;

 if (!ctx->header) {
  ret = delta_mjpeg_read_header(pctx, au_vaddr, au_size,
           header, &data_offset);
  if (ret) {
   pctx->stream_errors++;
   goto err;
  }
  if (header->frame_width * header->frame_height >
      DELTA_MJPEG_MAX_RESO) {
   dev_err(delta->dev,
    "%s stream resolution too large: %dx%d > %d pixels budget\n",
    pctx->name,
    header->frame_width,
    header->frame_height, DELTA_MJPEG_MAX_RESO);
   ret = -EINVAL;
   goto err;
  }
  ctx->header = header;
  goto out;
 }

 if (!ctx->ipc_hdl) {
  ret = delta_mjpeg_ipc_open(pctx);
  if (ret)
   goto err;
 }

 ret = delta_mjpeg_read_header(pctx, au_vaddr, au_size,
          ctx->header, &data_offset);
 if (ret) {
  pctx->stream_errors++;
  goto err;
 }

 au_dma += data_offset;
 au_vaddr += data_offset;

 ret = delta_mjpeg_ipc_decode(pctx, au_dma, au_dma + au_size - 1);
 if (ret)
  goto err;

out:
 return 0;

err:
 return ret;
}

static int delta_mjpeg_get_frame(struct delta_ctx *pctx,
     struct delta_frame **frame)
{
 struct delta_mjpeg_ctx *ctx = to_ctx(pctx);

 if (!ctx->out_frame)
  return -ENODATA;

 *frame = ctx->out_frame;

 ctx->out_frame = NULL;

 return 0;
}

const struct delta_dec mjpegdec = {
 .name = "MJPEG",
 .streamformat = V4L2_PIX_FMT_MJPEG,
 .pixelformat = V4L2_PIX_FMT_NV12,
 .open = delta_mjpeg_open,
 .close = delta_mjpeg_close,
 .get_streaminfo = delta_mjpeg_get_streaminfo,
 .get_frameinfo = delta_get_frameinfo_default,
 .decode = delta_mjpeg_decode,
 .get_frame = delta_mjpeg_get_frame,
 .recycle = delta_recycle_default,
};

Messung V0.5
C=93 H=87 G=89

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.