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