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