vpxdec: Relocate WebM input support.
- Move it to webmdec.c and webmdec.h. - Also, tidy up obvious style nits in the vicinity of code I was already touching. Change-Id: Ie2898d06e73c1e9030d9c8d465b73ee7edc3c02a
This commit is contained in:
parent
a7c4209724
commit
2abe2d4664
@ -25,6 +25,7 @@ vpxdec.SRCS += vpx/vpx_integer.h
|
|||||||
vpxdec.SRCS += args.c args.h
|
vpxdec.SRCS += args.c args.h
|
||||||
vpxdec.SRCS += ivfdec.c ivfdec.h
|
vpxdec.SRCS += ivfdec.c ivfdec.h
|
||||||
vpxdec.SRCS += tools_common.c tools_common.h
|
vpxdec.SRCS += tools_common.c tools_common.h
|
||||||
|
vpxdec.SRCS += webmdec.c webmdec.h
|
||||||
vpxdec.SRCS += nestegg/halloc/halloc.h
|
vpxdec.SRCS += nestegg/halloc/halloc.h
|
||||||
vpxdec.SRCS += nestegg/halloc/src/align.h
|
vpxdec.SRCS += nestegg/halloc/src/align.h
|
||||||
vpxdec.SRCS += nestegg/halloc/src/halloc.c
|
vpxdec.SRCS += nestegg/halloc/src/halloc.c
|
||||||
|
@ -92,11 +92,11 @@ struct VpxInputContext {
|
|||||||
off_t length;
|
off_t length;
|
||||||
struct FileTypeDetectionBuffer detect;
|
struct FileTypeDetectionBuffer detect;
|
||||||
enum VideoFileType file_type;
|
enum VideoFileType file_type;
|
||||||
unsigned int width;
|
uint32_t width;
|
||||||
unsigned int height;
|
uint32_t height;
|
||||||
int use_i420;
|
int use_i420;
|
||||||
int only_i420;
|
int only_i420;
|
||||||
unsigned int fourcc;
|
uint32_t fourcc;
|
||||||
struct VpxRational framerate;
|
struct VpxRational framerate;
|
||||||
#if CONFIG_ENCODERS
|
#if CONFIG_ENCODERS
|
||||||
y4m_input y4m;
|
y4m_input y4m;
|
||||||
|
215
vpxdec.c
215
vpxdec.c
@ -15,6 +15,9 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "third_party/libyuv/include/libyuv/scale.h"
|
||||||
|
|
||||||
|
#include "./args.h"
|
||||||
#include "./ivfdec.h"
|
#include "./ivfdec.h"
|
||||||
|
|
||||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||||
@ -27,20 +30,19 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CONFIG_MD5
|
#if CONFIG_MD5
|
||||||
#include "md5_utils.h"
|
#include "./md5_utils.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "./tools_common.h"
|
#include "./tools_common.h"
|
||||||
#include "nestegg/include/nestegg/nestegg.h"
|
#include "./webmdec.h"
|
||||||
#include "third_party/libyuv/include/libyuv/scale.h"
|
|
||||||
|
|
||||||
static const char *exec_name;
|
static const char *exec_name;
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
char const *name;
|
char const *name;
|
||||||
const vpx_codec_iface_t *(*iface)(void);
|
const vpx_codec_iface_t *(*iface)(void);
|
||||||
unsigned int fourcc;
|
uint32_t fourcc;
|
||||||
unsigned int fourcc_mask;
|
uint32_t fourcc_mask;
|
||||||
} ifaces[] = {
|
} ifaces[] = {
|
||||||
#if CONFIG_VP8_DECODER
|
#if CONFIG_VP8_DECODER
|
||||||
{"vp8", vpx_codec_vp8_dx, VP8_FOURCC_MASK, 0x00FFFFFF},
|
{"vp8", vpx_codec_vp8_dx, VP8_FOURCC_MASK, 0x00FFFFFF},
|
||||||
@ -50,7 +52,11 @@ static const struct {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "args.h"
|
struct VpxDecInputContext {
|
||||||
|
struct VpxInputContext *vpx_input_ctx;
|
||||||
|
struct WebmInputContext *webm_ctx;
|
||||||
|
};
|
||||||
|
|
||||||
static const arg_def_t looparg = ARG_DEF(NULL, "loops", 1,
|
static const arg_def_t looparg = ARG_DEF(NULL, "loops", 1,
|
||||||
"Number of times to decode the file");
|
"Number of times to decode the file");
|
||||||
static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
|
static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
|
||||||
@ -162,15 +168,6 @@ void usage_exit() {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VpxDecInputContext {
|
|
||||||
nestegg *nestegg_ctx;
|
|
||||||
nestegg_packet *pkt;
|
|
||||||
unsigned int chunk;
|
|
||||||
unsigned int chunks;
|
|
||||||
unsigned int video_track;
|
|
||||||
struct VpxInputContext *vpx_input_ctx;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int read_frame(struct VpxDecInputContext *input,
|
static int read_frame(struct VpxDecInputContext *input,
|
||||||
uint8_t **buf,
|
uint8_t **buf,
|
||||||
size_t *bytes_in_buffer,
|
size_t *bytes_in_buffer,
|
||||||
@ -180,30 +177,8 @@ static int read_frame(struct VpxDecInputContext *input,
|
|||||||
FILE *infile = input->vpx_input_ctx->file;
|
FILE *infile = input->vpx_input_ctx->file;
|
||||||
enum VideoFileType kind = input->vpx_input_ctx->file_type;
|
enum VideoFileType kind = input->vpx_input_ctx->file_type;
|
||||||
if (kind == FILE_TYPE_WEBM) {
|
if (kind == FILE_TYPE_WEBM) {
|
||||||
if (input->chunk >= input->chunks) {
|
return webm_read_frame(input->webm_ctx,
|
||||||
unsigned int track;
|
buf, bytes_in_buffer, buffer_size);
|
||||||
|
|
||||||
do {
|
|
||||||
/* End of this packet, get another. */
|
|
||||||
if (input->pkt)
|
|
||||||
nestegg_free_packet(input->pkt);
|
|
||||||
|
|
||||||
if (nestegg_read_packet(input->nestegg_ctx, &input->pkt) <= 0
|
|
||||||
|| nestegg_packet_track(input->pkt, &track))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
} while (track != input->video_track);
|
|
||||||
|
|
||||||
if (nestegg_packet_count(input->pkt, &input->chunks))
|
|
||||||
return 1;
|
|
||||||
input->chunk = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nestegg_packet_data(input->pkt, input->chunk, buf, bytes_in_buffer))
|
|
||||||
return 1;
|
|
||||||
input->chunk++;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} else if (kind == FILE_TYPE_RAW) {
|
} else if (kind == FILE_TYPE_RAW) {
|
||||||
if (fread(raw_hdr, RAW_FRAME_HDR_SZ, 1, infile) != 1) {
|
if (fread(raw_hdr, RAW_FRAME_HDR_SZ, 1, infile) != 1) {
|
||||||
if (!feof(infile))
|
if (!feof(infile))
|
||||||
@ -333,161 +308,12 @@ int file_is_raw(struct VpxInputContext *input) {
|
|||||||
return is_raw;
|
return is_raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
nestegg_read_cb(void *buffer, size_t length, void *userdata) {
|
|
||||||
FILE *f = 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) {
|
|
||||||
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(userdata, (long)offset, whence) ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int64_t
|
|
||||||
nestegg_tell_cb(void *userdata) {
|
|
||||||
return ftell(userdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
webm_guess_framerate(struct VpxDecInputContext *input) {
|
|
||||||
unsigned int i;
|
|
||||||
uint64_t tstamp = 0;
|
|
||||||
|
|
||||||
/* Check to see if we can seek before we parse any data. */
|
|
||||||
if (nestegg_track_seek(input->nestegg_ctx, input->video_track, 0)) {
|
|
||||||
warn("WARNING: Failed to guess framerate (no Cues), set to 30fps.\n");
|
|
||||||
input->vpx_input_ctx->framerate.numerator = 30;
|
|
||||||
input->vpx_input_ctx->framerate.denominator = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Guess the framerate. Read up to 1 second, or 50 video packets,
|
|
||||||
* whichever comes first.
|
|
||||||
*/
|
|
||||||
for (i = 0; tstamp < 1000000000 && i < 50;) {
|
|
||||||
nestegg_packet *pkt;
|
|
||||||
unsigned int track;
|
|
||||||
|
|
||||||
if (nestegg_read_packet(input->nestegg_ctx, &pkt) <= 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
nestegg_packet_track(pkt, &track);
|
|
||||||
if (track == input->video_track) {
|
|
||||||
nestegg_packet_tstamp(pkt, &tstamp);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
nestegg_free_packet(pkt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nestegg_track_seek(input->nestegg_ctx, input->video_track, 0))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
input->vpx_input_ctx->framerate.numerator = (i - 1) * 1000000;
|
|
||||||
input->vpx_input_ctx->framerate.denominator = (int)(tstamp / 1000);
|
|
||||||
return 0;
|
|
||||||
fail:
|
|
||||||
nestegg_destroy(input->nestegg_ctx);
|
|
||||||
input->nestegg_ctx = NULL;
|
|
||||||
rewind(input->vpx_input_ctx->file);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
file_is_webm(struct VpxDecInputContext *input) {
|
|
||||||
unsigned int i, n;
|
|
||||||
int track_type = -1;
|
|
||||||
int codec_id;
|
|
||||||
|
|
||||||
nestegg_io io = {nestegg_read_cb, nestegg_seek_cb, nestegg_tell_cb, 0};
|
|
||||||
nestegg_video_params params;
|
|
||||||
|
|
||||||
io.userdata = input->vpx_input_ctx->file;
|
|
||||||
if (nestegg_init(&input->nestegg_ctx, io, NULL))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (nestegg_track_count(input->nestegg_ctx, &n))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
track_type = nestegg_track_type(input->nestegg_ctx, i);
|
|
||||||
|
|
||||||
if (track_type == NESTEGG_TRACK_VIDEO)
|
|
||||||
break;
|
|
||||||
else if (track_type < 0)
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
codec_id = nestegg_track_codec_id(input->nestegg_ctx, i);
|
|
||||||
if (codec_id == NESTEGG_CODEC_VP8) {
|
|
||||||
input->vpx_input_ctx->fourcc = VP8_FOURCC_MASK;
|
|
||||||
} else if (codec_id == NESTEGG_CODEC_VP9) {
|
|
||||||
input->vpx_input_ctx->fourcc = VP9_FOURCC_MASK;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Not VPx video, quitting.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
input->video_track = i;
|
|
||||||
|
|
||||||
if (nestegg_track_video_params(input->nestegg_ctx, i, ¶ms))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
input->vpx_input_ctx->framerate.denominator = 0;
|
|
||||||
input->vpx_input_ctx->framerate.numerator = 0;
|
|
||||||
input->vpx_input_ctx->width = params.width;
|
|
||||||
input->vpx_input_ctx->height = params.height;
|
|
||||||
return 1;
|
|
||||||
fail:
|
|
||||||
input->nestegg_ctx = NULL;
|
|
||||||
rewind(input->vpx_input_ctx->file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void show_progress(int frame_in, int frame_out, unsigned long dx_time) {
|
void show_progress(int frame_in, int frame_out, unsigned long dx_time) {
|
||||||
fprintf(stderr, "%d decoded frames/%d showed frames in %lu us (%.2f fps)\r",
|
fprintf(stderr, "%d decoded frames/%d showed frames in %lu us (%.2f fps)\r",
|
||||||
frame_in, frame_out, dx_time,
|
frame_in, frame_out, dx_time,
|
||||||
(float)frame_out * 1000000.0 / (float)dx_time);
|
(float)frame_out * 1000000.0 / (float)dx_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void generate_filename(const char *pattern, char *out, size_t q_len,
|
void generate_filename(const char *pattern, char *out, size_t q_len,
|
||||||
unsigned int d_w, unsigned int d_h,
|
unsigned int d_w, unsigned int d_h,
|
||||||
unsigned int frame_in) {
|
unsigned int frame_in) {
|
||||||
@ -606,7 +432,9 @@ int main_loop(int argc, const char **argv_) {
|
|||||||
|
|
||||||
struct VpxDecInputContext input = {0};
|
struct VpxDecInputContext input = {0};
|
||||||
struct VpxInputContext vpx_input_ctx = {0};
|
struct VpxInputContext vpx_input_ctx = {0};
|
||||||
|
struct WebmInputContext webm_ctx = {0};
|
||||||
input.vpx_input_ctx = &vpx_input_ctx;
|
input.vpx_input_ctx = &vpx_input_ctx;
|
||||||
|
input.webm_ctx = &webm_ctx;
|
||||||
|
|
||||||
/* Parse command line */
|
/* Parse command line */
|
||||||
exec_name = argv_[0];
|
exec_name = argv_[0];
|
||||||
@ -748,7 +576,7 @@ int main_loop(int argc, const char **argv_) {
|
|||||||
input.vpx_input_ctx->file = infile;
|
input.vpx_input_ctx->file = infile;
|
||||||
if (file_is_ivf(input.vpx_input_ctx))
|
if (file_is_ivf(input.vpx_input_ctx))
|
||||||
input.vpx_input_ctx->file_type = FILE_TYPE_IVF;
|
input.vpx_input_ctx->file_type = FILE_TYPE_IVF;
|
||||||
else if (file_is_webm(&input))
|
else if (file_is_webm(input.webm_ctx, input.vpx_input_ctx))
|
||||||
input.vpx_input_ctx->file_type = FILE_TYPE_WEBM;
|
input.vpx_input_ctx->file_type = FILE_TYPE_WEBM;
|
||||||
else if (file_is_raw(input.vpx_input_ctx))
|
else if (file_is_raw(input.vpx_input_ctx))
|
||||||
input.vpx_input_ctx->file_type = FILE_TYPE_RAW;
|
input.vpx_input_ctx->file_type = FILE_TYPE_RAW;
|
||||||
@ -792,7 +620,7 @@ int main_loop(int argc, const char **argv_) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (vpx_input_ctx.file_type == FILE_TYPE_WEBM)
|
if (vpx_input_ctx.file_type == FILE_TYPE_WEBM)
|
||||||
if (webm_guess_framerate(&input)) {
|
if (webm_guess_framerate(input.webm_ctx, input.vpx_input_ctx)) {
|
||||||
fprintf(stderr, "Failed to guess framerate -- error parsing "
|
fprintf(stderr, "Failed to guess framerate -- error parsing "
|
||||||
"webm file?\n");
|
"webm file?\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@ -1036,10 +864,11 @@ fail:
|
|||||||
if (single_file && !noblit)
|
if (single_file && !noblit)
|
||||||
out_close(out, outfile, do_md5);
|
out_close(out, outfile, do_md5);
|
||||||
|
|
||||||
if (input.nestegg_ctx)
|
if (input.vpx_input_ctx->file_type == FILE_TYPE_WEBM)
|
||||||
nestegg_destroy(input.nestegg_ctx);
|
webm_free(input.webm_ctx);
|
||||||
if (input.vpx_input_ctx->file_type != FILE_TYPE_WEBM)
|
else
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
fclose(infile);
|
fclose(infile);
|
||||||
free(argv);
|
free(argv);
|
||||||
|
|
||||||
|
193
webmdec.c
Normal file
193
webmdec.c
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "./webmdec.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "nestegg/include/nestegg/nestegg.h"
|
||||||
|
|
||||||
|
static int nestegg_read_cb(void *buffer, size_t length, void *userdata) {
|
||||||
|
FILE *f = 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) {
|
||||||
|
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(userdata, (int32_t)offset, whence) ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t nestegg_tell_cb(void *userdata) {
|
||||||
|
return ftell(userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int file_is_webm(struct WebmInputContext *webm_ctx,
|
||||||
|
struct VpxInputContext *vpx_ctx) {
|
||||||
|
uint32_t i, n;
|
||||||
|
int track_type = -1;
|
||||||
|
int codec_id;
|
||||||
|
|
||||||
|
nestegg_io io = {nestegg_read_cb, nestegg_seek_cb, nestegg_tell_cb, 0};
|
||||||
|
nestegg_video_params params;
|
||||||
|
|
||||||
|
io.userdata = vpx_ctx->file;
|
||||||
|
if (nestegg_init(&webm_ctx->nestegg_ctx, io, NULL))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (nestegg_track_count(webm_ctx->nestegg_ctx, &n))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
track_type = nestegg_track_type(webm_ctx->nestegg_ctx, i);
|
||||||
|
|
||||||
|
if (track_type == NESTEGG_TRACK_VIDEO)
|
||||||
|
break;
|
||||||
|
else if (track_type < 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
codec_id = nestegg_track_codec_id(webm_ctx->nestegg_ctx, i);
|
||||||
|
if (codec_id == NESTEGG_CODEC_VP8) {
|
||||||
|
vpx_ctx->fourcc = VP8_FOURCC_MASK;
|
||||||
|
} else if (codec_id == NESTEGG_CODEC_VP9) {
|
||||||
|
vpx_ctx->fourcc = VP9_FOURCC_MASK;
|
||||||
|
} else {
|
||||||
|
fatal("Not VPx video, quitting.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
webm_ctx->video_track = i;
|
||||||
|
|
||||||
|
if (nestegg_track_video_params(webm_ctx->nestegg_ctx, i, ¶ms))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
vpx_ctx->framerate.denominator = 0;
|
||||||
|
vpx_ctx->framerate.numerator = 0;
|
||||||
|
vpx_ctx->width = params.width;
|
||||||
|
vpx_ctx->height = params.height;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
webm_ctx->nestegg_ctx = NULL;
|
||||||
|
rewind(vpx_ctx->file);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int webm_read_frame(struct WebmInputContext *webm_ctx,
|
||||||
|
uint8_t **buffer,
|
||||||
|
size_t *bytes_in_buffer,
|
||||||
|
size_t *buffer_size) {
|
||||||
|
if (webm_ctx->chunk >= webm_ctx->chunks) {
|
||||||
|
uint32_t track;
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* End of this packet, get another. */
|
||||||
|
if (webm_ctx->pkt)
|
||||||
|
nestegg_free_packet(webm_ctx->pkt);
|
||||||
|
|
||||||
|
if (nestegg_read_packet(webm_ctx->nestegg_ctx, &webm_ctx->pkt) <= 0 ||
|
||||||
|
nestegg_packet_track(webm_ctx->pkt, &track)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} while (track != webm_ctx->video_track);
|
||||||
|
|
||||||
|
if (nestegg_packet_count(webm_ctx->pkt, &webm_ctx->chunks))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
webm_ctx->chunk = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nestegg_packet_data(webm_ctx->pkt, webm_ctx->chunk,
|
||||||
|
buffer, bytes_in_buffer)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
webm_ctx->chunk++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int webm_guess_framerate(struct WebmInputContext *webm_ctx,
|
||||||
|
struct VpxInputContext *vpx_ctx) {
|
||||||
|
uint32_t i;
|
||||||
|
uint64_t tstamp = 0;
|
||||||
|
|
||||||
|
/* Check to see if we can seek before we parse any data. */
|
||||||
|
if (nestegg_track_seek(webm_ctx->nestegg_ctx, webm_ctx->video_track, 0)) {
|
||||||
|
warn("Failed to guess framerate (no Cues), set to 30fps.\n");
|
||||||
|
vpx_ctx->framerate.numerator = 30;
|
||||||
|
vpx_ctx->framerate.denominator = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Guess the framerate. Read up to 1 second, or 50 video packets,
|
||||||
|
* whichever comes first.
|
||||||
|
*/
|
||||||
|
for (i = 0; tstamp < 1000000000 && i < 50;) {
|
||||||
|
nestegg_packet *pkt;
|
||||||
|
uint32_t track;
|
||||||
|
|
||||||
|
if (nestegg_read_packet(webm_ctx->nestegg_ctx, &pkt) <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
nestegg_packet_track(pkt, &track);
|
||||||
|
if (track == webm_ctx->video_track) {
|
||||||
|
nestegg_packet_tstamp(pkt, &tstamp);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
nestegg_free_packet(pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nestegg_track_seek(webm_ctx->nestegg_ctx, webm_ctx->video_track, 0))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
vpx_ctx->framerate.numerator = (i - 1) * 1000000;
|
||||||
|
vpx_ctx->framerate.denominator = (int)(tstamp / 1000);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
nestegg_destroy(webm_ctx->nestegg_ctx);
|
||||||
|
webm_ctx->nestegg_ctx = NULL;
|
||||||
|
rewind(vpx_ctx->file);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void webm_free(struct WebmInputContext *webm_ctx) {
|
||||||
|
if (webm_ctx && webm_ctx->nestegg_ctx)
|
||||||
|
nestegg_destroy(webm_ctx->nestegg_ctx);
|
||||||
|
}
|
40
webmdec.h
Normal file
40
webmdec.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 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 WEBMDEC_H_
|
||||||
|
#define WEBMDEC_H_
|
||||||
|
|
||||||
|
#include "./tools_common.h"
|
||||||
|
|
||||||
|
struct nestegg;
|
||||||
|
struct nestegg_packet;
|
||||||
|
struct VpxInputContext;
|
||||||
|
|
||||||
|
struct WebmInputContext {
|
||||||
|
uint32_t chunk;
|
||||||
|
uint32_t chunks;
|
||||||
|
uint32_t video_track;
|
||||||
|
struct nestegg *nestegg_ctx;
|
||||||
|
struct nestegg_packet *pkt;
|
||||||
|
};
|
||||||
|
|
||||||
|
int file_is_webm(struct WebmInputContext *webm_ctx,
|
||||||
|
struct VpxInputContext *vpx_ctx);
|
||||||
|
|
||||||
|
int webm_read_frame(struct WebmInputContext *webm_ctx,
|
||||||
|
uint8_t **buffer,
|
||||||
|
size_t *bytes_in_buffer,
|
||||||
|
size_t *buffer_size);
|
||||||
|
|
||||||
|
int webm_guess_framerate(struct WebmInputContext *webm_ctx,
|
||||||
|
struct VpxInputContext *vpx_ctx);
|
||||||
|
|
||||||
|
void webm_free(struct WebmInputContext *webm_ctx);
|
||||||
|
|
||||||
|
#endif // WEBMDEC_H_
|
Loading…
x
Reference in New Issue
Block a user