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 "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_) 94 nestegg_destroy(nestegg_ctx_); 95 } 96 97 virtual void Init() { 98 } 99 100 virtual void Begin() { 101 input_file_ = OpenTestDataFile(file_name_); 102 ASSERT_TRUE(input_file_ != NULL) << "Input file open failed. Filename: " 103 << file_name_; 104 105 nestegg_io io = {nestegg_read_cb, nestegg_seek_cb, nestegg_tell_cb, 106 input_file_}; 107 ASSERT_FALSE(nestegg_init(&nestegg_ctx_, io, NULL)) 108 << "nestegg_init failed"; 109 110 unsigned int n; 111 ASSERT_FALSE(nestegg_track_count(nestegg_ctx_, &n)) 112 << "failed to get track count"; 113 114 for (unsigned int i = 0; i < n; i++) { 115 int track_type = nestegg_track_type(nestegg_ctx_, i); 116 ASSERT_GE(track_type, 0) << "failed to get track type"; 117 118 if (track_type == NESTEGG_TRACK_VIDEO) { 119 video_track_ = i; 120 break; 121 } 122 } 123 124 FillFrame(); 125 } 126 127 virtual void Next() { 128 ++frame_; 129 FillFrame(); 130 } 131 132 void FillFrame() { 133 ASSERT_TRUE(input_file_ != NULL); 134 if (chunk_ >= chunks_) { 135 unsigned int track; 136 137 do { 138 /* End of this packet, get another. */ 139 if (pkt_) 140 nestegg_free_packet(pkt_); 141 142 int again = nestegg_read_packet(nestegg_ctx_, &pkt_); 143 ASSERT_GE(again, 0) << "nestegg_read_packet failed"; 144 if (!again) { 145 end_of_file_ = true; 146 return; 147 } 148 149 ASSERT_FALSE(nestegg_packet_track(pkt_, &track)) 150 << "nestegg_packet_track failed"; 151 } while (track != video_track_); 152 153 ASSERT_FALSE(nestegg_packet_count(pkt_, &chunks_)) 154 << "nestegg_packet_count failed"; 155 chunk_ = 0; 156 } 157 158 ASSERT_FALSE(nestegg_packet_data(pkt_, chunk_, &buf_, &buf_sz_)) 159 << "nestegg_packet_data failed"; 160 chunk_++; 161 } 162 163 virtual const uint8_t *cxdata() const { 164 return end_of_file_ ? NULL : buf_; 165 } 166 virtual const unsigned int frame_size() const { return buf_sz_; } 167 virtual const unsigned int frame_number() const { return frame_; } 168 169 protected: 170 std::string file_name_; 171 FILE *input_file_; 172 nestegg *nestegg_ctx_; 173 nestegg_packet *pkt_; 174 unsigned int video_track_; 175 unsigned int chunk_; 176 unsigned int chunks_; 177 uint8_t *buf_; 178 size_t buf_sz_; 179 unsigned int frame_; 180 bool end_of_file_; 181}; 182 183} // namespace libvpx_test 184 185#endif // TEST_WEBM_VIDEO_SOURCE_H_ 186