forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
2.8 KiB
152 lines
2.8 KiB
// SPDX-License-Identifier: GPL-2.0-only |
|
/* |
|
* Copyright (c) 2016 MediaTek Inc. |
|
* Author: Ming Hsiu Tsai <[email protected]> |
|
* Rick Chang <[email protected]> |
|
*/ |
|
|
|
#include <linux/kernel.h> |
|
#include <linux/videodev2.h> |
|
|
|
#include "mtk_jpeg_dec_parse.h" |
|
|
|
#define TEM 0x01 |
|
#define SOF0 0xc0 |
|
#define RST 0xd0 |
|
#define SOI 0xd8 |
|
#define EOI 0xd9 |
|
|
|
struct mtk_jpeg_stream { |
|
u8 *addr; |
|
u32 size; |
|
u32 curr; |
|
}; |
|
|
|
static int read_byte(struct mtk_jpeg_stream *stream) |
|
{ |
|
if (stream->curr >= stream->size) |
|
return -1; |
|
return stream->addr[stream->curr++]; |
|
} |
|
|
|
static int read_word_be(struct mtk_jpeg_stream *stream, u32 *word) |
|
{ |
|
u32 temp; |
|
int byte; |
|
|
|
byte = read_byte(stream); |
|
if (byte == -1) |
|
return -1; |
|
temp = byte << 8; |
|
byte = read_byte(stream); |
|
if (byte == -1) |
|
return -1; |
|
*word = (u32)byte | temp; |
|
|
|
return 0; |
|
} |
|
|
|
static void read_skip(struct mtk_jpeg_stream *stream, long len) |
|
{ |
|
if (len <= 0) |
|
return; |
|
while (len--) |
|
read_byte(stream); |
|
} |
|
|
|
static bool mtk_jpeg_do_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va, |
|
u32 src_size) |
|
{ |
|
bool notfound = true; |
|
struct mtk_jpeg_stream stream; |
|
|
|
stream.addr = src_addr_va; |
|
stream.size = src_size; |
|
stream.curr = 0; |
|
|
|
while (notfound) { |
|
int i, length, byte; |
|
u32 word; |
|
|
|
byte = read_byte(&stream); |
|
if (byte == -1) |
|
return false; |
|
if (byte != 0xff) |
|
continue; |
|
do |
|
byte = read_byte(&stream); |
|
while (byte == 0xff); |
|
if (byte == -1) |
|
return false; |
|
if (byte == 0) |
|
continue; |
|
|
|
length = 0; |
|
switch (byte) { |
|
case SOF0: |
|
/* length */ |
|
if (read_word_be(&stream, &word)) |
|
break; |
|
|
|
/* precision */ |
|
if (read_byte(&stream) == -1) |
|
break; |
|
|
|
if (read_word_be(&stream, &word)) |
|
break; |
|
param->pic_h = word; |
|
|
|
if (read_word_be(&stream, &word)) |
|
break; |
|
param->pic_w = word; |
|
|
|
param->comp_num = read_byte(&stream); |
|
if (param->comp_num != 1 && param->comp_num != 3) |
|
break; |
|
|
|
for (i = 0; i < param->comp_num; i++) { |
|
param->comp_id[i] = read_byte(&stream); |
|
if (param->comp_id[i] == -1) |
|
break; |
|
|
|
/* sampling */ |
|
byte = read_byte(&stream); |
|
if (byte == -1) |
|
break; |
|
param->sampling_w[i] = (byte >> 4) & 0x0F; |
|
param->sampling_h[i] = byte & 0x0F; |
|
|
|
param->qtbl_num[i] = read_byte(&stream); |
|
if (param->qtbl_num[i] == -1) |
|
break; |
|
} |
|
|
|
notfound = !(i == param->comp_num); |
|
break; |
|
case RST ... RST + 7: |
|
case SOI: |
|
case EOI: |
|
case TEM: |
|
break; |
|
default: |
|
if (read_word_be(&stream, &word)) |
|
break; |
|
length = (long)word - 2; |
|
read_skip(&stream, length); |
|
break; |
|
} |
|
} |
|
|
|
return !notfound; |
|
} |
|
|
|
bool mtk_jpeg_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va, |
|
u32 src_size) |
|
{ |
|
if (!mtk_jpeg_do_parse(param, src_addr_va, src_size)) |
|
return false; |
|
if (mtk_jpeg_dec_fill_param(param)) |
|
return false; |
|
|
|
return true; |
|
}
|
|
|