• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2012 The WebM 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 #ifndef TEST_WEBM_VIDEO_SOURCE_H_
11 #define TEST_WEBM_VIDEO_SOURCE_H_
12 #include <cstdarg>
13 #include <cstdio>
14 #include <cstdlib>
15 #include <new>
16 #include <string>
17 #include "third_party/nestegg/include/nestegg/nestegg.h"
18 #include "test/video_source.h"
19 
20 namespace libvpx_test {
21 
22 static int
nestegg_read_cb(void * buffer,size_t length,void * userdata)23 nestegg_read_cb(void *buffer, size_t length, void *userdata) {
24   FILE *f = reinterpret_cast<FILE *>(userdata);
25 
26   if (fread(buffer, 1, length, f) < length) {
27     if (ferror(f))
28       return -1;
29     if (feof(f))
30       return 0;
31   }
32   return 1;
33 }
34 
35 
36 static int
nestegg_seek_cb(int64_t offset,int whence,void * userdata)37 nestegg_seek_cb(int64_t offset, int whence, void *userdata) {
38   FILE *f = reinterpret_cast<FILE *>(userdata);
39   switch (whence) {
40     case NESTEGG_SEEK_SET:
41       whence = SEEK_SET;
42       break;
43     case NESTEGG_SEEK_CUR:
44       whence = SEEK_CUR;
45       break;
46     case NESTEGG_SEEK_END:
47       whence = SEEK_END;
48       break;
49   };
50   return fseek(f, (long)offset, whence) ? -1 : 0;
51 }
52 
53 
54 static int64_t
nestegg_tell_cb(void * userdata)55 nestegg_tell_cb(void *userdata) {
56   FILE *f = reinterpret_cast<FILE *>(userdata);
57   return ftell(f);
58 }
59 
60 
61 static void
nestegg_log_cb(nestegg * context,unsigned int severity,char const * format,...)62 nestegg_log_cb(nestegg *context, unsigned int severity, char const *format,
63                ...) {
64   va_list ap;
65 
66   va_start(ap, format);
67   vfprintf(stderr, format, ap);
68   fprintf(stderr, "\n");
69   va_end(ap);
70 }
71 
72 // This class extends VideoSource to allow parsing of WebM files,
73 // so that we can do actual file decodes.
74 class WebMVideoSource : public CompressedVideoSource {
75  public:
WebMVideoSource(const std::string & file_name)76   explicit WebMVideoSource(const std::string &file_name)
77       : file_name_(file_name),
78         input_file_(NULL),
79         nestegg_ctx_(NULL),
80         pkt_(NULL),
81         video_track_(0),
82         chunk_(0),
83         chunks_(0),
84         buf_(NULL),
85         buf_sz_(0),
86         frame_(0),
87         end_of_file_(false) {
88   }
89 
~WebMVideoSource()90   virtual ~WebMVideoSource() {
91     if (input_file_)
92       fclose(input_file_);
93     if (nestegg_ctx_ != NULL) {
94       if (pkt_ != NULL) {
95         nestegg_free_packet(pkt_);
96       }
97       nestegg_destroy(nestegg_ctx_);
98     }
99   }
100 
Init()101   virtual void Init() {
102   }
103 
Begin()104   virtual void Begin() {
105     input_file_ = OpenTestDataFile(file_name_);
106     ASSERT_TRUE(input_file_ != NULL) << "Input file open failed. Filename: "
107         << file_name_;
108 
109     nestegg_io io = {nestegg_read_cb, nestegg_seek_cb, nestegg_tell_cb,
110                      input_file_};
111     ASSERT_FALSE(nestegg_init(&nestegg_ctx_, io, NULL, -1))
112         << "nestegg_init failed";
113 
114     unsigned int n;
115     ASSERT_FALSE(nestegg_track_count(nestegg_ctx_, &n))
116         << "failed to get track count";
117 
118     for (unsigned int i = 0; i < n; i++) {
119       int track_type = nestegg_track_type(nestegg_ctx_, i);
120       ASSERT_GE(track_type, 0) << "failed to get track type";
121 
122       if (track_type == NESTEGG_TRACK_VIDEO) {
123         video_track_ = i;
124         break;
125       }
126     }
127 
128     FillFrame();
129   }
130 
Next()131   virtual void Next() {
132     ++frame_;
133     FillFrame();
134   }
135 
FillFrame()136   void FillFrame() {
137     ASSERT_TRUE(input_file_ != NULL);
138     if (chunk_ >= chunks_) {
139       unsigned int track;
140 
141       do {
142         /* End of this packet, get another. */
143         if (pkt_ != NULL) {
144           nestegg_free_packet(pkt_);
145           pkt_ = NULL;
146         }
147 
148         int again = nestegg_read_packet(nestegg_ctx_, &pkt_);
149         ASSERT_GE(again, 0) << "nestegg_read_packet failed";
150         if (!again) {
151           end_of_file_ = true;
152           return;
153         }
154 
155         ASSERT_FALSE(nestegg_packet_track(pkt_, &track))
156             << "nestegg_packet_track failed";
157       } while (track != video_track_);
158 
159       ASSERT_FALSE(nestegg_packet_count(pkt_, &chunks_))
160           << "nestegg_packet_count failed";
161       chunk_ = 0;
162     }
163 
164     ASSERT_FALSE(nestegg_packet_data(pkt_, chunk_, &buf_, &buf_sz_))
165         << "nestegg_packet_data failed";
166     chunk_++;
167   }
168 
cxdata()169   virtual const uint8_t *cxdata() const {
170     return end_of_file_ ? NULL : buf_;
171   }
frame_size()172   virtual size_t frame_size() const { return buf_sz_; }
frame_number()173   virtual unsigned int frame_number() const { return frame_; }
174 
175  protected:
176   std::string file_name_;
177   FILE *input_file_;
178   nestegg *nestegg_ctx_;
179   nestegg_packet *pkt_;
180   unsigned int video_track_;
181   unsigned int chunk_;
182   unsigned int chunks_;
183   uint8_t *buf_;
184   size_t buf_sz_;
185   unsigned int frame_;
186   bool end_of_file_;
187 };
188 
189 }  // namespace libvpx_test
190 
191 #endif  // TEST_WEBM_VIDEO_SOURCE_H_
192