1b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian/*
2b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
3b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *
4b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  Use of this source code is governed by a BSD-style license
5b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  that can be found in the LICENSE file in the root of the source
6b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  tree. An additional intellectual property rights grant can be found
7b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  in the file PATENTS.  All contributing project authors may
8b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  be found in the AUTHORS file in the root of the source tree.
9b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian */
10b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
11b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include <stdio.h>
12b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include <stdlib.h>
13b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include <string.h>
14b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
15b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include "vpx_ports/mem_ops.h"
16b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
17b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include "./ivfdec.h"
18b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
19b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic const char *IVF_SIGNATURE = "DKIF";
20b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
21b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic void fix_framerate(int *num, int *den) {
22b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  // Some versions of vpxenc used 1/(2*fps) for the timebase, so
23b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  // we can guess the framerate using only the timebase in this
24b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  // case. Other files would require reading ahead to guess the
25b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  // timebase, like we do for webm.
26b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (*num < 1000) {
27b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    // Correct for the factor of 2 applied to the timebase in the encoder.
28b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (*num & 1)
29b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      *den *= 2;
30b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    else
31b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      *num /= 2;
32b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  } else {
33b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    // Don't know FPS for sure, and don't have readahead code
34b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    // (yet?), so just default to 30fps.
35b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    *num = 30;
36b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    *den = 1;
37b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  }
38b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
39b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
40b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianint file_is_ivf(struct VpxInputContext *input_ctx) {
41b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  char raw_hdr[32];
42b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  int is_ivf = 0;
43b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
44b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (fread(raw_hdr, 1, 32, input_ctx->file) == 32) {
45b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (memcmp(IVF_SIGNATURE, raw_hdr, 4) == 0) {
46b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      is_ivf = 1;
47b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
48b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if (mem_get_le16(raw_hdr + 4) != 0) {
49b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        fprintf(stderr, "Error: Unrecognized IVF version! This file may not"
50b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                " decode properly.");
51b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      }
52b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
53b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      input_ctx->fourcc = mem_get_le32(raw_hdr + 8);
54b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      input_ctx->width = mem_get_le16(raw_hdr + 12);
55b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      input_ctx->height = mem_get_le16(raw_hdr + 14);
56b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      input_ctx->framerate.numerator = mem_get_le32(raw_hdr + 16);
57b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      input_ctx->framerate.denominator = mem_get_le32(raw_hdr + 20);
58b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      fix_framerate(&input_ctx->framerate.numerator,
59b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                    &input_ctx->framerate.denominator);
60b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    }
61b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  }
62b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
63b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (!is_ivf) {
64b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    rewind(input_ctx->file);
65b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    input_ctx->detect.buf_read = 0;
66b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  } else {
67b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    input_ctx->detect.position = 4;
68b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  }
69b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return is_ivf;
70b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
71b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
72b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianint ivf_read_frame(FILE *infile, uint8_t **buffer,
73b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                   size_t *bytes_read, size_t *buffer_size) {
74b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  char raw_header[IVF_FRAME_HDR_SZ] = {0};
75b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  size_t frame_size = 0;
76b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
77b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (fread(raw_header, IVF_FRAME_HDR_SZ, 1, infile) != 1) {
78b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (!feof(infile))
79b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      warn("Failed to read frame size\n");
80b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  } else {
81b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    frame_size = mem_get_le32(raw_header);
82b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
83b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (frame_size > 256 * 1024 * 1024) {
84b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      warn("Read invalid frame size (%u)\n", (unsigned int)frame_size);
85b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      frame_size = 0;
86b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    }
87b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
88b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (frame_size > *buffer_size) {
89b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      uint8_t *new_buffer = realloc(*buffer, 2 * frame_size);
90b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
91b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if (new_buffer) {
92b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        *buffer = new_buffer;
93b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        *buffer_size = 2 * frame_size;
94b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      } else {
95b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        warn("Failed to allocate compressed data buffer\n");
96b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        frame_size = 0;
97b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      }
98b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    }
99b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  }
100b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
101b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (!feof(infile)) {
102b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (fread(*buffer, 1, frame_size, infile) != frame_size) {
103b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      warn("Failed to read full frame\n");
104b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return 1;
105b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    }
106b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
107b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    *bytes_read = frame_size;
108b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return 0;
109b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  }
110b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
111b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return 1;
112b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
113