/* * Copyright (c) 2012 The WebM project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef TEST_WEBM_VIDEO_SOURCE_H_ #define TEST_WEBM_VIDEO_SOURCE_H_ #include #include #include #include #include #include "nestegg/include/nestegg/nestegg.h" #include "test/video_source.h" namespace libvpx_test { static int nestegg_read_cb(void *buffer, size_t length, void *userdata) { FILE *f = reinterpret_cast(userdata); if (fread(buffer, 1, length, f) < length) { if (ferror(f)) return -1; if (feof(f)) return 0; } return 1; } static int nestegg_seek_cb(int64_t offset, int whence, void *userdata) { FILE *f = reinterpret_cast(userdata); switch (whence) { case NESTEGG_SEEK_SET: whence = SEEK_SET; break; case NESTEGG_SEEK_CUR: whence = SEEK_CUR; break; case NESTEGG_SEEK_END: whence = SEEK_END; break; }; return fseek(f, (long)offset, whence) ? -1 : 0; } static int64_t nestegg_tell_cb(void *userdata) { FILE *f = reinterpret_cast(userdata); return ftell(f); } static void nestegg_log_cb(nestegg *context, unsigned int severity, char const *format, ...) { va_list ap; va_start(ap, format); vfprintf(stderr, format, ap); fprintf(stderr, "\n"); va_end(ap); } // This class extends VideoSource to allow parsing of WebM files, // so that we can do actual file decodes. class WebMVideoSource : public CompressedVideoSource { public: explicit WebMVideoSource(const std::string &file_name) : file_name_(file_name), input_file_(NULL), nestegg_ctx_(NULL), pkt_(NULL), video_track_(0), chunk_(0), chunks_(0), buf_(NULL), buf_sz_(0), frame_(0), end_of_file_(false) { } virtual ~WebMVideoSource() { if (input_file_) fclose(input_file_); if (nestegg_ctx_) nestegg_destroy(nestegg_ctx_); } virtual void Init() { } virtual void Begin() { input_file_ = OpenTestDataFile(file_name_); ASSERT_TRUE(input_file_ != NULL) << "Input file open failed. Filename: " << file_name_; nestegg_io io = {nestegg_read_cb, nestegg_seek_cb, nestegg_tell_cb, input_file_}; ASSERT_FALSE(nestegg_init(&nestegg_ctx_, io, NULL)) << "nestegg_init failed"; unsigned int n; ASSERT_FALSE(nestegg_track_count(nestegg_ctx_, &n)) << "failed to get track count"; for (unsigned int i = 0; i < n; i++) { int track_type = nestegg_track_type(nestegg_ctx_, i); ASSERT_GE(track_type, 0) << "failed to get track type"; if (track_type == NESTEGG_TRACK_VIDEO) { video_track_ = i; break; } } FillFrame(); } virtual void Next() { ++frame_; FillFrame(); } void FillFrame() { ASSERT_TRUE(input_file_ != NULL); if (chunk_ >= chunks_) { unsigned int track; do { /* End of this packet, get another. */ if (pkt_) nestegg_free_packet(pkt_); int again = nestegg_read_packet(nestegg_ctx_, &pkt_); ASSERT_GE(again, 0) << "nestegg_read_packet failed"; if (!again) { end_of_file_ = true; return; } ASSERT_FALSE(nestegg_packet_track(pkt_, &track)) << "nestegg_packet_track failed"; } while (track != video_track_); ASSERT_FALSE(nestegg_packet_count(pkt_, &chunks_)) << "nestegg_packet_count failed"; chunk_ = 0; } ASSERT_FALSE(nestegg_packet_data(pkt_, chunk_, &buf_, &buf_sz_)) << "nestegg_packet_data failed"; chunk_++; } virtual const uint8_t *cxdata() const { return end_of_file_ ? NULL : buf_; } virtual const unsigned int frame_size() const { return buf_sz_; } virtual const unsigned int frame_number() const { return frame_; } protected: std::string file_name_; FILE *input_file_; nestegg *nestegg_ctx_; nestegg_packet *pkt_; unsigned int video_track_; unsigned int chunk_; unsigned int chunks_; uint8_t *buf_; size_t buf_sz_; unsigned int frame_; bool end_of_file_; }; } // namespace libvpx_test #endif // TEST_WEBM_VIDEO_SOURCE_H_