1 /*
2 * Copyright 2012 The LibYuv Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "libyuv/mjpeg_decoder.h"
12
13 #include <string.h> // For memchr.
14
15 #ifdef __cplusplus
16 namespace libyuv {
17 extern "C" {
18 #endif
19
20 // Enable this to try scasb implementation.
21 // #define ENABLE_SCASB 1
22
23 #ifdef ENABLE_SCASB
24
25 // Multiple of 1.
26 __declspec(naked)
ScanRow_ERMS(const uint8 * src,uint32 val,int count)27 const uint8* ScanRow_ERMS(const uint8* src, uint32 val, int count) {
28 __asm {
29 mov edx, edi
30 mov edi, [esp + 4] // src
31 mov eax, [esp + 8] // val
32 mov ecx, [esp + 12] // count
33 repne scasb
34 jne sr99
35 mov eax, edi
36 sub eax, 1
37 mov edi, edx
38 ret
39
40 sr99:
41 mov eax, 0
42 mov edi, edx
43 ret
44 }
45 }
46 #endif
47
48 // Helper function to scan for EOI marker.
ScanEOI(const uint8 * sample,size_t sample_size)49 static LIBYUV_BOOL ScanEOI(const uint8* sample, size_t sample_size) {
50 const uint8* end = sample + sample_size - 1;
51 const uint8* it = sample;
52 for (;;) {
53 #ifdef ENABLE_SCASB
54 it = ScanRow_ERMS(it, 0xff, end - it);
55 #else
56 it = static_cast<const uint8*>(memchr(it, 0xff, end - it));
57 #endif
58 if (it == NULL) {
59 break;
60 }
61 if (it[1] == 0xd9) {
62 return LIBYUV_TRUE; // Success: Valid jpeg.
63 }
64 ++it; // Skip over current 0xff.
65 }
66 // ERROR: Invalid jpeg end code not found. Size sample_size
67 return LIBYUV_FALSE;
68 }
69
70 // Helper function to validate the jpeg appears intact.
ValidateJpeg(const uint8 * sample,size_t sample_size)71 LIBYUV_BOOL ValidateJpeg(const uint8* sample, size_t sample_size) {
72 const size_t kBackSearchSize = 1024;
73 if (sample_size < 64) {
74 // ERROR: Invalid jpeg size: sample_size
75 return LIBYUV_FALSE;
76 }
77 if (sample[0] != 0xff || sample[1] != 0xd8) { // Start Of Image
78 // ERROR: Invalid jpeg initial start code
79 return LIBYUV_FALSE;
80 }
81 // Step over SOI marker.
82 sample += 2;
83 sample_size -= 2;
84
85 // Look for the End Of Image (EOI) marker in the end kilobyte of the buffer.
86 if (sample_size > kBackSearchSize) {
87 if (ScanEOI(sample + sample_size - kBackSearchSize, kBackSearchSize)) {
88 return LIBYUV_TRUE; // Success: Valid jpeg.
89 }
90 // Reduce search size for forward search.
91 sample_size = sample_size - kBackSearchSize + 1;
92 }
93 return ScanEOI(sample, sample_size);
94
95 }
96
97 #ifdef __cplusplus
98 } // extern "C"
99 } // namespace libyuv
100 #endif
101
102