forked from Minki/linux
691222713d
With reordering enabled, the sequence init in CODA960 firmware requests an unreasonable number of internal frames for some baseline profile streams. Disabling the reordering feature manually if baseline streams are detected fixes this problem. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
114 lines
2.7 KiB
C
114 lines
2.7 KiB
C
/*
|
|
* Coda multi-standard codec IP - H.264 helper functions
|
|
*
|
|
* Copyright (C) 2012 Vista Silicon S.L.
|
|
* Javier Martin, <javier.martin@vista-silicon.com>
|
|
* Xavier Duret
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/string.h>
|
|
#include <linux/videodev2.h>
|
|
#include <coda.h>
|
|
|
|
static const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 };
|
|
|
|
static const u8 *coda_find_nal_header(const u8 *buf, const u8 *end)
|
|
{
|
|
u32 val = 0xffffffff;
|
|
|
|
do {
|
|
val = val << 8 | *buf++;
|
|
if (buf >= end)
|
|
return NULL;
|
|
} while (val != 0x00000001);
|
|
|
|
return buf;
|
|
}
|
|
|
|
int coda_sps_parse_profile(struct coda_ctx *ctx, struct vb2_buffer *vb)
|
|
{
|
|
const u8 *buf = vb2_plane_vaddr(vb, 0);
|
|
const u8 *end = buf + vb2_get_plane_payload(vb, 0);
|
|
|
|
/* Find SPS header */
|
|
do {
|
|
buf = coda_find_nal_header(buf, end);
|
|
if (!buf)
|
|
return -EINVAL;
|
|
} while ((*buf++ & 0x1f) != 0x7);
|
|
|
|
ctx->params.h264_profile_idc = buf[0];
|
|
ctx->params.h264_level_idc = buf[2];
|
|
|
|
return 0;
|
|
}
|
|
|
|
int coda_h264_filler_nal(int size, char *p)
|
|
{
|
|
if (size < 6)
|
|
return -EINVAL;
|
|
|
|
p[0] = 0x00;
|
|
p[1] = 0x00;
|
|
p[2] = 0x00;
|
|
p[3] = 0x01;
|
|
p[4] = 0x0c;
|
|
memset(p + 5, 0xff, size - 6);
|
|
/* Add rbsp stop bit and trailing at the end */
|
|
p[size - 1] = 0x80;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int coda_h264_padding(int size, char *p)
|
|
{
|
|
int nal_size;
|
|
int diff;
|
|
|
|
diff = size - (size & ~0x7);
|
|
if (diff == 0)
|
|
return 0;
|
|
|
|
nal_size = coda_filler_size[diff];
|
|
coda_h264_filler_nal(nal_size, p);
|
|
|
|
return nal_size;
|
|
}
|
|
|
|
int coda_h264_profile(int profile_idc)
|
|
{
|
|
switch (profile_idc) {
|
|
case 66: return V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
|
|
case 77: return V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
|
|
case 88: return V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED;
|
|
case 100: return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
|
|
default: return -EINVAL;
|
|
}
|
|
}
|
|
|
|
int coda_h264_level(int level_idc)
|
|
{
|
|
switch (level_idc) {
|
|
case 10: return V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
|
|
case 9: return V4L2_MPEG_VIDEO_H264_LEVEL_1B;
|
|
case 11: return V4L2_MPEG_VIDEO_H264_LEVEL_1_1;
|
|
case 12: return V4L2_MPEG_VIDEO_H264_LEVEL_1_2;
|
|
case 13: return V4L2_MPEG_VIDEO_H264_LEVEL_1_3;
|
|
case 20: return V4L2_MPEG_VIDEO_H264_LEVEL_2_0;
|
|
case 21: return V4L2_MPEG_VIDEO_H264_LEVEL_2_1;
|
|
case 22: return V4L2_MPEG_VIDEO_H264_LEVEL_2_2;
|
|
case 30: return V4L2_MPEG_VIDEO_H264_LEVEL_3_0;
|
|
case 31: return V4L2_MPEG_VIDEO_H264_LEVEL_3_1;
|
|
case 32: return V4L2_MPEG_VIDEO_H264_LEVEL_3_2;
|
|
case 40: return V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
|
|
case 41: return V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
|
|
default: return -EINVAL;
|
|
}
|
|
}
|