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 20namespace libvpx_test { 21 22static int 23nestegg_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 36static int 37nestegg_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 54static int64_t 55nestegg_tell_cb(void *userdata) { 56 FILE *f = reinterpret_cast<FILE *>(userdata); 57 return ftell(f); 58} 59 60 61static void 62nestegg_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. 74class WebMVideoSource : public CompressedVideoSource { 75 public: 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 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 101 virtual void Init() { 102 } 103 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 131 virtual void Next() { 132 ++frame_; 133 FillFrame(); 134 } 135 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 169 virtual const uint8_t *cxdata() const { 170 return end_of_file_ ? NULL : buf_; 171 } 172 virtual size_t frame_size() const { return buf_sz_; } 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