2 * Copyright (c) 2013 The WebM project authors. All Rights Reserved.
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.
11 #include "./webmdec.h"
15 #include "third_party/nestegg/include/nestegg/nestegg.h"
17 static int nestegg_read_cb(void *buffer
, size_t length
, void *userdata
) {
20 if (fread(buffer
, 1, length
, f
) < length
) {
29 static int nestegg_seek_cb(int64_t offset
, int whence
, void *userdata
) {
31 case NESTEGG_SEEK_SET
:
34 case NESTEGG_SEEK_CUR
:
37 case NESTEGG_SEEK_END
:
41 return fseek(userdata
, (int32_t)offset
, whence
) ? -1 : 0;
44 static int64_t nestegg_tell_cb(void *userdata
) {
45 return ftell(userdata
);
48 static void nestegg_log_cb(nestegg
*context
,
49 unsigned int severity
,
50 char const *format
, ...) {
53 vfprintf(stderr
, format
, ap
);
54 fprintf(stderr
, "\n");
58 int file_is_webm(struct WebmInputContext
*webm_ctx
,
59 struct VpxInputContext
*vpx_ctx
) {
64 nestegg_io io
= {nestegg_read_cb
, nestegg_seek_cb
, nestegg_tell_cb
, 0};
65 nestegg_video_params params
;
67 io
.userdata
= vpx_ctx
->file
;
68 if (nestegg_init(&webm_ctx
->nestegg_ctx
, io
, NULL
, -1))
71 if (nestegg_track_count(webm_ctx
->nestegg_ctx
, &n
))
74 for (i
= 0; i
< n
; i
++) {
75 track_type
= nestegg_track_type(webm_ctx
->nestegg_ctx
, i
);
77 if (track_type
== NESTEGG_TRACK_VIDEO
)
79 else if (track_type
< 0)
83 codec_id
= nestegg_track_codec_id(webm_ctx
->nestegg_ctx
, i
);
84 if (codec_id
== NESTEGG_CODEC_VP8
) {
85 vpx_ctx
->fourcc
= VP8_FOURCC
;
86 } else if (codec_id
== NESTEGG_CODEC_VP9
) {
87 vpx_ctx
->fourcc
= VP9_FOURCC
;
89 fatal("Not VPx video, quitting.\n");
92 webm_ctx
->video_track
= i
;
94 if (nestegg_track_video_params(webm_ctx
->nestegg_ctx
, i
, ¶ms
))
97 vpx_ctx
->framerate
.denominator
= 0;
98 vpx_ctx
->framerate
.numerator
= 0;
99 vpx_ctx
->width
= params
.width
;
100 vpx_ctx
->height
= params
.height
;
105 webm_ctx
->nestegg_ctx
= NULL
;
106 rewind(vpx_ctx
->file
);
111 int webm_read_frame(struct WebmInputContext
*webm_ctx
,
113 size_t *bytes_in_buffer
,
114 size_t *buffer_size
) {
115 if (webm_ctx
->chunk
>= webm_ctx
->chunks
) {
119 /* End of this packet, get another. */
121 nestegg_free_packet(webm_ctx
->pkt
);
122 webm_ctx
->pkt
= NULL
;
125 if (nestegg_read_packet(webm_ctx
->nestegg_ctx
, &webm_ctx
->pkt
) <= 0 ||
126 nestegg_packet_track(webm_ctx
->pkt
, &track
)) {
129 } while (track
!= webm_ctx
->video_track
);
131 if (nestegg_packet_count(webm_ctx
->pkt
, &webm_ctx
->chunks
))
137 if (nestegg_packet_data(webm_ctx
->pkt
, webm_ctx
->chunk
,
138 buffer
, bytes_in_buffer
)) {
146 int webm_guess_framerate(struct WebmInputContext
*webm_ctx
,
147 struct VpxInputContext
*vpx_ctx
) {
151 /* Check to see if we can seek before we parse any data. */
152 if (nestegg_track_seek(webm_ctx
->nestegg_ctx
, webm_ctx
->video_track
, 0)) {
153 warn("Failed to guess framerate (no Cues), set to 30fps.\n");
154 vpx_ctx
->framerate
.numerator
= 30;
155 vpx_ctx
->framerate
.denominator
= 1;
159 /* Guess the framerate. Read up to 1 second, or 50 video packets,
160 * whichever comes first.
162 for (i
= 0; tstamp
< 1000000000 && i
< 50;) {
166 if (nestegg_read_packet(webm_ctx
->nestegg_ctx
, &pkt
) <= 0)
169 nestegg_packet_track(pkt
, &track
);
170 if (track
== webm_ctx
->video_track
) {
171 nestegg_packet_tstamp(pkt
, &tstamp
);
175 nestegg_free_packet(pkt
);
178 if (nestegg_track_seek(webm_ctx
->nestegg_ctx
, webm_ctx
->video_track
, 0))
181 vpx_ctx
->framerate
.numerator
= (i
- 1) * 1000000;
182 vpx_ctx
->framerate
.denominator
= (int)(tstamp
/ 1000);
186 nestegg_destroy(webm_ctx
->nestegg_ctx
);
187 webm_ctx
->nestegg_ctx
= NULL
;
188 rewind(vpx_ctx
->file
);
192 void webm_free(struct WebmInputContext
*webm_ctx
) {
193 if (webm_ctx
&& webm_ctx
->nestegg_ctx
) {
195 nestegg_free_packet(webm_ctx
->pkt
);
196 nestegg_destroy(webm_ctx
->nestegg_ctx
);