1 /*
2  * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 #ifndef AOM_TEST_IVF_VIDEO_SOURCE_H_
12 #define AOM_TEST_IVF_VIDEO_SOURCE_H_
13 
14 #include <cstdio>
15 #include <cstdlib>
16 #include <new>
17 #include <string>
18 
19 #include "aom_ports/sanitizer.h"
20 #include "test/video_source.h"
21 
22 namespace libaom_test {
23 const unsigned int kCodeBufferSize = 256 * 1024 * 1024;
24 const unsigned int kIvfFileHdrSize = 32;
25 const unsigned int kIvfFrameHdrSize = 12;
26 
MemGetLe32(const uint8_t * mem)27 static unsigned int MemGetLe32(const uint8_t *mem) {
28   return (mem[3] << 24) | (mem[2] << 16) | (mem[1] << 8) | (mem[0]);
29 }
30 
31 // This class extends VideoSource to allow parsing of ivf files,
32 // so that we can do actual file decodes.
33 class IVFVideoSource : public CompressedVideoSource {
34  public:
IVFVideoSource(const std::string & file_name)35   explicit IVFVideoSource(const std::string &file_name)
36       : file_name_(file_name), input_file_(NULL), compressed_frame_buf_(NULL),
37         frame_sz_(0), frame_(0), end_of_file_(false) {}
38 
~IVFVideoSource()39   virtual ~IVFVideoSource() {
40     delete[] compressed_frame_buf_;
41 
42     if (input_file_) fclose(input_file_);
43   }
44 
Init()45   virtual void Init() {
46     // Allocate a buffer for read in the compressed video frame.
47     compressed_frame_buf_ = new uint8_t[kCodeBufferSize];
48     ASSERT_TRUE(compressed_frame_buf_ != NULL)
49         << "Allocate frame buffer failed";
50     ASAN_POISON_MEMORY_REGION(compressed_frame_buf_, kCodeBufferSize);
51   }
52 
Begin()53   virtual void Begin() {
54     input_file_ = OpenTestDataFile(file_name_);
55     ASSERT_TRUE(input_file_ != NULL)
56         << "Input file open failed. Filename: " << file_name_;
57 
58     // Read file header
59     uint8_t file_hdr[kIvfFileHdrSize];
60     ASSERT_EQ(kIvfFileHdrSize, fread(file_hdr, 1, kIvfFileHdrSize, input_file_))
61         << "File header read failed.";
62     // Check file header
63     ASSERT_TRUE(file_hdr[0] == 'D' && file_hdr[1] == 'K' &&
64                 file_hdr[2] == 'I' && file_hdr[3] == 'F')
65         << "Input is not an IVF file.";
66 
67     FillFrame();
68   }
69 
Next()70   virtual void Next() {
71     ++frame_;
72     FillFrame();
73   }
74 
FillFrame()75   void FillFrame() {
76     ASSERT_TRUE(input_file_ != NULL);
77     uint8_t frame_hdr[kIvfFrameHdrSize];
78     // Check frame header and read a frame from input_file.
79     if (fread(frame_hdr, 1, kIvfFrameHdrSize, input_file_) !=
80         kIvfFrameHdrSize) {
81       end_of_file_ = true;
82     } else {
83       end_of_file_ = false;
84 
85       frame_sz_ = MemGetLe32(frame_hdr);
86       ASSERT_LE(frame_sz_, kCodeBufferSize)
87           << "Frame is too big for allocated code buffer";
88       ASAN_UNPOISON_MEMORY_REGION(compressed_frame_buf_, kCodeBufferSize);
89       ASSERT_EQ(frame_sz_,
90                 fread(compressed_frame_buf_, 1, frame_sz_, input_file_))
91           << "Failed to read complete frame";
92       ASAN_POISON_MEMORY_REGION(compressed_frame_buf_ + frame_sz_,
93                                 kCodeBufferSize - frame_sz_);
94     }
95   }
96 
cxdata()97   virtual const uint8_t *cxdata() const {
98     return end_of_file_ ? NULL : compressed_frame_buf_;
99   }
frame_size()100   virtual size_t frame_size() const { return frame_sz_; }
frame_number()101   virtual unsigned int frame_number() const { return frame_; }
102 
103  protected:
104   std::string file_name_;
105   FILE *input_file_;
106   uint8_t *compressed_frame_buf_;
107   size_t frame_sz_;
108   unsigned int frame_;
109   bool end_of_file_;
110 };
111 
112 }  // namespace libaom_test
113 
114 #endif  // AOM_TEST_IVF_VIDEO_SOURCE_H_
115