if (coda_get_bitstream_payload(ctx) + payload + 512 >=
ctx->bitstream.size) returnfalse;
if (!vaddr) {
v4l2_err(&ctx->dev->v4l2_dev, "trying to queue empty buffer\n"); returntrue;
}
if (ctx->qsequence == 0 && payload < 512) { /* * Add padding after the first buffer, if it is too small to be * fetched by the CODA, by repeating the headers. Without * repeated headers, or the first frame already queued, decoder * sequence initialization fails with error code 0x2000 on i.MX6 * or error code 0x1 on i.MX51.
*/
u32 header_size = coda_buffer_parse_headers(ctx, src_buf,
payload);
if (header_size) {
coda_dbg(1, ctx, "pad with %u-byte header\n",
header_size); for (i = payload; i < 512; i += header_size) {
ret = coda_bitstream_queue(ctx, vaddr,
header_size); if (ret < 0) {
v4l2_err(&ctx->dev->v4l2_dev, "bitstream buffer overflow\n"); returnfalse;
} if (ctx->dev->devtype->product == CODA_960) break;
}
} else {
coda_dbg(1, ctx, "could not parse header, sequence initialization might fail\n");
}
/* Add padding before the first buffer, if it is too small */ if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264)
coda_h264_bitstream_pad(ctx, 512 - payload);
}
ret = coda_bitstream_queue(ctx, vaddr, payload); if (ret < 0) {
v4l2_err(&ctx->dev->v4l2_dev, "bitstream buffer overflow\n"); returnfalse;
}
src_buf->sequence = ctx->qsequence++;
/* Sync read pointer to device */ if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev))
coda_kfifo_sync_to_device_write(ctx);
/* Set the stream-end flag after the last buffer is queued */ if (src_buf->flags & V4L2_BUF_FLAG_LAST)
coda_bit_stream_end_flag(ctx);
ctx->hold = false;
if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) return;
while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) { /* * Only queue two JPEGs into the bitstream buffer to keep * latency low. We need at least one complete buffer and the * header of another buffer (for prescan) in the bitstream.
*/ if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
ctx->num_metas > 1) break;
if (ctx->num_internal_frames &&
ctx->num_metas >= ctx->num_internal_frames) {
meta = list_first_entry(&ctx->buffer_meta_list, struct coda_buffer_meta, list);
/* * If we managed to fill in at least a full reorder * window of buffers (num_internal_frames is a * conservative estimate for this) and the bitstream * prefetcher has at least 2 256 bytes periods beyond * the first buffer to fetch, we can safely stop queuing * in order to limit the decoder drain latency.
*/ if (coda_bitstream_can_fetch_past(ctx, meta->end)) break;
}
src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
/* Drop frames that do not start/end with a SOI/EOI markers */ if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
!coda_jpeg_check_buffer(ctx, &src_buf->vb2_buf)) {
v4l2_err(&ctx->dev->v4l2_dev, "dropping invalid JPEG frame %d\n",
ctx->qsequence);
src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); if (buffer_list) { struct v4l2_m2m_buffer *m2m_buf;
/* Buffer start position */
start = ctx->bitstream_fifo.kfifo.in;
if (coda_bitstream_try_queue(ctx, src_buf)) { /* * Source buffer is queued in the bitstream ringbuffer; * queue the timestamp and mark source buffer as done
*/
src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
meta = kmalloc(sizeof(*meta), GFP_KERNEL); if (meta) {
meta->sequence = src_buf->sequence;
meta->timecode = src_buf->timecode;
meta->timestamp = src_buf->vb2_buf.timestamp;
meta->start = start;
meta->end = ctx->bitstream_fifo.kfifo.in;
meta->last = src_buf->flags & V4L2_BUF_FLAG_LAST; if (meta->last)
coda_dbg(1, ctx, "marking last meta");
spin_lock(&ctx->buffer_meta_lock);
list_add_tail(&meta->list,
&ctx->buffer_meta_list);
ctx->num_metas++;
spin_unlock(&ctx->buffer_meta_lock);
trace_coda_bit_queue(ctx, src_buf, meta);
}
if (buffer_list) { struct v4l2_m2m_buffer *m2m_buf;
/* If this context is currently running, update the hardware flag */ if ((dev->devtype->product == CODA_960) &&
coda_isbusy(dev) &&
(ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX))) {
coda_write(dev, ctx->bit_stream_param,
CODA_REG_BIT_BIT_STREAM_PARAM);
}
}
/* Allocate frame buffers */ for (i = 0; i < ctx->num_internal_frames; i++) {
size_t size = ycbcr_size; char *name;
/* Add space for mvcol buffers */ if (dev->devtype->product != CODA_DX6 &&
(ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 ||
(ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4 && i == 0)))
size += ysize / 4;
name = kasprintf(GFP_KERNEL, "fb%d", i); if (!name) {
coda_free_framebuffers(ctx); return -ENOMEM;
}
ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i].buf,
size, name);
kfree(name); if (ret < 0) {
coda_free_framebuffers(ctx); return ret;
}
}
/* Register frame buffers in the parameter buffer */ for (i = 0; i < ctx->num_internal_frames; i++) {
u32 y, cb, cr, mvcol;
/* Start addresses of Y, Cb, Cr planes */
y = ctx->internal_frames[i].buf.paddr;
cb = y + ysize;
cr = y + ysize + ysize/4;
mvcol = y + ysize + ysize/4 + ysize/4; if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) {
cb = round_up(cb, 4096);
mvcol = cb + ysize/2;
cr = 0; /* Packed 20-bit MSB of base addresses */ /* YYYYYCCC, CCyyyyyc, cccc.... */
y = (y & 0xfffff000) | cb >> 20;
cb = (cb & 0x000ff000) << 12;
}
coda_parabuf_write(ctx, i * 3 + 0, y);
coda_parabuf_write(ctx, i * 3 + 1, cb);
coda_parabuf_write(ctx, i * 3 + 2, cr);
if (dev->devtype->product == CODA_DX6) continue;
/* mvcol buffer for h.264 and mpeg4 */ if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264)
coda_parabuf_write(ctx, 96 + i, mvcol); if (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4 && i == 0)
coda_parabuf_write(ctx, 97, mvcol);
}
staticvoid coda_setup_iram(struct coda_ctx *ctx)
{ struct coda_iram_info *iram_info = &ctx->iram_info; struct coda_dev *dev = ctx->dev; int w64, w128; int mb_width; int dbk_bits; int bit_bits; int ip_bits; int me_bits;
/* Prioritize in case IRAM is too small for everything */ if (dev->devtype->product == CODA_HX4 ||
dev->devtype->product == CODA_7541) {
iram_info->search_ram_size = round_up(mb_width * 16 *
36 + 2048, 1024);
iram_info->search_ram_paddr = coda_iram_alloc(iram_info,
iram_info->search_ram_size); if (!iram_info->search_ram_paddr) {
pr_err("IRAM is smaller than the search ram size\n"); goto out;
}
iram_info->axi_sram_use |= me_bits;
}
/* Only H.264BP and H.263P3 are considered */
iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w64);
iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w64); if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use) goto out;
iram_info->axi_sram_use |= dbk_bits;
staticbool coda_firmware_supported(u32 vernum)
{ int i;
for (i = 0; i < ARRAY_SIZE(coda_supported_firmwares); i++) if (vernum == coda_supported_firmwares[i]) returntrue; returnfalse;
}
int coda_check_firmware(struct coda_dev *dev)
{
u16 product, major, minor, release;
u32 data; int ret;
ret = clk_prepare_enable(dev->clk_per); if (ret) goto err_clk_per;
ret = clk_prepare_enable(dev->clk_ahb); if (ret) goto err_clk_ahb;
coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM);
coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX);
coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD);
coda_write(dev, CODA_COMMAND_FIRMWARE_GET, CODA_REG_BIT_RUN_COMMAND); if (coda_wait_timeout(dev)) {
v4l2_err(&dev->v4l2_dev, "firmware get command error\n");
ret = -EIO; goto err_run_cmd;
}
if (dev->devtype->product == CODA_960) {
data = coda_read(dev, CODA9_CMD_FIRMWARE_CODE_REV);
v4l2_info(&dev->v4l2_dev, "Firmware code revision: %d\n",
data);
}
/* Check we are compatible with the loaded firmware */
data = coda_read(dev, CODA_CMD_FIRMWARE_VERNUM);
product = CODA_FIRMWARE_PRODUCT(data);
major = CODA_FIRMWARE_MAJOR(data);
minor = CODA_FIRMWARE_MINOR(data);
release = CODA_FIRMWARE_RELEASE(data);
coda_jpeg_write_tables(ctx); break; default:
v4l2_err(v4l2_dev, "dst format (0x%08x) invalid.\n", dst_fourcc);
ret = -EINVAL; goto out;
}
/* * slice mode and GOP size registers are used for thumb size/offset * in JPEG mode
*/ if (dst_fourcc != V4L2_PIX_FMT_JPEG) {
value = coda_slice_mode(ctx);
coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE);
value = ctx->params.gop_size;
coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE);
}
/* Save stream headers */
buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); switch (dst_fourcc) { case V4L2_PIX_FMT_H264: /* * Get SPS in the first frame and copy it to an * intermediate buffer.
*/
ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_SPS,
&ctx->vpu_header[0][0],
&ctx->vpu_header_size[0]); if (ret < 0) goto out;
/* * If visible width or height are not aligned to macroblock * size, the crop_right and crop_bottom SPS fields must be set * to the difference between visible and coded size. This is * only supported by CODA960 firmware. All others do not allow * writing frame cropping parameters, so we have to manually * fix up the SPS RBSP (Sequence Parameter Set Raw Byte * Sequence Payload) ourselves.
*/ if (ctx->dev->devtype->product != CODA_960 &&
((q_data_src->rect.width % 16) ||
(q_data_src->rect.height % 16))) {
ret = coda_h264_sps_fixup(ctx, q_data_src->rect.width,
q_data_src->rect.height,
&ctx->vpu_header[0][0],
&ctx->vpu_header_size[0], sizeof(ctx->vpu_header[0])); if (ret < 0) goto out;
}
/* * Get PPS in the first frame and copy it to an * intermediate buffer.
*/
ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_PPS,
&ctx->vpu_header[1][0],
&ctx->vpu_header_size[1]); if (ret < 0) goto out;
/* * Length of H.264 headers is variable and thus it might not be * aligned for the coda to append the encoded frame. In that is * the case a filler NAL must be added to header 2.
*/
ctx->vpu_header_size[2] = coda_h264_padding(
(ctx->vpu_header_size[0] +
ctx->vpu_header_size[1]),
ctx->vpu_header[2]); break; case V4L2_PIX_FMT_MPEG4: /* * Get VOS in the first frame and copy it to an * intermediate buffer
*/
ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOS,
&ctx->vpu_header[0][0],
&ctx->vpu_header_size[0]); if (ret < 0) goto out;
ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VIS,
&ctx->vpu_header[1][0],
&ctx->vpu_header_size[1]); if (ret < 0) goto out;
ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOL,
&ctx->vpu_header[2][0],
&ctx->vpu_header_size[2]); if (ret < 0) goto out; break; default: /* No more formats need to save headers at the moment */ break;
}
/* * Workaround coda firmware BUG that only marks the first * frame as IDR. This is a problem for some decoders that can't * recover when a frame is lost.
*/ if (!force_ipicture) {
src_buf->flags |= V4L2_BUF_FLAG_PFRAME;
src_buf->flags &= ~V4L2_BUF_FLAG_KEYFRAME;
} else {
src_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
src_buf->flags &= ~V4L2_BUF_FLAG_PFRAME;
}
if (dev->devtype->product == CODA_960)
coda_set_gdi_regs(ctx);
/* * Copy headers in front of the first frame and forced I frames for * H.264 only. In MPEG4 they are already copied by the CODA.
*/ if (src_buf->sequence == 0 || force_ipicture) {
pic_stream_buffer_addr =
vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0) +
ctx->vpu_header_size[0] +
ctx->vpu_header_size[1] +
ctx->vpu_header_size[2];
pic_stream_buffer_size = q_data_dst->sizeimage -
ctx->vpu_header_size[0] -
ctx->vpu_header_size[1] -
ctx->vpu_header_size[2];
memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0),
&ctx->vpu_header[0][0], ctx->vpu_header_size[0]);
memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0)
+ ctx->vpu_header_size[0], &ctx->vpu_header[1][0],
ctx->vpu_header_size[1]);
memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0)
+ ctx->vpu_header_size[0] + ctx->vpu_header_size[1],
&ctx->vpu_header[2][0], ctx->vpu_header_size[2]);
} else {
pic_stream_buffer_addr =
vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
pic_stream_buffer_size = q_data_dst->sizeimage;
}
if (force_ipicture) { switch (dst_fourcc) { case V4L2_PIX_FMT_H264:
quant_param = ctx->params.h264_intra_qp; break; case V4L2_PIX_FMT_MPEG4:
quant_param = ctx->params.mpeg4_intra_qp; break; case V4L2_PIX_FMT_JPEG:
quant_param = 30; break; default:
v4l2_warn(&ctx->dev->v4l2_dev, "cannot set intra qp, fmt not supported\n"); break;
}
} else { switch (dst_fourcc) { case V4L2_PIX_FMT_H264:
quant_param = ctx->params.h264_inter_qp; break; case V4L2_PIX_FMT_MPEG4:
quant_param = ctx->params.mpeg4_inter_qp; break; default:
v4l2_warn(&ctx->dev->v4l2_dev, "cannot set inter qp, fmt not supported\n"); break;
}
}
if (!ctx->streamon_out) { /* After streamoff on the output side, set stream end flag */
ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
coda_write(dev, ctx->bit_stream_param,
CODA_REG_BIT_BIT_STREAM_PARAM);
}
if (dev->devtype->product != CODA_DX6)
coda_write(dev, ctx->iram_info.axi_sram_use,
CODA7_REG_BIT_AXI_SRAM_USE);
/* * Lock to make sure that an encoder stop command running in parallel * will either already have marked src_buf as last, or it will wake up * the capture queue after the buffers are returned.
*/
mutex_lock(&ctx->wakeup_mutex);
src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
trace_coda_enc_pic_done(ctx, dst_buf);
/* Get results from the coda */
start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START);
wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
coda_dbg(1, ctx, "%s: sent command 'SEQ_END' to coda\n", __func__); if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) {
v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_SEQ_END failed\n");
}
/* * FIXME: Sometimes h.264 encoding fails with 8-byte sequences missing * from the output stream after the h.264 decoder has run. Resetting the * hardware after the decoder has finished seems to help.
*/ if (dev->devtype->product == CODA_960)
coda_hw_reset(ctx);
/* * All metas that end at or before the RD pointer (fifo out), * are now consumed by the VPU and should be released.
*/
spin_lock(&ctx->buffer_meta_lock);
list_for_each_entry_safe(meta, tmp, &ctx->buffer_meta_list, list) { if (ctx->bitstream_fifo.kfifo.out >= meta->end) {
coda_dbg(2, ctx, "releasing meta: seq=%d start=%d end=%d\n",
meta->sequence, meta->start, meta->end);
ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED); /* * If the VDOA is used, the decoder needs one additional frame, * because the frames are freed when the next frame is decoded. * Otherwise there are visible errors in the decoded frames (green * regions in displayed frames) and a broken order of frames (earlier * frames are sporadically displayed after later frames).
*/ if (ctx->use_vdoa)
ctx->num_internal_frames += 1; if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) {
v4l2_err(&dev->v4l2_dev, "not enough framebuffers to decode (%d < %d)\n",
CODA_MAX_FRAMEBUFFERS, ctx->num_internal_frames); return -EINVAL;
}
if (src_fourcc == V4L2_PIX_FMT_H264) {
u32 left_right;
u32 top_bottom;
ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc); if (ret < 0) {
v4l2_err(&dev->v4l2_dev, "failed to allocate framebuffers\n"); return ret;
}
/* Tell the decoder how many frame buffers we allocated. */
coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM);
coda_write(dev, round_up(q_data_dst->rect.width, 16),
CODA_CMD_SET_FRAME_BUF_STRIDE);
if (dev->devtype->product != CODA_DX6) { /* Set secondary AXI IRAM */
coda_setup_iram(ctx);
/* Run coda_start_decoding (again) if not yet initialized */ if (!ctx->initialized) { int ret = __coda_start_decoding(ctx);
if (ret < 0) {
v4l2_err(&dev->v4l2_dev, "failed to start decoding\n"); return -EAGAIN;
} else {
ctx->initialized = 1;
}
}
if (dev->devtype->product == CODA_960)
coda_set_gdi_regs(ctx);
if (ctx->use_vdoa &&
ctx->display_idx >= 0 &&
ctx->display_idx < ctx->num_internal_frames) {
vdoa_device_run(ctx->vdoa,
vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0),
ctx->internal_frames[ctx->display_idx].buf.paddr);
} else { if (dev->devtype->product == CODA_960) { /* * It was previously assumed that the CODA960 has an * internal list of 64 buffer entries that contains * both the registered internal frame buffers as well * as the rotator buffer output, and that the ROT_INDEX * register must be set to a value between the last * internal frame buffers' index and 64. * At least on firmware version 3.1.1 it turns out that * setting ROT_INDEX to any value >= 32 causes CODA * hangups that it can not recover from with the SRC VPU * reset. * It does appear to work however, to just set it to a * fixed value in the [ctx->num_internal_frames, 31] * range, for example CODA_MAX_FRAMEBUFFERS.
*/
coda_write(dev, CODA_MAX_FRAMEBUFFERS,
CODA9_CMD_DEC_PIC_ROT_INDEX);
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.