Home | History | Annotate | Download | only in test
      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
     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
     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
     55 nestegg_tell_cb(void *userdata) {
     56   FILE *f = reinterpret_cast<FILE *>(userdata);
     57   return ftell(f);
     58 }
     59 
     60 
     61 static void
     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:
     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