| // SPDX-License-Identifier: GPL-2.0-or-later |
| /* |
| * Coda multi-standard codec IP - MPEG-4 helper functions |
| * |
| * Copyright (C) 2019 Pengutronix, Philipp Zabel |
| */ |
| |
| #include <linux/kernel.h> |
| #include <linux/videodev2.h> |
| |
| #include "coda.h" |
| |
| int coda_mpeg4_profile(int profile_idc) |
| { |
| switch (profile_idc) { |
| case 0: |
| return V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE; |
| case 15: |
| return V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE; |
| case 2: |
| return V4L2_MPEG_VIDEO_MPEG4_PROFILE_CORE; |
| case 1: |
| return V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE; |
| case 11: |
| return V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY; |
| default: |
| return -EINVAL; |
| } |
| } |
| |
| int coda_mpeg4_level(int level_idc) |
| { |
| switch (level_idc) { |
| case 0: |
| return V4L2_MPEG_VIDEO_MPEG4_LEVEL_0; |
| case 1: |
| return V4L2_MPEG_VIDEO_MPEG4_LEVEL_1; |
| case 2: |
| return V4L2_MPEG_VIDEO_MPEG4_LEVEL_2; |
| case 3: |
| return V4L2_MPEG_VIDEO_MPEG4_LEVEL_3; |
| case 4: |
| return V4L2_MPEG_VIDEO_MPEG4_LEVEL_4; |
| case 5: |
| return V4L2_MPEG_VIDEO_MPEG4_LEVEL_5; |
| default: |
| return -EINVAL; |
| } |
| } |
| |
| /* |
| * Check if the buffer starts with the MPEG-4 visual object sequence and visual |
| * object headers, for example: |
| * |
| * 00 00 01 b0 f1 |
| * 00 00 01 b5 a9 13 00 00 01 00 00 00 01 20 08 |
| * d4 8d 88 00 f5 04 04 08 14 30 3f |
| * |
| * Returns the detected header size in bytes or 0. |
| */ |
| u32 coda_mpeg4_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size) |
| { |
| static const u8 vos_start[4] = { 0x00, 0x00, 0x01, 0xb0 }; |
| static const union { |
| u8 vo_start[4]; |
| u8 start_code_prefix[3]; |
| } u = { { 0x00, 0x00, 0x01, 0xb5 } }; |
| |
| if (size < 30 || |
| memcmp(buf, vos_start, 4) != 0 || |
| memcmp(buf + 5, u.vo_start, 4) != 0) |
| return 0; |
| |
| if (size == 30 || |
| (size >= 33 && memcmp(buf + 30, u.start_code_prefix, 3) == 0)) |
| return 30; |
| |
| if (size == 31 || |
| (size >= 34 && memcmp(buf + 31, u.start_code_prefix, 3) == 0)) |
| return 31; |
| |
| if (size == 32 || |
| (size >= 35 && memcmp(buf + 32, u.start_code_prefix, 3) == 0)) |
| return 32; |
| |
| return 0; |
| } |