• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Coda multi-standard codec IP - H.264 helper functions
3  *
4  * Copyright (C) 2012 Vista Silicon S.L.
5  *    Javier Martin, <javier.martin@vista-silicon.com>
6  *    Xavier Duret
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  */
13 
14 #include <linux/kernel.h>
15 #include <linux/string.h>
16 #include <linux/videodev2.h>
17 #include <coda.h>
18 
19 static const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 };
20 
coda_find_nal_header(const u8 * buf,const u8 * end)21 static const u8 *coda_find_nal_header(const u8 *buf, const u8 *end)
22 {
23 	u32 val = 0xffffffff;
24 
25 	do {
26 		val = val << 8 | *buf++;
27 		if (buf >= end)
28 			return NULL;
29 	} while (val != 0x00000001);
30 
31 	return buf;
32 }
33 
coda_sps_parse_profile(struct coda_ctx * ctx,struct vb2_buffer * vb)34 int coda_sps_parse_profile(struct coda_ctx *ctx, struct vb2_buffer *vb)
35 {
36 	const u8 *buf = vb2_plane_vaddr(vb, 0);
37 	const u8 *end = buf + vb2_get_plane_payload(vb, 0);
38 
39 	/* Find SPS header */
40 	do {
41 		buf = coda_find_nal_header(buf, end);
42 		if (!buf)
43 			return -EINVAL;
44 	} while ((*buf++ & 0x1f) != 0x7);
45 
46 	ctx->params.h264_profile_idc = buf[0];
47 	ctx->params.h264_level_idc = buf[2];
48 
49 	return 0;
50 }
51 
coda_h264_filler_nal(int size,char * p)52 int coda_h264_filler_nal(int size, char *p)
53 {
54 	if (size < 6)
55 		return -EINVAL;
56 
57 	p[0] = 0x00;
58 	p[1] = 0x00;
59 	p[2] = 0x00;
60 	p[3] = 0x01;
61 	p[4] = 0x0c;
62 	memset(p + 5, 0xff, size - 6);
63 	/* Add rbsp stop bit and trailing at the end */
64 	p[size - 1] = 0x80;
65 
66 	return 0;
67 }
68 
coda_h264_padding(int size,char * p)69 int coda_h264_padding(int size, char *p)
70 {
71 	int nal_size;
72 	int diff;
73 
74 	diff = size - (size & ~0x7);
75 	if (diff == 0)
76 		return 0;
77 
78 	nal_size = coda_filler_size[diff];
79 	coda_h264_filler_nal(nal_size, p);
80 
81 	return nal_size;
82 }
83 
coda_h264_profile(int profile_idc)84 int coda_h264_profile(int profile_idc)
85 {
86 	switch (profile_idc) {
87 	case 66: return V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
88 	case 77: return V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
89 	case 88: return V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED;
90 	case 100: return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
91 	default: return -EINVAL;
92 	}
93 }
94 
coda_h264_level(int level_idc)95 int coda_h264_level(int level_idc)
96 {
97 	switch (level_idc) {
98 	case 10: return V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
99 	case 9:  return V4L2_MPEG_VIDEO_H264_LEVEL_1B;
100 	case 11: return V4L2_MPEG_VIDEO_H264_LEVEL_1_1;
101 	case 12: return V4L2_MPEG_VIDEO_H264_LEVEL_1_2;
102 	case 13: return V4L2_MPEG_VIDEO_H264_LEVEL_1_3;
103 	case 20: return V4L2_MPEG_VIDEO_H264_LEVEL_2_0;
104 	case 21: return V4L2_MPEG_VIDEO_H264_LEVEL_2_1;
105 	case 22: return V4L2_MPEG_VIDEO_H264_LEVEL_2_2;
106 	case 30: return V4L2_MPEG_VIDEO_H264_LEVEL_3_0;
107 	case 31: return V4L2_MPEG_VIDEO_H264_LEVEL_3_1;
108 	case 32: return V4L2_MPEG_VIDEO_H264_LEVEL_3_2;
109 	case 40: return V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
110 	case 41: return V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
111 	default: return -EINVAL;
112 	}
113 }
114