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);
if (dev->devtype->product != CODA_DX6)
coda_write(dev, ctx->iram_info.axi_sram_use,
CODA7_REG_BIT_AXI_SRAM_USE);
spin_lock(&ctx->buffer_meta_lock);
meta = list_first_entry_or_null(&ctx->buffer_meta_list, struct coda_buffer_meta, list);
if (meta && ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) {
/* If this is the last buffer in the bitstream, add padding */ if (meta->end == ctx->bitstream_fifo.kfifo.in) { staticunsignedchar buf[512]; unsignedint pad;
/* Pad to multiple of 256 and then add 256 more */
pad = ((0 - meta->end) & 0xff) + 256;
/* Clear decode success flag */
coda_write(dev, 0, CODA_RET_DEC_PIC_SUCCESS);
/* Clear error return value */
coda_write(dev, 0, CODA_RET_DEC_PIC_ERR_MB);
trace_coda_dec_pic_run(ctx, meta);
coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
return 0;
}
staticvoid coda_finish_decode(struct coda_ctx *ctx)
{ struct coda_dev *dev = ctx->dev; struct coda_q_data *q_data_src; struct coda_q_data *q_data_dst; struct vb2_v4l2_buffer *dst_buf; struct coda_buffer_meta *meta; int width, height; int decoded_idx; int display_idx; struct coda_internal_frame *decoded_frame = NULL;
u32 src_fourcc; int success;
u32 err_mb; int err_vdoa = 0;
u32 val;
if (ctx->aborting) return;
/* Update kfifo out pointer from coda bitstream read pointer */
coda_kfifo_sync_from_device(ctx);
/* * in stream-end mode, the read pointer can overshoot the write pointer * by up to 512 bytes
*/ if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) { if (coda_get_bitstream_payload(ctx) >= ctx->bitstream.size - 512)
kfifo_init(&ctx->bitstream_fifo,
ctx->bitstream.vaddr, ctx->bitstream.size);
}
/* The previous display frame was copied out and can be overwritten */ if (ctx->display_idx >= 0 &&
ctx->display_idx < ctx->num_internal_frames) {
ctx->frm_dis_flg &= ~(1 << ctx->display_idx);
coda_write(dev, ctx->frm_dis_flg,
CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
}
/* * The index of the last decoded frame, not necessarily in * display order, and the index of the next display frame. * The latter could have been decoded in a previous run.
*/
decoded_idx = coda_read(dev, CODA_RET_DEC_PIC_CUR_IDX);
display_idx = coda_read(dev, CODA_RET_DEC_PIC_FRAME_IDX);
if (decoded_idx == -1) { /* no frame was decoded, but we might have a display frame */ if (display_idx >= 0 && display_idx < ctx->num_internal_frames)
ctx->sequence_offset++; elseif (ctx->display_idx < 0)
ctx->hold = true;
} elseif (decoded_idx == -2) { if (ctx->display_idx >= 0 &&
ctx->display_idx < ctx->num_internal_frames)
ctx->sequence_offset++; /* no frame was decoded, we still return remaining buffers */
} elseif (decoded_idx < 0 || decoded_idx >= ctx->num_internal_frames) {
v4l2_err(&dev->v4l2_dev, "decoded frame index out of range: %d\n", decoded_idx);
} else { int sequence;
val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM); if (ctx->sequence_offset == -1)
ctx->sequence_offset = val;
sequence = val + ctx->first_frame_sequence
- ctx->sequence_offset;
spin_lock(&ctx->buffer_meta_lock); if (!list_empty(&ctx->buffer_meta_list)) {
meta = list_first_entry(&ctx->buffer_meta_list, struct coda_buffer_meta, list);
list_del(&meta->list);
ctx->num_metas--;
spin_unlock(&ctx->buffer_meta_lock); /* * Clamp counters to 16 bits for comparison, as the HW * counter rolls over at this point for h.264. This * may be different for other formats, but using 16 bits * should be enough to detect most errors and saves us * from doing different things based on the format.
*/ if ((sequence & 0xffff) != (meta->sequence & 0xffff)) {
v4l2_err(&dev->v4l2_dev, "sequence number mismatch (%d(%d) != %d)\n",
sequence, ctx->sequence_offset,
meta->sequence);
}
decoded_frame->meta = *meta;
kfree(meta);
} else {
spin_unlock(&ctx->buffer_meta_lock);
v4l2_err(&dev->v4l2_dev, "empty timestamp list!\n");
memset(&decoded_frame->meta, 0, sizeof(struct coda_buffer_meta));
decoded_frame->meta.sequence = sequence;
decoded_frame->meta.last = false;
ctx->sequence_offset++;
}
if (display_idx == -1) { /* * no more frames to be decoded, but there could still * be rotator output to dequeue
*/
ctx->hold = true;
} elseif (display_idx == -3) { /* possibly prescan failure */
} elseif (display_idx < 0 || display_idx >= ctx->num_internal_frames) {
v4l2_err(&dev->v4l2_dev, "presentation frame index out of range: %d\n",
display_idx);
}
/* If a frame was copied out, return it */ if (ctx->display_idx >= 0 &&
ctx->display_idx < ctx->num_internal_frames) { struct coda_internal_frame *ready_frame;
dst_buf->field = V4L2_FIELD_NONE;
dst_buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
V4L2_BUF_FLAG_PFRAME |
V4L2_BUF_FLAG_BFRAME);
dst_buf->flags |= ready_frame->type;
meta = &ready_frame->meta; if (meta->last && !coda_reorder_enable(ctx)) { /* * If this was the last decoded frame, and reordering * is disabled, this will be the last display frame.
*/
coda_dbg(1, ctx, "last meta, marking as last frame\n");
dst_buf->flags |= V4L2_BUF_FLAG_LAST;
} elseif (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG &&
display_idx == -1) { /* * If there is no designated presentation frame anymore, * this frame has to be the last one.
*/
coda_dbg(1, ctx, "no more frames to return, marking as last frame\n");
dst_buf->flags |= V4L2_BUF_FLAG_LAST;
}
dst_buf->timecode = meta->timecode;
dst_buf->vb2_buf.timestamp = meta->timestamp;
if (decoded_frame) {
coda_dbg(1, ctx, "job finished: decoded %c frame %u, returned %c frame %u (%u/%u)%s\n",
coda_frame_type_char(decoded_frame->type),
decoded_frame->meta.sequence,
coda_frame_type_char(dst_buf->flags),
ready_frame->meta.sequence,
dst_buf->sequence, ctx->qsequence,
(dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : "");
} else {
coda_dbg(1, ctx, "job finished: no frame decoded (%d), returned %c frame %u (%u/%u)%s\n",
decoded_idx,
coda_frame_type_char(dst_buf->flags),
ready_frame->meta.sequence,
dst_buf->sequence, ctx->qsequence,
(dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : "");
}
} else { if (decoded_frame) {
coda_dbg(1, ctx, "job finished: decoded %c frame %u, no frame returned (%d)\n",
coda_frame_type_char(decoded_frame->type),
decoded_frame->meta.sequence,
ctx->display_idx);
} else {
coda_dbg(1, ctx, "job finished: no frame decoded (%d) or returned (%d)\n",
decoded_idx, ctx->display_idx);
}
}
/* The rotator will copy the current display frame next time */
ctx->display_idx = display_idx;
/* * The current decode run might have brought the bitstream fill level * below the size where we can start the next decode run. As userspace * might have filled the output queue completely and might thus be * blocked, we can't rely on the next qbuf to trigger the bitstream * refill. Check if we have data to refill the bitstream now.
*/
mutex_lock(&ctx->bitstream_mutex);
coda_fill_bitstream(ctx, NULL);
mutex_unlock(&ctx->bitstream_mutex);
}
/* * For now this only handles the case where we would deadlock with * userspace, i.e. userspace issued DEC_CMD_STOP and waits for EOS, * but after a failed decode run we would hold the context and wait for * userspace to queue more buffers.
*/ if (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG)) return;
/* read status register to attend the IRQ */
coda_read(dev, CODA_REG_BIT_INT_STATUS);
coda_write(dev, 0, CODA_REG_BIT_INT_REASON);
coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET,
CODA_REG_BIT_INT_CLEAR);
ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); if (ctx == NULL) {
v4l2_err(&dev->v4l2_dev, "Instance released before the end of transaction\n"); return IRQ_HANDLED;
}
trace_coda_bit_done(ctx);
if (ctx->aborting) {
coda_dbg(1, ctx, "task has been aborted\n");
}
if (coda_isbusy(ctx->dev)) {
coda_dbg(1, ctx, "coda is still busy!!!!\n"); return IRQ_NONE;
}
complete(&ctx->completion);
return IRQ_HANDLED;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.30 Sekunden
(vorverarbeitet am 2026-04-25)
¤
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.