Merge WebM input/output branch
Change-Id: I83a6f18d2314e5d97759b4ae49afaa52fd8b3c44
This commit is contained in:
commit
bdc9262a6d
8
args.c
8
args.c
@ -120,9 +120,13 @@ void arg_show_usage(FILE *fp, const struct arg_def *const *defs)
|
||||
char *long_val = def->has_val ? "=<arg>" : "";
|
||||
|
||||
if (def->short_name && def->long_name)
|
||||
snprintf(option_text, 37, "-%s%s, --%s%s",
|
||||
def->short_name, short_val,
|
||||
{
|
||||
char *comma = def->has_val ? "," : ", ";
|
||||
|
||||
snprintf(option_text, 37, "-%s%s%s --%s%6s",
|
||||
def->short_name, short_val, comma,
|
||||
def->long_name, long_val);
|
||||
}
|
||||
else if (def->short_name)
|
||||
snprintf(option_text, 37, "-%s%s",
|
||||
def->short_name, short_val);
|
||||
|
45
examples.mk
45
examples.mk
@ -12,19 +12,38 @@
|
||||
# List of examples to build. UTILS are files that are taken from the source
|
||||
# tree directly, and GEN_EXAMPLES are files that are created from the
|
||||
# examples folder.
|
||||
UTILS-$(CONFIG_DECODERS) += ivfdec.c
|
||||
ivfdec.SRCS += md5_utils.c md5_utils.h
|
||||
ivfdec.SRCS += vpx_ports/vpx_timer.h
|
||||
ivfdec.SRCS += vpx/vpx_integer.h
|
||||
ivfdec.SRCS += args.c args.h vpx_ports/config.h
|
||||
ivfdec.GUID = BA5FE66F-38DD-E034-F542-B1578C5FB950
|
||||
ivfdec.DESCRIPTION = Full featured decoder
|
||||
UTILS-$(CONFIG_ENCODERS) += ivfenc.c
|
||||
ivfenc.SRCS += args.c args.h y4minput.c y4minput.h
|
||||
ivfenc.SRCS += vpx_ports/config.h vpx_ports/mem_ops.h
|
||||
ivfenc.SRCS += vpx_ports/mem_ops_aligned.h
|
||||
ivfenc.GUID = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
|
||||
ivfenc.DESCRIPTION = Full featured encoder
|
||||
UTILS-$(CONFIG_DECODERS) += vpxdec.c
|
||||
vpxdec.SRCS += md5_utils.c md5_utils.h
|
||||
vpxdec.SRCS += vpx_ports/vpx_timer.h
|
||||
vpxdec.SRCS += vpx/vpx_integer.h
|
||||
vpxdec.SRCS += args.c args.h vpx_ports/config.h
|
||||
vpxdec.SRCS += nestegg/halloc/halloc.h
|
||||
vpxdec.SRCS += nestegg/halloc/src/align.h
|
||||
vpxdec.SRCS += nestegg/halloc/src/halloc.c
|
||||
vpxdec.SRCS += nestegg/halloc/src/hlist.h
|
||||
vpxdec.SRCS += nestegg/halloc/src/macros.h
|
||||
vpxdec.SRCS += nestegg/include/nestegg/nestegg.h
|
||||
vpxdec.SRCS += nestegg/src/nestegg.c
|
||||
vpxdec.GUID = BA5FE66F-38DD-E034-F542-B1578C5FB950
|
||||
vpxdec.DESCRIPTION = Full featured decoder
|
||||
UTILS-$(CONFIG_ENCODERS) += vpxenc.c
|
||||
vpxenc.SRCS += args.c args.h y4minput.c y4minput.h
|
||||
vpxenc.SRCS += vpx_ports/config.h vpx_ports/mem_ops.h
|
||||
vpxenc.SRCS += vpx_ports/mem_ops_aligned.h
|
||||
vpxenc.SRCS += libmkv/EbmlIDs.h
|
||||
vpxenc.SRCS += libmkv/EbmlWriter.c
|
||||
vpxenc.SRCS += libmkv/EbmlWriter.h
|
||||
vpxenc.GUID = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
|
||||
vpxenc.DESCRIPTION = Full featured encoder
|
||||
|
||||
# Clean up old ivfenc, ivfdec binaries.
|
||||
ifeq ($(CONFIG_MSVS),yes)
|
||||
CLEAN-OBJS += $(foreach p,$(VS_PLATFORMS),$(p)/Release/ivfenc.exe)
|
||||
CLEAN-OBJS += $(foreach p,$(VS_PLATFORMS),$(p)/Release/ivfdec.exe)
|
||||
else
|
||||
CLEAN-OBJS += ivfenc{.c.o,.c.d,.dox,.exe}
|
||||
CLEAN-OBJS += ivfdec{.c.o,.c.d,.dox,.exe}
|
||||
endif
|
||||
|
||||
# XMA example disabled for now, not used in VP8
|
||||
#UTILS-$(CONFIG_DECODERS) += example_xma.c
|
||||
|
640
ivfdec.c
640
ivfdec.c
@ -1,640 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2010 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.
|
||||
*/
|
||||
|
||||
|
||||
/* This is a simple program that reads ivf files and decodes them
|
||||
* using the new interface. Decoded frames are output as YV12 raw.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||
#include "vpx_config.h"
|
||||
#include "vpx/vpx_decoder.h"
|
||||
#include "vpx_ports/vpx_timer.h"
|
||||
#if CONFIG_VP8_DECODER
|
||||
#include "vpx/vp8dx.h"
|
||||
#endif
|
||||
#if CONFIG_MD5
|
||||
#include "md5_utils.h"
|
||||
#endif
|
||||
|
||||
static const char *exec_name;
|
||||
|
||||
static const struct
|
||||
{
|
||||
char const *name;
|
||||
const vpx_codec_iface_t *iface;
|
||||
unsigned int fourcc;
|
||||
unsigned int fourcc_mask;
|
||||
} ifaces[] =
|
||||
{
|
||||
#if CONFIG_VP8_DECODER
|
||||
{"vp8", &vpx_codec_vp8_dx_algo, 0x00385056, 0x00FFFFFF},
|
||||
#endif
|
||||
};
|
||||
|
||||
#include "args.h"
|
||||
static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
|
||||
"Codec to use");
|
||||
static const arg_def_t prefixarg = ARG_DEF("p", "prefix", 1,
|
||||
"Prefix to use when saving frames");
|
||||
static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
|
||||
"Output file is YV12 ");
|
||||
static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
|
||||
"Output file is I420 (default)");
|
||||
static const arg_def_t flipuvarg = ARG_DEF(NULL, "flipuv", 0,
|
||||
"Synonym for --yv12");
|
||||
static const arg_def_t noblitarg = ARG_DEF(NULL, "noblit", 0,
|
||||
"Don't process the decoded frames");
|
||||
static const arg_def_t progressarg = ARG_DEF(NULL, "progress", 0,
|
||||
"Show progress after each frame decodes");
|
||||
static const arg_def_t limitarg = ARG_DEF(NULL, "limit", 1,
|
||||
"Stop decoding after n frames");
|
||||
static const arg_def_t postprocarg = ARG_DEF(NULL, "postproc", 0,
|
||||
"Postprocess decoded frames");
|
||||
static const arg_def_t summaryarg = ARG_DEF(NULL, "summary", 0,
|
||||
"Show timing summary");
|
||||
static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
|
||||
"Output raw yv12 file instead of images");
|
||||
static const arg_def_t usey4marg = ARG_DEF("y", "y4m", 0,
|
||||
"Output file is YUV4MPEG2");
|
||||
static const arg_def_t threadsarg = ARG_DEF("t", "threads", 1,
|
||||
"Max threads to use");
|
||||
static const arg_def_t quietarg = ARG_DEF("q", "quiet", 0,
|
||||
"Suppress version string");
|
||||
|
||||
#if CONFIG_MD5
|
||||
static const arg_def_t md5arg = ARG_DEF(NULL, "md5", 0,
|
||||
"Compute the MD5 sum of the decoded frame");
|
||||
#endif
|
||||
static const arg_def_t *all_args[] =
|
||||
{
|
||||
&codecarg, &prefixarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg,
|
||||
&progressarg, &limitarg, &postprocarg, &summaryarg, &outputfile,
|
||||
&usey4marg, &threadsarg, &quietarg,
|
||||
#if CONFIG_MD5
|
||||
&md5arg,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
#if CONFIG_VP8_DECODER
|
||||
static const arg_def_t addnoise_level = ARG_DEF(NULL, "noise-level", 1,
|
||||
"Enable VP8 postproc add noise");
|
||||
static const arg_def_t deblock = ARG_DEF(NULL, "deblock", 0,
|
||||
"Enable VP8 deblocking");
|
||||
static const arg_def_t demacroblock_level = ARG_DEF(NULL, "demacroblock-level", 1,
|
||||
"Enable VP8 demacroblocking, w/ level");
|
||||
static const arg_def_t pp_debug_info = ARG_DEF(NULL, "pp-debug-info", 1,
|
||||
"Enable VP8 visible debug info");
|
||||
|
||||
|
||||
static const arg_def_t *vp8_pp_args[] =
|
||||
{
|
||||
&addnoise_level, &deblock, &demacroblock_level, &pp_debug_info,
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
static void usage_exit()
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "Usage: %s <options> filename\n\n"
|
||||
"Options:\n", exec_name);
|
||||
arg_show_usage(stderr, all_args);
|
||||
#if CONFIG_VP8_DECODER
|
||||
fprintf(stderr, "\nVP8 Postprocessing Options:\n");
|
||||
arg_show_usage(stderr, vp8_pp_args);
|
||||
#endif
|
||||
fprintf(stderr, "\nIncluded decoders:\n\n");
|
||||
|
||||
for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
|
||||
fprintf(stderr, " %-6s - %s\n",
|
||||
ifaces[i].name,
|
||||
vpx_codec_iface_name(ifaces[i].iface));
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void die(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fprintf(stderr, "\n");
|
||||
usage_exit();
|
||||
}
|
||||
|
||||
static unsigned int mem_get_le16(const void *vmem)
|
||||
{
|
||||
unsigned int val;
|
||||
const unsigned char *mem = (const unsigned char *)vmem;
|
||||
|
||||
val = mem[1] << 8;
|
||||
val |= mem[0];
|
||||
return val;
|
||||
}
|
||||
|
||||
static unsigned int mem_get_le32(const void *vmem)
|
||||
{
|
||||
unsigned int val;
|
||||
const unsigned char *mem = (const unsigned char *)vmem;
|
||||
|
||||
val = mem[3] << 24;
|
||||
val |= mem[2] << 16;
|
||||
val |= mem[1] << 8;
|
||||
val |= mem[0];
|
||||
return val;
|
||||
}
|
||||
|
||||
#define IVF_FRAME_HDR_SZ (sizeof(uint32_t) + sizeof(uint64_t))
|
||||
#define RAW_FRAME_HDR_SZ (sizeof(uint32_t))
|
||||
static int read_frame(FILE *infile,
|
||||
uint8_t **buf,
|
||||
uint32_t *buf_sz,
|
||||
uint32_t *buf_alloc_sz,
|
||||
int is_ivf)
|
||||
{
|
||||
char raw_hdr[IVF_FRAME_HDR_SZ];
|
||||
uint32_t new_buf_sz;
|
||||
|
||||
/* For both the raw and ivf formats, the frame size is the first 4 bytes
|
||||
* of the frame header. We just need to special case on the header
|
||||
* size.
|
||||
*/
|
||||
if (fread(raw_hdr, is_ivf ? IVF_FRAME_HDR_SZ : RAW_FRAME_HDR_SZ, 1,
|
||||
infile) != 1)
|
||||
{
|
||||
if (!feof(infile))
|
||||
fprintf(stderr, "Failed to read frame size\n");
|
||||
|
||||
new_buf_sz = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_buf_sz = mem_get_le32(raw_hdr);
|
||||
|
||||
if (new_buf_sz > 256 * 1024 * 1024)
|
||||
{
|
||||
fprintf(stderr, "Error: Read invalid frame size (%u)\n",
|
||||
new_buf_sz);
|
||||
new_buf_sz = 0;
|
||||
}
|
||||
|
||||
if (!is_ivf && new_buf_sz > 256 * 1024)
|
||||
fprintf(stderr, "Warning: Read invalid frame size (%u)"
|
||||
" - not a raw file?\n", new_buf_sz);
|
||||
|
||||
if (new_buf_sz > *buf_alloc_sz)
|
||||
{
|
||||
uint8_t *new_buf = realloc(*buf, 2 * new_buf_sz);
|
||||
|
||||
if (new_buf)
|
||||
{
|
||||
*buf = new_buf;
|
||||
*buf_alloc_sz = 2 * new_buf_sz;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Failed to allocate compressed data buffer\n");
|
||||
new_buf_sz = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*buf_sz = new_buf_sz;
|
||||
|
||||
if (*buf_sz)
|
||||
{
|
||||
if (fread(*buf, 1, *buf_sz, infile) != *buf_sz)
|
||||
{
|
||||
fprintf(stderr, "Failed to read full frame\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *out_open(const char *out_fn, int do_md5)
|
||||
{
|
||||
void *out = NULL;
|
||||
|
||||
if (do_md5)
|
||||
{
|
||||
#if CONFIG_MD5
|
||||
MD5Context *md5_ctx = out = malloc(sizeof(MD5Context));
|
||||
(void)out_fn;
|
||||
MD5Init(md5_ctx);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
FILE *outfile = out = strcmp("-", out_fn) ? fopen(out_fn, "wb") : stdout;
|
||||
|
||||
if (!outfile)
|
||||
{
|
||||
fprintf(stderr, "Failed to output file");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void out_put(void *out, const uint8_t *buf, unsigned int len, int do_md5)
|
||||
{
|
||||
if (do_md5)
|
||||
{
|
||||
#if CONFIG_MD5
|
||||
MD5Update(out, buf, len);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
fwrite(buf, 1, len, out);
|
||||
}
|
||||
}
|
||||
|
||||
void out_close(void *out, const char *out_fn, int do_md5)
|
||||
{
|
||||
if (do_md5)
|
||||
{
|
||||
#if CONFIG_MD5
|
||||
uint8_t md5[16];
|
||||
int i;
|
||||
|
||||
MD5Final(md5, out);
|
||||
free(out);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
printf("%02x", md5[i]);
|
||||
|
||||
printf(" %s\n", out_fn);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(out);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int file_is_ivf(FILE *infile,
|
||||
unsigned int *fourcc,
|
||||
unsigned int *width,
|
||||
unsigned int *height,
|
||||
unsigned int *timebase_num,
|
||||
unsigned int *timebase_den)
|
||||
{
|
||||
char raw_hdr[32];
|
||||
int is_ivf = 0;
|
||||
|
||||
if (fread(raw_hdr, 1, 32, infile) == 32)
|
||||
{
|
||||
if (raw_hdr[0] == 'D' && raw_hdr[1] == 'K'
|
||||
&& raw_hdr[2] == 'I' && raw_hdr[3] == 'F')
|
||||
{
|
||||
is_ivf = 1;
|
||||
|
||||
if (mem_get_le16(raw_hdr + 4) != 0)
|
||||
fprintf(stderr, "Error: Unrecognized IVF version! This file may not"
|
||||
" decode properly.");
|
||||
|
||||
*fourcc = mem_get_le32(raw_hdr + 8);
|
||||
*width = mem_get_le16(raw_hdr + 12);
|
||||
*height = mem_get_le16(raw_hdr + 14);
|
||||
*timebase_den = mem_get_le32(raw_hdr + 16);
|
||||
*timebase_num = mem_get_le32(raw_hdr + 20);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_ivf)
|
||||
rewind(infile);
|
||||
|
||||
return is_ivf;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv_)
|
||||
{
|
||||
vpx_codec_ctx_t decoder;
|
||||
char *prefix = NULL, *fn = NULL;
|
||||
int i;
|
||||
uint8_t *buf = NULL;
|
||||
uint32_t buf_sz = 0, buf_alloc_sz = 0;
|
||||
FILE *infile;
|
||||
int frame_in = 0, frame_out = 0, flipuv = 0, noblit = 0, do_md5 = 0, progress = 0;
|
||||
int stop_after = 0, postproc = 0, summary = 0, quiet = 0;
|
||||
vpx_codec_iface_t *iface = NULL;
|
||||
unsigned int is_ivf, fourcc;
|
||||
unsigned long dx_time = 0;
|
||||
struct arg arg;
|
||||
char **argv, **argi, **argj;
|
||||
const char *fn2 = 0;
|
||||
int use_y4m = 0;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int timebase_num;
|
||||
unsigned int timebase_den;
|
||||
void *out = NULL;
|
||||
vpx_codec_dec_cfg_t cfg = {0};
|
||||
#if CONFIG_VP8_DECODER
|
||||
vp8_postproc_cfg_t vp8_pp_cfg = {0};
|
||||
#endif
|
||||
|
||||
/* Parse command line */
|
||||
exec_name = argv_[0];
|
||||
argv = argv_dup(argc - 1, argv_ + 1);
|
||||
|
||||
for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step)
|
||||
{
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
arg.argv_step = 1;
|
||||
|
||||
if (arg_match(&arg, &codecarg, argi))
|
||||
{
|
||||
int j, k = -1;
|
||||
|
||||
for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
|
||||
if (!strcmp(ifaces[j].name, arg.val))
|
||||
k = j;
|
||||
|
||||
if (k >= 0)
|
||||
iface = ifaces[k].iface;
|
||||
else
|
||||
die("Error: Unrecognized argument (%s) to --codec\n",
|
||||
arg.val);
|
||||
}
|
||||
else if (arg_match(&arg, &outputfile, argi))
|
||||
fn2 = arg.val;
|
||||
else if (arg_match(&arg, &usey4marg, argi))
|
||||
use_y4m = 1;
|
||||
else if (arg_match(&arg, &prefixarg, argi))
|
||||
prefix = strdup(arg.val);
|
||||
else if (arg_match(&arg, &use_yv12, argi))
|
||||
flipuv = 1;
|
||||
else if (arg_match(&arg, &use_i420, argi))
|
||||
flipuv = 0;
|
||||
else if (arg_match(&arg, &flipuvarg, argi))
|
||||
flipuv = 1;
|
||||
else if (arg_match(&arg, &noblitarg, argi))
|
||||
noblit = 1;
|
||||
else if (arg_match(&arg, &progressarg, argi))
|
||||
progress = 1;
|
||||
else if (arg_match(&arg, &limitarg, argi))
|
||||
stop_after = arg_parse_uint(&arg);
|
||||
else if (arg_match(&arg, &postprocarg, argi))
|
||||
postproc = 1;
|
||||
else if (arg_match(&arg, &md5arg, argi))
|
||||
do_md5 = 1;
|
||||
else if (arg_match(&arg, &summaryarg, argi))
|
||||
summary = 1;
|
||||
else if (arg_match(&arg, &threadsarg, argi))
|
||||
cfg.threads = arg_parse_uint(&arg);
|
||||
else if (arg_match(&arg, &quietarg, argi))
|
||||
quiet = 1;
|
||||
|
||||
#if CONFIG_VP8_DECODER
|
||||
else if (arg_match(&arg, &addnoise_level, argi))
|
||||
{
|
||||
postproc = 1;
|
||||
vp8_pp_cfg.post_proc_flag |= VP8_ADDNOISE;
|
||||
vp8_pp_cfg.noise_level = arg_parse_uint(&arg);
|
||||
}
|
||||
else if (arg_match(&arg, &demacroblock_level, argi))
|
||||
{
|
||||
postproc = 1;
|
||||
vp8_pp_cfg.post_proc_flag |= VP8_DEMACROBLOCK;
|
||||
vp8_pp_cfg.deblocking_level = arg_parse_uint(&arg);
|
||||
}
|
||||
else if (arg_match(&arg, &deblock, argi))
|
||||
{
|
||||
postproc = 1;
|
||||
vp8_pp_cfg.post_proc_flag |= VP8_DEBLOCK;
|
||||
}
|
||||
else if (arg_match(&arg, &pp_debug_info, argi))
|
||||
{
|
||||
unsigned int level = arg_parse_uint(&arg);
|
||||
|
||||
postproc = 1;
|
||||
vp8_pp_cfg.post_proc_flag &= ~0x7;
|
||||
|
||||
if (level)
|
||||
vp8_pp_cfg.post_proc_flag |= 8 << (level - 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
else
|
||||
argj++;
|
||||
}
|
||||
|
||||
/* Check for unrecognized options */
|
||||
for (argi = argv; *argi; argi++)
|
||||
if (argi[0][0] == '-' && strlen(argi[0]) > 1)
|
||||
die("Error: Unrecognized option %s\n", *argi);
|
||||
|
||||
/* Handle non-option arguments */
|
||||
fn = argv[0];
|
||||
|
||||
if (!fn)
|
||||
usage_exit();
|
||||
|
||||
if (!prefix)
|
||||
prefix = strdup("img");
|
||||
|
||||
/* Open file */
|
||||
infile = strcmp(fn, "-") ? fopen(fn, "rb") : stdin;
|
||||
|
||||
if (!infile)
|
||||
{
|
||||
fprintf(stderr, "Failed to open file");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (fn2)
|
||||
out = out_open(fn2, do_md5);
|
||||
|
||||
is_ivf = file_is_ivf(infile, &fourcc, &width, &height,
|
||||
&timebase_num, &timebase_den);
|
||||
|
||||
if (is_ivf)
|
||||
{
|
||||
if (use_y4m)
|
||||
{
|
||||
char buffer[128];
|
||||
if (!fn2)
|
||||
{
|
||||
fprintf(stderr, "YUV4MPEG2 output only supported with -o.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
/*Correct for the factor of 2 applied to the timebase in the
|
||||
encoder.*/
|
||||
if(timebase_den&1)timebase_num<<=1;
|
||||
else timebase_den>>=1;
|
||||
/*Note: We can't output an aspect ratio here because IVF doesn't
|
||||
store one, and neither does VP8.
|
||||
That will have to wait until these tools support WebM natively.*/
|
||||
sprintf(buffer, "YUV4MPEG2 C%s W%u H%u F%u:%u I%c\n",
|
||||
"420jpeg", width, height, timebase_den, timebase_num, 'p');
|
||||
out_put(out, (unsigned char *)buffer, strlen(buffer), do_md5);
|
||||
}
|
||||
|
||||
/* Try to determine the codec from the fourcc. */
|
||||
for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
|
||||
if ((fourcc & ifaces[i].fourcc_mask) == ifaces[i].fourcc)
|
||||
{
|
||||
vpx_codec_iface_t *ivf_iface = ifaces[i].iface;
|
||||
|
||||
if (iface && iface != ivf_iface)
|
||||
fprintf(stderr, "Notice -- IVF header indicates codec: %s\n",
|
||||
ifaces[i].name);
|
||||
else
|
||||
iface = ivf_iface;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(use_y4m)
|
||||
{
|
||||
fprintf(stderr, "YUV4MPEG2 output only supported from IVF input.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (vpx_codec_dec_init(&decoder, iface ? iface : ifaces[0].iface, &cfg,
|
||||
postproc ? VPX_CODEC_USE_POSTPROC : 0))
|
||||
{
|
||||
fprintf(stderr, "Failed to initialize decoder: %s\n", vpx_codec_error(&decoder));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!quiet)
|
||||
fprintf(stderr, "%s\n", decoder.name);
|
||||
|
||||
#if CONFIG_VP8_DECODER
|
||||
|
||||
if (vp8_pp_cfg.post_proc_flag
|
||||
&& vpx_codec_control(&decoder, VP8_SET_POSTPROC, &vp8_pp_cfg))
|
||||
{
|
||||
fprintf(stderr, "Failed to configure postproc: %s\n", vpx_codec_error(&decoder));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Decode file */
|
||||
while (!read_frame(infile, &buf, &buf_sz, &buf_alloc_sz, is_ivf))
|
||||
{
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
vpx_image_t *img;
|
||||
struct vpx_usec_timer timer;
|
||||
|
||||
vpx_usec_timer_start(&timer);
|
||||
|
||||
if (vpx_codec_decode(&decoder, buf, buf_sz, NULL, 0))
|
||||
{
|
||||
const char *detail = vpx_codec_error_detail(&decoder);
|
||||
fprintf(stderr, "Failed to decode frame: %s\n", vpx_codec_error(&decoder));
|
||||
|
||||
if (detail)
|
||||
fprintf(stderr, " Additional information: %s\n", detail);
|
||||
|
||||
goto fail;
|
||||
}
|
||||
|
||||
vpx_usec_timer_mark(&timer);
|
||||
dx_time += vpx_usec_timer_elapsed(&timer);
|
||||
|
||||
++frame_in;
|
||||
|
||||
if (progress)
|
||||
fprintf(stderr, "decoded frame %d.\n", frame_in);
|
||||
|
||||
if ((img = vpx_codec_get_frame(&decoder, &iter)))
|
||||
++frame_out;
|
||||
|
||||
if (!noblit)
|
||||
{
|
||||
if (img)
|
||||
{
|
||||
unsigned int y;
|
||||
char out_fn[128+24];
|
||||
uint8_t *buf;
|
||||
const char *sfx = flipuv ? "yv12" : "i420";
|
||||
|
||||
if (!fn2)
|
||||
{
|
||||
sprintf(out_fn, "%s-%dx%d-%04d.%s",
|
||||
prefix, img->d_w, img->d_h, frame_in, sfx);
|
||||
out = out_open(out_fn, do_md5);
|
||||
}
|
||||
else if(use_y4m)
|
||||
out_put(out, (unsigned char *)"FRAME\n", 6, do_md5);
|
||||
|
||||
buf = img->planes[VPX_PLANE_Y];
|
||||
|
||||
for (y = 0; y < img->d_h; y++)
|
||||
{
|
||||
out_put(out, buf, img->d_w, do_md5);
|
||||
buf += img->stride[VPX_PLANE_Y];
|
||||
}
|
||||
|
||||
buf = img->planes[flipuv?VPX_PLANE_V:VPX_PLANE_U];
|
||||
|
||||
for (y = 0; y < (1 + img->d_h) / 2; y++)
|
||||
{
|
||||
out_put(out, buf, (1 + img->d_w) / 2, do_md5);
|
||||
buf += img->stride[VPX_PLANE_U];
|
||||
}
|
||||
|
||||
buf = img->planes[flipuv?VPX_PLANE_U:VPX_PLANE_V];
|
||||
|
||||
for (y = 0; y < (1 + img->d_h) / 2; y++)
|
||||
{
|
||||
out_put(out, buf, (1 + img->d_w) / 2, do_md5);
|
||||
buf += img->stride[VPX_PLANE_V];
|
||||
}
|
||||
|
||||
if (!fn2)
|
||||
out_close(out, out_fn, do_md5);
|
||||
}
|
||||
}
|
||||
|
||||
if (stop_after && frame_in >= stop_after)
|
||||
break;
|
||||
}
|
||||
|
||||
if (summary)
|
||||
{
|
||||
fprintf(stderr, "%d decoded frames/%d showed frames in %lu us (%.2f fps)\n",
|
||||
frame_in, frame_out, dx_time, (float)frame_out * 1000000.0 / (float)dx_time);
|
||||
}
|
||||
|
||||
fail:
|
||||
|
||||
if (vpx_codec_destroy(&decoder))
|
||||
{
|
||||
fprintf(stderr, "Failed to destroy decoder: %s\n", vpx_codec_error(&decoder));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (fn2)
|
||||
out_close(out, fn2, do_md5);
|
||||
|
||||
free(buf);
|
||||
fclose(infile);
|
||||
free(prefix);
|
||||
free(argv);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
60
libmkv/EbmlBufferWriter.c
Normal file
60
libmkv/EbmlBufferWriter.c
Normal file
@ -0,0 +1,60 @@
|
||||
//#include <strmif.h>
|
||||
#include "EbmlBufferWriter.h"
|
||||
#include "EbmlWriter.h"
|
||||
//#include <cassert>
|
||||
//#include <limits>
|
||||
//#include <malloc.h> //_alloca
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <string.h>
|
||||
|
||||
void Ebml_Write(EbmlGlobal *glob, const void *buffer_in, unsigned long len)
|
||||
{
|
||||
unsigned char *src = glob->buf;
|
||||
src += glob->offset;
|
||||
memcpy(src, buffer_in, len);
|
||||
glob->offset += len;
|
||||
}
|
||||
|
||||
static void _Serialize(EbmlGlobal *glob, const unsigned char *p, const unsigned char *q)
|
||||
{
|
||||
while (q != p)
|
||||
{
|
||||
--q;
|
||||
|
||||
unsigned long cbWritten;
|
||||
memcpy(&(glob->buf[glob->offset]), q, 1);
|
||||
glob->offset ++;
|
||||
}
|
||||
}
|
||||
|
||||
void Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in, unsigned long len)
|
||||
{
|
||||
//assert(buf);
|
||||
|
||||
const unsigned char *const p = (const unsigned char *)(buffer_in);
|
||||
const unsigned char *const q = p + len;
|
||||
|
||||
_Serialize(glob, p, q);
|
||||
}
|
||||
|
||||
|
||||
void Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc, unsigned long class_id)
|
||||
{
|
||||
Ebml_WriteID(glob, class_id);
|
||||
ebmlLoc->offset = glob->offset;
|
||||
//todo this is always taking 8 bytes, this may need later optimization
|
||||
unsigned long long unknownLen = 0x01FFFFFFFFFFFFFFLLU;
|
||||
Ebml_Serialize(glob, (void *)&unknownLen, 8); //this is a key that says lenght unknown
|
||||
}
|
||||
|
||||
void Ebml_EndSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc)
|
||||
{
|
||||
unsigned long long size = glob->offset - ebmlLoc->offset - 8;
|
||||
unsigned long long curOffset = glob->offset;
|
||||
glob->offset = ebmlLoc->offset;
|
||||
size |= 0x0100000000000000LLU;
|
||||
Ebml_Serialize(glob, &size, 8);
|
||||
glob->offset = curOffset;
|
||||
}
|
||||
|
21
libmkv/EbmlBufferWriter.h
Normal file
21
libmkv/EbmlBufferWriter.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef EBMLBUFFERWRITER_HPP
|
||||
#define EBMLBUFFERWRITER_HPP
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long long offset;
|
||||
} EbmlLoc;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char *buf;
|
||||
unsigned int length;
|
||||
unsigned int offset;
|
||||
} EbmlGlobal;
|
||||
|
||||
|
||||
void Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc, unsigned long class_id);
|
||||
void Ebml_EndSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc);
|
||||
|
||||
|
||||
#endif
|
231
libmkv/EbmlIDs.h
Normal file
231
libmkv/EbmlIDs.h
Normal file
@ -0,0 +1,231 @@
|
||||
// Copyright (c) 2010 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 MKV_DEFS_HPP
|
||||
#define MKV_DEFS_HPP 1
|
||||
|
||||
//Commenting out values not available in webm, but available in matroska
|
||||
|
||||
enum mkv
|
||||
{
|
||||
EBML = 0x1A45DFA3,
|
||||
EBMLVersion = 0x4286,
|
||||
EBMLReadVersion = 0x42F7,
|
||||
EBMLMaxIDLength = 0x42F2,
|
||||
EBMLMaxSizeLength = 0x42F3,
|
||||
DocType = 0x4282,
|
||||
DocTypeVersion = 0x4287,
|
||||
DocTypeReadVersion = 0x4285,
|
||||
// CRC_32 = 0xBF,
|
||||
Void = 0xEC,
|
||||
SignatureSlot = 0x1B538667,
|
||||
SignatureAlgo = 0x7E8A,
|
||||
SignatureHash = 0x7E9A,
|
||||
SignaturePublicKey = 0x7EA5,
|
||||
Signature = 0x7EB5,
|
||||
SignatureElements = 0x7E5B,
|
||||
SignatureElementList = 0x7E7B,
|
||||
SignedElement = 0x6532,
|
||||
//segment
|
||||
Segment = 0x18538067,
|
||||
//Meta Seek Information
|
||||
SeekHead = 0x114D9B74,
|
||||
Seek = 0x4DBB,
|
||||
SeekID = 0x53AB,
|
||||
SeekPosition = 0x53AC,
|
||||
//Segment Information
|
||||
Info = 0x1549A966,
|
||||
// SegmentUID = 0x73A4,
|
||||
// SegmentFilename = 0x7384,
|
||||
// PrevUID = 0x3CB923,
|
||||
// PrevFilename = 0x3C83AB,
|
||||
// NextUID = 0x3EB923,
|
||||
// NextFilename = 0x3E83BB,
|
||||
// SegmentFamily = 0x4444,
|
||||
// ChapterTranslate = 0x6924,
|
||||
// ChapterTranslateEditionUID = 0x69FC,
|
||||
// ChapterTranslateCodec = 0x69BF,
|
||||
// ChapterTranslateID = 0x69A5,
|
||||
TimecodeScale = 0x2AD7B1,
|
||||
Segment_Duration = 0x4489,
|
||||
DateUTC = 0x4461,
|
||||
// Title = 0x7BA9,
|
||||
MuxingApp = 0x4D80,
|
||||
WritingApp = 0x5741,
|
||||
//Cluster
|
||||
Cluster = 0x1F43B675,
|
||||
Timecode = 0xE7,
|
||||
// SilentTracks = 0x5854,
|
||||
// SilentTrackNumber = 0x58D7,
|
||||
// Position = 0xA7,
|
||||
PrevSize = 0xAB,
|
||||
BlockGroup = 0xA0,
|
||||
Block = 0xA1,
|
||||
// BlockVirtual = 0xA2,
|
||||
// BlockAdditions = 0x75A1,
|
||||
// BlockMore = 0xA6,
|
||||
// BlockAddID = 0xEE,
|
||||
// BlockAdditional = 0xA5,
|
||||
BlockDuration = 0x9B,
|
||||
// ReferencePriority = 0xFA,
|
||||
ReferenceBlock = 0xFB,
|
||||
// ReferenceVirtual = 0xFD,
|
||||
// CodecState = 0xA4,
|
||||
// Slices = 0x8E,
|
||||
// TimeSlice = 0xE8,
|
||||
LaceNumber = 0xCC,
|
||||
// FrameNumber = 0xCD,
|
||||
// BlockAdditionID = 0xCB,
|
||||
// MkvDelay = 0xCE,
|
||||
// Cluster_Duration = 0xCF,
|
||||
SimpleBlock = 0xA3,
|
||||
// EncryptedBlock = 0xAF,
|
||||
//Track
|
||||
Tracks = 0x1654AE6B,
|
||||
TrackEntry = 0xAE,
|
||||
TrackNumber = 0xD7,
|
||||
TrackUID = 0x73C5,
|
||||
TrackType = 0x83,
|
||||
FlagEnabled = 0xB9,
|
||||
FlagDefault = 0x88,
|
||||
FlagForced = 0x55AA,
|
||||
FlagLacing = 0x9C,
|
||||
// MinCache = 0x6DE7,
|
||||
// MaxCache = 0x6DF8,
|
||||
DefaultDuration = 0x23E383,
|
||||
// TrackTimecodeScale = 0x23314F,
|
||||
// TrackOffset = 0x537F,
|
||||
// MaxBlockAdditionID = 0x55EE,
|
||||
Name = 0x536E,
|
||||
Language = 0x22B59C,
|
||||
CodecID = 0x86,
|
||||
CodecPrivate = 0x63A2,
|
||||
CodecName = 0x258688,
|
||||
// AttachmentLink = 0x7446,
|
||||
// CodecSettings = 0x3A9697,
|
||||
// CodecInfoURL = 0x3B4040,
|
||||
// CodecDownloadURL = 0x26B240,
|
||||
// CodecDecodeAll = 0xAA,
|
||||
// TrackOverlay = 0x6FAB,
|
||||
// TrackTranslate = 0x6624,
|
||||
// TrackTranslateEditionUID = 0x66FC,
|
||||
// TrackTranslateCodec = 0x66BF,
|
||||
// TrackTranslateTrackID = 0x66A5,
|
||||
//video
|
||||
Video = 0xE0,
|
||||
FlagInterlaced = 0x9A,
|
||||
// StereoMode = 0x53B8,
|
||||
PixelWidth = 0xB0,
|
||||
PixelHeight = 0xBA,
|
||||
PixelCropBottom = 0x54AA,
|
||||
PixelCropTop = 0x54BB,
|
||||
PixelCropLeft = 0x54CC,
|
||||
PixelCropRight = 0x54DD,
|
||||
DisplayWidth = 0x54B0,
|
||||
DisplayHeight = 0x54BA,
|
||||
DisplayUnit = 0x54B2,
|
||||
AspectRatioType = 0x54B3,
|
||||
// ColourSpace = 0x2EB524,
|
||||
// GammaValue = 0x2FB523,
|
||||
FrameRate = 0x2383E3,
|
||||
//end video
|
||||
//audio
|
||||
Audio = 0xE1,
|
||||
SamplingFrequency = 0xB5,
|
||||
OutputSamplingFrequency = 0x78B5,
|
||||
Channels = 0x9F,
|
||||
// ChannelPositions = 0x7D7B,
|
||||
BitDepth = 0x6264,
|
||||
//end audio
|
||||
//content encoding
|
||||
// ContentEncodings = 0x6d80,
|
||||
// ContentEncoding = 0x6240,
|
||||
// ContentEncodingOrder = 0x5031,
|
||||
// ContentEncodingScope = 0x5032,
|
||||
// ContentEncodingType = 0x5033,
|
||||
// ContentCompression = 0x5034,
|
||||
// ContentCompAlgo = 0x4254,
|
||||
// ContentCompSettings = 0x4255,
|
||||
// ContentEncryption = 0x5035,
|
||||
// ContentEncAlgo = 0x47e1,
|
||||
// ContentEncKeyID = 0x47e2,
|
||||
// ContentSignature = 0x47e3,
|
||||
// ContentSigKeyID = 0x47e4,
|
||||
// ContentSigAlgo = 0x47e5,
|
||||
// ContentSigHashAlgo = 0x47e6,
|
||||
//end content encoding
|
||||
//Cueing Data
|
||||
Cues = 0x1C53BB6B,
|
||||
CuePoint = 0xBB,
|
||||
CueTime = 0xB3,
|
||||
CueTrackPositions = 0xB7,
|
||||
CueTrack = 0xF7,
|
||||
CueClusterPosition = 0xF1,
|
||||
CueBlockNumber = 0x5378,
|
||||
// CueCodecState = 0xEA,
|
||||
// CueReference = 0xDB,
|
||||
// CueRefTime = 0x96,
|
||||
// CueRefCluster = 0x97,
|
||||
// CueRefNumber = 0x535F,
|
||||
// CueRefCodecState = 0xEB,
|
||||
//Attachment
|
||||
// Attachments = 0x1941A469,
|
||||
// AttachedFile = 0x61A7,
|
||||
// FileDescription = 0x467E,
|
||||
// FileName = 0x466E,
|
||||
// FileMimeType = 0x4660,
|
||||
// FileData = 0x465C,
|
||||
// FileUID = 0x46AE,
|
||||
// FileReferral = 0x4675,
|
||||
//Chapters
|
||||
// Chapters = 0x1043A770,
|
||||
// EditionEntry = 0x45B9,
|
||||
// EditionUID = 0x45BC,
|
||||
// EditionFlagHidden = 0x45BD,
|
||||
// EditionFlagDefault = 0x45DB,
|
||||
// EditionFlagOrdered = 0x45DD,
|
||||
// ChapterAtom = 0xB6,
|
||||
// ChapterUID = 0x73C4,
|
||||
// ChapterTimeStart = 0x91,
|
||||
// ChapterTimeEnd = 0x92,
|
||||
// ChapterFlagHidden = 0x98,
|
||||
// ChapterFlagEnabled = 0x4598,
|
||||
// ChapterSegmentUID = 0x6E67,
|
||||
// ChapterSegmentEditionUID = 0x6EBC,
|
||||
// ChapterPhysicalEquiv = 0x63C3,
|
||||
// ChapterTrack = 0x8F,
|
||||
// ChapterTrackNumber = 0x89,
|
||||
// ChapterDisplay = 0x80,
|
||||
// ChapString = 0x85,
|
||||
// ChapLanguage = 0x437C,
|
||||
// ChapCountry = 0x437E,
|
||||
// ChapProcess = 0x6944,
|
||||
// ChapProcessCodecID = 0x6955,
|
||||
// ChapProcessPrivate = 0x450D,
|
||||
// ChapProcessCommand = 0x6911,
|
||||
// ChapProcessTime = 0x6922,
|
||||
// ChapProcessData = 0x6933,
|
||||
//Tagging
|
||||
// Tags = 0x1254C367,
|
||||
// Tag = 0x7373,
|
||||
// Targets = 0x63C0,
|
||||
// TargetTypeValue = 0x68CA,
|
||||
// TargetType = 0x63CA,
|
||||
// Tagging_TrackUID = 0x63C5,
|
||||
// Tagging_EditionUID = 0x63C9,
|
||||
// Tagging_ChapterUID = 0x63C4,
|
||||
// AttachmentUID = 0x63C6,
|
||||
// SimpleTag = 0x67C8,
|
||||
// TagName = 0x45A3,
|
||||
// TagLanguage = 0x447A,
|
||||
// TagDefault = 0x4484,
|
||||
// TagString = 0x4487,
|
||||
// TagBinary = 0x4485,
|
||||
};
|
||||
#endif
|
166
libmkv/EbmlWriter.c
Normal file
166
libmkv/EbmlWriter.c
Normal file
@ -0,0 +1,166 @@
|
||||
// Copyright (c) 2010 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 "EbmlWriter.h"
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <string.h>
|
||||
#if defined(_MSC_VER)
|
||||
#define LITERALU64(n) n
|
||||
#else
|
||||
#define LITERALU64(n) n##LLU
|
||||
#endif
|
||||
|
||||
void Ebml_WriteLen(EbmlGlobal *glob, long long val)
|
||||
{
|
||||
//TODO check and make sure we are not > than 0x0100000000000000LLU
|
||||
unsigned char size = 8; //size in bytes to output
|
||||
unsigned long long minVal = LITERALU64(0x00000000000000ff); //mask to compare for byte size
|
||||
|
||||
for (size = 1; size < 8; size ++)
|
||||
{
|
||||
if (val < minVal)
|
||||
break;
|
||||
|
||||
minVal = (minVal << 7);
|
||||
}
|
||||
|
||||
val |= (LITERALU64(0x000000000000080) << ((size - 1) * 7));
|
||||
|
||||
Ebml_Serialize(glob, (void *) &val, size);
|
||||
}
|
||||
|
||||
void Ebml_WriteString(EbmlGlobal *glob, const char *str)
|
||||
{
|
||||
const size_t size_ = strlen(str);
|
||||
const unsigned long long size = size_;
|
||||
Ebml_WriteLen(glob, size);
|
||||
//TODO: it's not clear from the spec whether the nul terminator
|
||||
//should be serialized too. For now we omit the null terminator.
|
||||
Ebml_Write(glob, str, size);
|
||||
}
|
||||
|
||||
void Ebml_WriteUTF8(EbmlGlobal *glob, const wchar_t *wstr)
|
||||
{
|
||||
const size_t strlen = wcslen(wstr);
|
||||
|
||||
//TODO: it's not clear from the spec whether the nul terminator
|
||||
//should be serialized too. For now we include it.
|
||||
const unsigned long long size = strlen;
|
||||
|
||||
Ebml_WriteLen(glob, size);
|
||||
Ebml_Write(glob, wstr, size);
|
||||
}
|
||||
|
||||
void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id)
|
||||
{
|
||||
if (class_id >= 0x01000000)
|
||||
Ebml_Serialize(glob, (void *)&class_id, 4);
|
||||
else if (class_id >= 0x00010000)
|
||||
Ebml_Serialize(glob, (void *)&class_id, 3);
|
||||
else if (class_id >= 0x00000100)
|
||||
Ebml_Serialize(glob, (void *)&class_id, 2);
|
||||
else
|
||||
Ebml_Serialize(glob, (void *)&class_id, 1);
|
||||
}
|
||||
void Ebml_SerializeUnsigned64(EbmlGlobal *glob, unsigned long class_id, uint64_t ui)
|
||||
{
|
||||
unsigned char sizeSerialized = 8 | 0x80;
|
||||
Ebml_WriteID(glob, class_id);
|
||||
Ebml_Serialize(glob, &sizeSerialized, 1);
|
||||
Ebml_Serialize(glob, &ui, 8);
|
||||
}
|
||||
|
||||
void Ebml_SerializeUnsigned(EbmlGlobal *glob, unsigned long class_id, unsigned long ui)
|
||||
{
|
||||
unsigned char size = 8; //size in bytes to output
|
||||
unsigned char sizeSerialized = 0;
|
||||
unsigned long minVal;
|
||||
|
||||
Ebml_WriteID(glob, class_id);
|
||||
minVal = 0x7fLU; //mask to compare for byte size
|
||||
|
||||
for (size = 1; size < 4; size ++)
|
||||
{
|
||||
if (ui < minVal)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
minVal <<= 7;
|
||||
}
|
||||
|
||||
sizeSerialized = 0x80 | size;
|
||||
Ebml_Serialize(glob, &sizeSerialized, 1);
|
||||
Ebml_Serialize(glob, &ui, size);
|
||||
}
|
||||
//TODO: perhaps this is a poor name for this id serializer helper function
|
||||
void Ebml_SerializeBinary(EbmlGlobal *glob, unsigned long class_id, unsigned long bin)
|
||||
{
|
||||
int size;
|
||||
for (size=4; size > 1; size--)
|
||||
{
|
||||
if (bin & 0x000000ff << ((size-1) * 8))
|
||||
break;
|
||||
}
|
||||
Ebml_WriteID(glob, class_id);
|
||||
Ebml_WriteLen(glob, size);
|
||||
Ebml_WriteID(glob, bin);
|
||||
}
|
||||
|
||||
void Ebml_SerializeFloat(EbmlGlobal *glob, unsigned long class_id, double d)
|
||||
{
|
||||
unsigned char len = 0x88;
|
||||
|
||||
Ebml_WriteID(glob, class_id);
|
||||
Ebml_Serialize(glob, &len, 1);
|
||||
Ebml_Serialize(glob, &d, 8);
|
||||
}
|
||||
|
||||
void Ebml_WriteSigned16(EbmlGlobal *glob, short val)
|
||||
{
|
||||
signed long out = ((val & 0x003FFFFF) | 0x00200000) << 8;
|
||||
Ebml_Serialize(glob, &out, 3);
|
||||
}
|
||||
|
||||
void Ebml_SerializeString(EbmlGlobal *glob, unsigned long class_id, const char *s)
|
||||
{
|
||||
Ebml_WriteID(glob, class_id);
|
||||
Ebml_WriteString(glob, s);
|
||||
}
|
||||
|
||||
void Ebml_SerializeUTF8(EbmlGlobal *glob, unsigned long class_id, wchar_t *s)
|
||||
{
|
||||
Ebml_WriteID(glob, class_id);
|
||||
Ebml_WriteUTF8(glob, s);
|
||||
}
|
||||
|
||||
void Ebml_SerializeData(EbmlGlobal *glob, unsigned long class_id, unsigned char *data, unsigned long data_length)
|
||||
{
|
||||
unsigned char size = 4;
|
||||
Ebml_WriteID(glob, class_id);
|
||||
Ebml_WriteLen(glob, data_length);
|
||||
Ebml_Write(glob, data, data_length);
|
||||
}
|
||||
|
||||
void Ebml_WriteVoid(EbmlGlobal *glob, unsigned long vSize)
|
||||
{
|
||||
unsigned char tmp = 0;
|
||||
unsigned long i = 0;
|
||||
|
||||
Ebml_WriteID(glob, 0xEC);
|
||||
Ebml_WriteLen(glob, vSize);
|
||||
|
||||
for (i = 0; i < vSize; i++)
|
||||
{
|
||||
Ebml_Write(glob, &tmp, 1);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO Serialize Date
|
38
libmkv/EbmlWriter.h
Normal file
38
libmkv/EbmlWriter.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef EBMLWRITER_HPP
|
||||
#define EBMLWRITER_HPP
|
||||
|
||||
// Copyright (c) 2010 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.
|
||||
|
||||
//note: you must define write and serialize functions as well as your own EBML_GLOBAL
|
||||
//These functions MUST be implemented
|
||||
#include <stddef.h>
|
||||
#include "vpx/vpx_integer.h"
|
||||
|
||||
typedef struct EbmlGlobal EbmlGlobal;
|
||||
void Ebml_Serialize(EbmlGlobal *glob, const void *, unsigned long);
|
||||
void Ebml_Write(EbmlGlobal *glob, const void *, unsigned long);
|
||||
/////
|
||||
|
||||
|
||||
void Ebml_WriteLen(EbmlGlobal *glob, long long val);
|
||||
void Ebml_WriteString(EbmlGlobal *glob, const char *str);
|
||||
void Ebml_WriteUTF8(EbmlGlobal *glob, const wchar_t *wstr);
|
||||
void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id);
|
||||
void Ebml_SerializeUnsigned64(EbmlGlobal *glob, unsigned long class_id, uint64_t ui);
|
||||
void Ebml_SerializeUnsigned(EbmlGlobal *glob, unsigned long class_id, unsigned long ui);
|
||||
void Ebml_SerializeBinary(EbmlGlobal *glob, unsigned long class_id, unsigned long ui);
|
||||
void Ebml_SerializeFloat(EbmlGlobal *glob, unsigned long class_id, double d);
|
||||
//TODO make this more generic to signed
|
||||
void Ebml_WriteSigned16(EbmlGlobal *glob, short val);
|
||||
void Ebml_SerializeString(EbmlGlobal *glob, unsigned long class_id, const char *s);
|
||||
void Ebml_SerializeUTF8(EbmlGlobal *glob, unsigned long class_id, wchar_t *s);
|
||||
void Ebml_SerializeData(EbmlGlobal *glob, unsigned long class_id, unsigned char *data, unsigned long data_length);
|
||||
void Ebml_WriteVoid(EbmlGlobal *glob, unsigned long vSize);
|
||||
//TODO need date function
|
||||
#endif
|
25
libmkv/Makefile
Normal file
25
libmkv/Makefile
Normal file
@ -0,0 +1,25 @@
|
||||
#Variables
|
||||
CC=gcc
|
||||
LINKER=gcc
|
||||
FLAGS=
|
||||
|
||||
|
||||
#Build Targets
|
||||
EbmlWriter.o: EbmlWriter.c EbmlWriter.h
|
||||
$(CC) $(FLAGS) -c EbmlWriter.c
|
||||
|
||||
EbmlBufferWriter.o: EbmlBufferWriter.c EbmlBufferWriter.h
|
||||
$(CC) $(FLAGS) -c EbmlBufferWriter.c
|
||||
|
||||
MkvElement.o: MkvElement.c WebMElement.h
|
||||
$(CC) $(FLAGS) -c MkvElement.c
|
||||
|
||||
testlibmkv.o: testlibmkv.c
|
||||
$(CC) $(FLAGS) -c testlibmkv.c
|
||||
|
||||
testlibmkv: testlibmkv.o MkvElement.o EbmlBufferWriter.o EbmlWriter.o
|
||||
$(LINKER) $(FLAGS) testlibmkv.o MkvElement.o EbmlBufferWriter.o EbmlWriter.o -o testlibmkv
|
||||
|
||||
clean:
|
||||
rm -rf *.o testlibmkv
|
||||
|
220
libmkv/WebMElement.c
Normal file
220
libmkv/WebMElement.c
Normal file
@ -0,0 +1,220 @@
|
||||
// Copyright (c) 2010 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 "EbmlBufferWriter.h"
|
||||
#include "EbmlIDs.h"
|
||||
#include "WebMElement.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define kVorbisPrivateMaxSize 4000
|
||||
|
||||
void writeHeader(EbmlGlobal *glob)
|
||||
{
|
||||
EbmlLoc start;
|
||||
Ebml_StartSubElement(glob, &start, EBML);
|
||||
Ebml_SerializeUnsigned(glob, EBMLVersion, 1);
|
||||
Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1); //EBML Read Version
|
||||
Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4); //EBML Max ID Length
|
||||
Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8); //EBML Max Size Length
|
||||
Ebml_SerializeString(glob, DocType, "webm"); //Doc Type
|
||||
Ebml_SerializeUnsigned(glob, DocTypeVersion, 2); //Doc Type Version
|
||||
Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2); //Doc Type Read Version
|
||||
Ebml_EndSubElement(glob, &start);
|
||||
}
|
||||
|
||||
void writeSimpleBlock(EbmlGlobal *glob, unsigned char trackNumber, short timeCode,
|
||||
int isKeyframe, unsigned char lacingFlag, int discardable,
|
||||
unsigned char *data, unsigned long dataLength)
|
||||
{
|
||||
Ebml_WriteID(glob, SimpleBlock);
|
||||
unsigned long blockLength = 4 + dataLength;
|
||||
blockLength |= 0x10000000; //TODO check length < 0x0FFFFFFFF
|
||||
Ebml_Serialize(glob, &blockLength, 4);
|
||||
trackNumber |= 0x80; //TODO check track nubmer < 128
|
||||
Ebml_Write(glob, &trackNumber, 1);
|
||||
//Ebml_WriteSigned16(glob, timeCode,2); //this is 3 bytes
|
||||
Ebml_Serialize(glob, &timeCode, 2);
|
||||
unsigned char flags = 0x00 | (isKeyframe ? 0x80 : 0x00) | (lacingFlag << 1) | discardable;
|
||||
Ebml_Write(glob, &flags, 1);
|
||||
Ebml_Write(glob, data, dataLength);
|
||||
}
|
||||
|
||||
static UInt64 generateTrackID(unsigned int trackNumber)
|
||||
{
|
||||
UInt64 t = time(NULL) * trackNumber;
|
||||
UInt64 r = rand();
|
||||
r = r << 32;
|
||||
r += rand();
|
||||
UInt64 rval = t ^ r;
|
||||
return rval;
|
||||
}
|
||||
|
||||
void writeVideoTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
|
||||
char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
|
||||
double frameRate)
|
||||
{
|
||||
EbmlLoc start;
|
||||
Ebml_StartSubElement(glob, &start, TrackEntry);
|
||||
Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
|
||||
UInt64 trackID = generateTrackID(trackNumber);
|
||||
Ebml_SerializeUnsigned(glob, TrackUID, trackID);
|
||||
Ebml_SerializeString(glob, CodecName, "VP8"); //TODO shouldn't be fixed
|
||||
|
||||
Ebml_SerializeUnsigned(glob, TrackType, 1); //video is always 1
|
||||
Ebml_SerializeString(glob, CodecID, codecId);
|
||||
{
|
||||
EbmlLoc videoStart;
|
||||
Ebml_StartSubElement(glob, &videoStart, Video);
|
||||
Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
|
||||
Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
|
||||
Ebml_SerializeFloat(glob, FrameRate, frameRate);
|
||||
Ebml_EndSubElement(glob, &videoStart); //Video
|
||||
}
|
||||
Ebml_EndSubElement(glob, &start); //Track Entry
|
||||
}
|
||||
void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
|
||||
char *codecId, double samplingFrequency, unsigned int channels,
|
||||
unsigned char *private, unsigned long privateSize)
|
||||
{
|
||||
EbmlLoc start;
|
||||
Ebml_StartSubElement(glob, &start, TrackEntry);
|
||||
Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
|
||||
UInt64 trackID = generateTrackID(trackNumber);
|
||||
Ebml_SerializeUnsigned(glob, TrackUID, trackID);
|
||||
Ebml_SerializeUnsigned(glob, TrackType, 2); //audio is always 2
|
||||
//I am using defaults for thesed required fields
|
||||
/* Ebml_SerializeUnsigned(glob, FlagEnabled, 1);
|
||||
Ebml_SerializeUnsigned(glob, FlagDefault, 1);
|
||||
Ebml_SerializeUnsigned(glob, FlagForced, 1);
|
||||
Ebml_SerializeUnsigned(glob, FlagLacing, flagLacing);*/
|
||||
Ebml_SerializeString(glob, CodecID, codecId);
|
||||
Ebml_SerializeData(glob, CodecPrivate, private, privateSize);
|
||||
|
||||
Ebml_SerializeString(glob, CodecName, "VORBIS"); //fixed for now
|
||||
{
|
||||
EbmlLoc AudioStart;
|
||||
Ebml_StartSubElement(glob, &AudioStart, Audio);
|
||||
Ebml_SerializeFloat(glob, SamplingFrequency, samplingFrequency);
|
||||
Ebml_SerializeUnsigned(glob, Channels, channels);
|
||||
Ebml_EndSubElement(glob, &AudioStart);
|
||||
}
|
||||
Ebml_EndSubElement(glob, &start);
|
||||
}
|
||||
void writeSegmentInformation(EbmlGlobal *ebml, EbmlLoc* startInfo, unsigned long timeCodeScale, double duration)
|
||||
{
|
||||
Ebml_StartSubElement(ebml, startInfo, Info);
|
||||
Ebml_SerializeUnsigned(ebml, TimecodeScale, timeCodeScale);
|
||||
Ebml_SerializeFloat(ebml, Segment_Duration, duration * 1000.0); //Currently fixed to using milliseconds
|
||||
Ebml_SerializeString(ebml, 0x4D80, "QTmuxingAppLibWebM-0.0.1");
|
||||
Ebml_SerializeString(ebml, 0x5741, "QTwritingAppLibWebM-0.0.1");
|
||||
Ebml_EndSubElement(ebml, startInfo);
|
||||
}
|
||||
|
||||
/*
|
||||
void Mkv_InitializeSegment(Ebml& ebml_out, EbmlLoc& ebmlLoc)
|
||||
{
|
||||
Ebml_StartSubElement(ebml_out, ebmlLoc, 0x18538067);
|
||||
}
|
||||
|
||||
void Mkv_InitializeSeek(Ebml& ebml_out, EbmlLoc& ebmlLoc)
|
||||
{
|
||||
Ebml_StartSubElement(ebml_out, ebmlLoc, 0x114d9b74);
|
||||
}
|
||||
void Mkv_WriteSeekInformation(Ebml& ebml_out, SeekStruct& seekInformation)
|
||||
{
|
||||
EbmlLoc ebmlLoc;
|
||||
Ebml_StartSubElement(ebml_out, ebmlLoc, 0x4dbb);
|
||||
Ebml_SerializeString(ebml_out, 0x53ab, seekInformation.SeekID);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0x53ac, seekInformation.SeekPosition);
|
||||
Ebml_EndSubElement(ebml_out, ebmlLoc);
|
||||
}
|
||||
|
||||
void Mkv_WriteSegmentInformation(Ebml& ebml_out, SegmentInformationStruct& segmentInformation)
|
||||
{
|
||||
Ebml_SerializeUnsigned(ebml_out, 0x73a4, segmentInformation.segmentUID);
|
||||
if (segmentInformation.filename != 0)
|
||||
Ebml_SerializeString(ebml_out, 0x7384, segmentInformation.filename);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0x2AD7B1, segmentInformation.TimecodeScale);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0x4489, segmentInformation.Duration);
|
||||
//TODO date
|
||||
Ebml_SerializeWString(ebml_out, 0x4D80, L"MKVMUX");
|
||||
Ebml_SerializeWString(ebml_out, 0x5741, segmentInformation.WritingApp);
|
||||
}
|
||||
|
||||
void Mkv_InitializeTrack(Ebml& ebml_out, EbmlLoc& ebmlLoc)
|
||||
{
|
||||
Ebml_StartSubElement(ebml_out, ebmlLoc, 0x1654AE6B);
|
||||
}
|
||||
|
||||
static void Mkv_WriteGenericTrackData(Ebml& ebml_out, TrackStruct& track)
|
||||
{
|
||||
Ebml_SerializeUnsigned(ebml_out, 0xD7, track.TrackNumber);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0x73C5, track.TrackUID);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0x83, track.TrackType);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0xB9, track.FlagEnabled ? 1 :0);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0x88, track.FlagDefault ? 1 :0);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0x55AA, track.FlagForced ? 1 :0);
|
||||
if (track.Language != 0)
|
||||
Ebml_SerializeString(ebml_out, 0x22B59C, track.Language);
|
||||
if (track.CodecID != 0)
|
||||
Ebml_SerializeString(ebml_out, 0x86, track.CodecID);
|
||||
if (track.CodecPrivate != 0)
|
||||
Ebml_SerializeData(ebml_out, 0x63A2, track.CodecPrivate, track.CodecPrivateLength);
|
||||
if (track.CodecName != 0)
|
||||
Ebml_SerializeWString(ebml_out, 0x258688, track.CodecName);
|
||||
}
|
||||
|
||||
void Mkv_WriteVideoTrack(Ebml& ebml_out, TrackStruct & track, VideoTrackStruct& video)
|
||||
{
|
||||
EbmlLoc trackHeadLoc, videoHeadLoc;
|
||||
Ebml_StartSubElement(ebml_out, trackHeadLoc, 0xAE); //start Track
|
||||
Mkv_WriteGenericTrackData(ebml_out, track);
|
||||
Ebml_StartSubElement(ebml_out, videoHeadLoc, 0xE0); //start Video
|
||||
Ebml_SerializeUnsigned(ebml_out, 0x9A, video.FlagInterlaced ? 1 :0);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0xB0, video.PixelWidth);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0xBA, video.PixelHeight);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0x54B0, video.PixelDisplayWidth);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0x54BA, video.PixelDisplayHeight);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0x54B2, video.displayUnit);
|
||||
Ebml_SerializeFloat(ebml_out, 0x2383E3, video.FrameRate);
|
||||
Ebml_EndSubElement(ebml_out, videoHeadLoc);
|
||||
Ebml_EndSubElement(ebml_out, trackHeadLoc);
|
||||
|
||||
}
|
||||
|
||||
void Mkv_WriteAudioTrack(Ebml& ebml_out, TrackStruct & track, AudioTrackStruct& video)
|
||||
{
|
||||
EbmlLoc trackHeadLoc, audioHeadLoc;
|
||||
Ebml_StartSubElement(ebml_out, trackHeadLoc, 0xAE);
|
||||
Mkv_WriteGenericTrackData(ebml_out, track);
|
||||
Ebml_StartSubElement(ebml_out, audioHeadLoc, 0xE0); //start Audio
|
||||
Ebml_SerializeFloat(ebml_out, 0xB5, video.SamplingFrequency);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0x9F, video.Channels);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0x6264, video.BitDepth);
|
||||
Ebml_EndSubElement(ebml_out, audioHeadLoc); // end audio
|
||||
Ebml_EndSubElement(ebml_out, trackHeadLoc);
|
||||
}
|
||||
|
||||
void Mkv_WriteEbmlClusterHead(Ebml& ebml_out, EbmlLoc& ebmlLoc, ClusterHeadStruct & clusterHead)
|
||||
{
|
||||
Ebml_StartSubElement(ebml_out, ebmlLoc, 0x1F43B675);
|
||||
Ebml_SerializeUnsigned(ebml_out, 0x6264, clusterHead.TimeCode);
|
||||
}
|
||||
|
||||
void Mkv_WriteSimpleBlockHead(Ebml& ebml_out, EbmlLoc& ebmlLoc, SimpleBlockStruct& block)
|
||||
{
|
||||
Ebml_StartSubElement(ebml_out, ebmlLoc, 0xA3);
|
||||
Ebml_Write1UInt(ebml_out, block.TrackNumber);
|
||||
Ebml_WriteSigned16(ebml_out,block.TimeCode);
|
||||
unsigned char flags = 0x00 | (block.iskey ? 0x80:0x00) | (block.lacing << 1) | block.discardable;
|
||||
Ebml_Write1UInt(ebml_out, flags); //TODO this may be the wrong function
|
||||
Ebml_Serialize(ebml_out, block.data, block.dataLength);
|
||||
Ebml_EndSubElement(ebml_out,ebmlLoc);
|
||||
}
|
||||
*/
|
35
libmkv/WebMElement.h
Normal file
35
libmkv/WebMElement.h
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2010 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 MKV_CONTEXT_HPP
|
||||
#define MKV_CONTEXT_HPP 1
|
||||
|
||||
void writeSimpleBock(EbmlGlobal *ebml, unsigned char trackNumber, unsigned short timeCode,
|
||||
int isKeyframe, unsigned char lacingFlag, int discardable,
|
||||
unsigned char *data, unsigned long dataLength);
|
||||
|
||||
|
||||
// these are helper functions
|
||||
void writeHeader(EbmlGlobal *ebml);
|
||||
void writeSegmentInformation(EbmlGlobal *ebml, EbmlLoc* startInfo , unsigned long timeCodeScale, double duration);
|
||||
//this function is a helper only, it assumes a lot of defaults
|
||||
void writeVideoTrack(EbmlGlobal *ebml, unsigned int trackNumber, int flagLacing,
|
||||
char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
|
||||
double frameRate);
|
||||
void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
|
||||
char *codecId, double samplingFrequency, unsigned int channels,
|
||||
unsigned char *private, unsigned long privateSize);
|
||||
|
||||
void writeSimpleBlock(EbmlGlobal *ebml, unsigned char trackNumber, short timeCode,
|
||||
int isKeyframe, unsigned char lacingFlag, int discardable,
|
||||
unsigned char *data, unsigned long dataLength);
|
||||
|
||||
|
||||
|
||||
#endif
|
63
libmkv/testlibmkv.c
Normal file
63
libmkv/testlibmkv.c
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright (c) 2010 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 "EbmlIDs.h"
|
||||
#include "EbmlBufferWriter.h"
|
||||
#include "WebMElement.h"
|
||||
|
||||
#include <stdio.h>
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
//init the datatype we're using for ebml output
|
||||
unsigned char data[8192];
|
||||
EbmlGlobal ebml;
|
||||
ebml.buf = data;
|
||||
ebml.offset = 0;
|
||||
ebml.length = 8192;
|
||||
|
||||
writeHeader(&ebml);
|
||||
{
|
||||
EbmlLoc startSegment;
|
||||
Ebml_StartSubElement(&ebml, &startSegment, Segment); //segment
|
||||
{
|
||||
//segment info
|
||||
EbmlLoc startInfo;
|
||||
Ebml_StartSubElement(&ebml, &startInfo, Info);
|
||||
Ebml_SerializeString(&ebml, 0x4D80, "muxingAppLibMkv");
|
||||
Ebml_SerializeString(&ebml, 0x5741, "writingAppLibMkv");
|
||||
Ebml_EndSubElement(&ebml, &startInfo);
|
||||
}
|
||||
|
||||
{
|
||||
EbmlLoc trackStart;
|
||||
Ebml_StartSubElement(&ebml, &trackStart, Tracks);
|
||||
writeVideoTrack(&ebml, 1, 1, "V_MS/VFW/FOURCC", 320, 240, 29.97);
|
||||
//writeAudioTrack(&ebml,2,1, "A_VORBIS", 32000, 1, NULL, 0);
|
||||
Ebml_EndSubElement(&ebml, &trackStart);
|
||||
}
|
||||
|
||||
{
|
||||
EbmlLoc clusterStart;
|
||||
Ebml_StartSubElement(&ebml, &clusterStart, Cluster); //cluster
|
||||
Ebml_SerializeUnsigned(&ebml, Timecode, 0);
|
||||
|
||||
unsigned char someData[4] = {1, 2, 3, 4};
|
||||
writeSimpleBlock(&ebml, 1, 0, 1, 0, 0, someData, 4);
|
||||
Ebml_EndSubElement(&ebml, &clusterStart);
|
||||
} //end cluster
|
||||
Ebml_EndSubElement(&ebml, &startSegment);
|
||||
}
|
||||
|
||||
//dump ebml stuff to the file
|
||||
FILE *file_out = fopen("test.mkv", "wb");
|
||||
size_t bytesWritten = fwrite(data, 1, ebml.offset, file_out);
|
||||
fclose(file_out);
|
||||
return 0;
|
||||
}
|
40
nestegg/.gitignore
vendored
Normal file
40
nestegg/.gitignore
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
*.lo
|
||||
*.o
|
||||
*.swp
|
||||
*~
|
||||
.deps
|
||||
.dirstamp
|
||||
.libs
|
||||
Makefile
|
||||
Makefile.in
|
||||
_stdint.h
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
compile
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
docs/Doxyfile
|
||||
docs/doxygen-build.stamp
|
||||
docs/html
|
||||
install-sh
|
||||
libtool
|
||||
ltmain.sh
|
||||
m4/libtool.m4
|
||||
m4/ltoptions.m4
|
||||
m4/ltsugar.m4
|
||||
m4/ltversion.m4
|
||||
m4/lt~obsolete.m4
|
||||
missing
|
||||
nestegg-uninstalled.pc
|
||||
nestegg.pc
|
||||
src/.dirstamp
|
||||
src/libnestegg.la
|
||||
stamp-h1
|
||||
test/test
|
||||
include/nestegg/nestegg-stdint.h
|
1
nestegg/AUTHORS
Normal file
1
nestegg/AUTHORS
Normal file
@ -0,0 +1 @@
|
||||
Matthew Gregan <kinetik@flim.org>
|
8
nestegg/INSTALL
Normal file
8
nestegg/INSTALL
Normal file
@ -0,0 +1,8 @@
|
||||
Build instructions for libnestegg
|
||||
=================================
|
||||
|
||||
0. Change directory into the source directory.
|
||||
1. Run |autoreconf --install| to generate configure.
|
||||
2. Run |./configure| to configure the build.
|
||||
3. Run |make| to build.
|
||||
4. Run |make check| to run the test suite.
|
13
nestegg/LICENSE
Normal file
13
nestegg/LICENSE
Normal file
@ -0,0 +1,13 @@
|
||||
Copyright © 2010 Mozilla Foundation
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
51
nestegg/Makefile.am
Normal file
51
nestegg/Makefile.am
Normal file
@ -0,0 +1,51 @@
|
||||
AUTOMAKE_OPTIONS = foreign 1.11 no-dist-gzip dist-bzip2 subdir-objects
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include -I. -I$(top_srcdir)/halloc
|
||||
AM_CFLAGS = -ansi -pedantic -Wall -Wextra -Wno-long-long -O0 -g
|
||||
|
||||
SUBDIRS = docs
|
||||
|
||||
EXTRA_DIST = \
|
||||
AUTHORS README LICENSE \
|
||||
nestegg-uninstalled.pc.in \
|
||||
m4/as-ac-expand.m4 \
|
||||
m4/pkg.m4 \
|
||||
m4/ax_create_stdint_h.m4 \
|
||||
halloc/src/halloc.c \
|
||||
halloc/halloc.h \
|
||||
halloc/src/align.h \
|
||||
halloc/src/hlist.h \
|
||||
halloc/src/macros.h
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = nestegg.pc
|
||||
|
||||
nesteggincludedir = $(includedir)/nestegg
|
||||
nestegginclude_HEADERS = include/nestegg/nestegg.h include/nestegg/nestegg-stdint.h
|
||||
|
||||
lib_LTLIBRARIES = src/libnestegg.la
|
||||
|
||||
src_libnestegg_la_SOURCES = \
|
||||
src/nestegg.c \
|
||||
halloc/src/halloc.c \
|
||||
halloc/halloc.h \
|
||||
halloc/src/align.h \
|
||||
halloc/src/hlist.h \
|
||||
halloc/src/macros.h
|
||||
|
||||
check_PROGRAMS = test/test
|
||||
|
||||
test_test_SOURCES = test/test.c
|
||||
test_test_LDADD = src/libnestegg.la
|
||||
|
||||
DISTCLEANFILES = include/nestegg/nestegg-stdint.h
|
||||
|
||||
dist-hook:
|
||||
find $(distdir) -type d -name '.git' | xargs rm -rf
|
||||
|
||||
debug:
|
||||
$(MAKE) all CFLAGS="@DEBUG@"
|
||||
|
||||
profile:
|
||||
$(MAKE) all CFLAGS="@PROFILE@"
|
6
nestegg/README
Normal file
6
nestegg/README
Normal file
@ -0,0 +1,6 @@
|
||||
See INSTALL for build instructions.
|
||||
|
||||
Licensed under an ISC-style license. See LICENSE for details.
|
||||
|
||||
The source under the halloc/ directory is licensed under a BSD license. See
|
||||
halloc/halloc.h for details.
|
21
nestegg/TODO
Normal file
21
nestegg/TODO
Normal file
@ -0,0 +1,21 @@
|
||||
- Document when read, seek, tell callbacks are used.
|
||||
- Add an automated testsuite.
|
||||
- Test (and fix, if necessary) support for unknown sizes.
|
||||
- Test (and fix, if necessary) support for large files.
|
||||
- Read past unknown elements rather than seeking.
|
||||
- Try to handle unknown elements with unknown sizes.
|
||||
- Formalize handling of default element values.
|
||||
- Try to resynchronize stream when read_block fails so that failure to parse
|
||||
a single block can be treated as non-fatal.
|
||||
- Make logging more useful to API users.
|
||||
- Avoid reparsing Cues and ignore any SeekHead at end of file.
|
||||
- Optionally build a Cue index as Clusters are parsed.
|
||||
- Support seeking without Cues.
|
||||
- Avoid building a list of Clusters as they are parsed and retain only the
|
||||
last one parsed.
|
||||
- Add an asynchronous error code to struct nestegg and ensure that API calls
|
||||
continue to fail safely one a fatal error has been returned.
|
||||
- Modify parser/data structures to provide a clean separation. Perhaps the
|
||||
parser should return a generic tree of nodes that a second pass uses to
|
||||
initialize the main data structures.
|
||||
- Use pool allocator for all allocations.
|
124
nestegg/configure.ac
Normal file
124
nestegg/configure.ac
Normal file
@ -0,0 +1,124 @@
|
||||
dnl ------------------------------------------------
|
||||
dnl Initialization and Versioning
|
||||
dnl ------------------------------------------------
|
||||
|
||||
AC_INIT(libnestegg,[0.1git])
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
AC_CANONICAL_TARGET
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AM_CONFIG_HEADER([config.h])
|
||||
AC_CONFIG_SRCDIR([src/nestegg.c])
|
||||
AM_INIT_AUTOMAKE
|
||||
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
dnl Library versioning
|
||||
dnl CURRENT, REVISION, AGE
|
||||
dnl - library source changed -> increment REVISION
|
||||
dnl - interfaces added/removed/changed -> increment CURRENT, REVISION = 0
|
||||
dnl - interfaces added -> increment AGE
|
||||
dnl - interfaces removed -> AGE = 0
|
||||
|
||||
NESTEGG_CURRENT=0
|
||||
NESTEGG_REVISION=0
|
||||
NESTEGG_AGE=1
|
||||
AC_SUBST(NESTEGG_CURRENT)
|
||||
AC_SUBST(NESTEGG_REVISION)
|
||||
AC_SUBST(NESTEGG_AGE)
|
||||
|
||||
|
||||
dnl --------------------------------------------------
|
||||
dnl Check for programs
|
||||
dnl --------------------------------------------------
|
||||
|
||||
dnl save $CFLAGS since AC_PROG_CC likes to insert "-g -O2"
|
||||
dnl if $CFLAGS is blank
|
||||
cflags_save="$CFLAGS"
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
CFLAGS="$cflags_save"
|
||||
|
||||
AM_PROG_CC_C_O
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AM_PROG_LIBTOOL
|
||||
|
||||
dnl Check for doxygen
|
||||
AC_ARG_ENABLE([doc],
|
||||
AS_HELP_STRING([--enable-doc], [Build API documentation]),
|
||||
[ac_enable_doc=$enableval], [ac_enable_doc=auto])
|
||||
|
||||
if test "x$ac_enable_doc" != "xno"; then
|
||||
AC_CHECK_PROG(HAVE_DOXYGEN, doxygen, true, false)
|
||||
|
||||
if test "x$HAVE_DOXYGEN" = "xfalse" -a "x$ac_enable_doc" = "xyes"; then
|
||||
AC_MSG_ERROR([*** API documentation explicitly requested but Doxygen not found])
|
||||
fi
|
||||
else
|
||||
HAVE_DOXYGEN=false
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_DOXYGEN,$HAVE_DOXYGEN)
|
||||
if test $HAVE_DOXYGEN = "false"; then
|
||||
AC_MSG_WARN([*** doxygen not found, API documentation will not be built])
|
||||
fi
|
||||
|
||||
# Generate portable stdint.h replacement
|
||||
AX_CREATE_STDINT_H(include/nestegg/nestegg-stdint.h)
|
||||
|
||||
# Test whenever ld supports -version-script
|
||||
AC_PROG_LD
|
||||
AC_PROG_LD_GNU
|
||||
AC_MSG_CHECKING([how to control symbol export])
|
||||
|
||||
dnl --------------------------------------------------
|
||||
dnl Do substitutions
|
||||
dnl --------------------------------------------------
|
||||
|
||||
AC_SUBST(DEBUG)
|
||||
AC_SUBST(PROFILE)
|
||||
|
||||
AC_OUTPUT([
|
||||
Makefile
|
||||
docs/Makefile
|
||||
docs/Doxyfile
|
||||
nestegg.pc
|
||||
nestegg-uninstalled.pc
|
||||
])
|
||||
|
||||
AS_AC_EXPAND(LIBDIR, ${libdir})
|
||||
AS_AC_EXPAND(INCLUDEDIR, ${includedir})
|
||||
AS_AC_EXPAND(BINDIR, ${bindir})
|
||||
AS_AC_EXPAND(DOCDIR, ${docdir})
|
||||
|
||||
if test $HAVE_DOXYGEN = "false"; then
|
||||
doc_build="no"
|
||||
else
|
||||
doc_build="yes"
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([
|
||||
------------------------------------------------------------------------
|
||||
$PACKAGE $VERSION: Automatic configuration OK.
|
||||
|
||||
General configuration:
|
||||
|
||||
API Documentation: .......... ${doc_build}
|
||||
|
||||
Installation paths:
|
||||
|
||||
libnestegg: .................. ${LIBDIR}
|
||||
C header files: .............. ${INCLUDEDIR}/nestegg
|
||||
Documentation: ............... ${DOCDIR}
|
||||
|
||||
Building:
|
||||
|
||||
Type 'make' to compile $PACKAGE.
|
||||
|
||||
Type 'make install' to install $PACKAGE.
|
||||
|
||||
Example programs will be built but not installed.
|
||||
------------------------------------------------------------------------
|
||||
])
|
||||
|
1551
nestegg/docs/Doxyfile.in
Normal file
1551
nestegg/docs/Doxyfile.in
Normal file
File diff suppressed because it is too large
Load Diff
38
nestegg/docs/Makefile.am
Normal file
38
nestegg/docs/Makefile.am
Normal file
@ -0,0 +1,38 @@
|
||||
doc_DATA = doxygen-build.stamp
|
||||
|
||||
EXTRA_DIST = Doxyfile.in
|
||||
|
||||
if HAVE_DOXYGEN
|
||||
doxygen-build.stamp: Doxyfile
|
||||
doxygen
|
||||
touch doxygen-build.stamp
|
||||
else
|
||||
doxygen-build.stamp:
|
||||
echo "*** Warning: Doxygen not found; documentation will not be built."
|
||||
touch doxygen-build.stamp
|
||||
endif
|
||||
|
||||
dist_docdir = $(distdir)/libnestegg
|
||||
|
||||
dist-hook:
|
||||
if test -d html; then \
|
||||
mkdir $(dist_docdir); \
|
||||
echo -n "copying built documenation..."; \
|
||||
cp -rp html $(dist_docdir)/html; \
|
||||
echo "OK"; \
|
||||
fi
|
||||
|
||||
|
||||
install-data-local: doxygen-build.stamp
|
||||
$(mkinstalldirs) $(DESTDIR)$(docdir)
|
||||
if test -d html; then \
|
||||
cp -rp html $(DESTDIR)$(docdir)/html; \
|
||||
fi
|
||||
|
||||
uninstall-local:
|
||||
rm -rf $(DESTDIR)$(docdir)
|
||||
|
||||
clean-local:
|
||||
if test -d html; then rm -rf html; fi
|
||||
if test -f doxygen-build.stamp; then rm -f doxygen-build.stamp; fi
|
||||
|
45
nestegg/halloc/README
Normal file
45
nestegg/halloc/README
Normal file
@ -0,0 +1,45 @@
|
||||
halloc 1.2.1
|
||||
============
|
||||
|
||||
Hierarchical memory heap interface - an extension to standard
|
||||
malloc/free interface that simplifies tasks of memory disposal
|
||||
when allocated structures exhibit hierarchical properties.
|
||||
|
||||
http://swapped.cc/halloc
|
||||
=
|
||||
To build libhalloc.a with GNU tools run
|
||||
make
|
||||
|
||||
To install in /usr/include and /usr/lib
|
||||
make install
|
||||
|
||||
To cleanup the build files
|
||||
make clean
|
||||
=
|
||||
halloc-1.2.1
|
||||
* fixed a double-free bug in _set_allocator() as per
|
||||
Matthew Gregan comments
|
||||
|
||||
* switched to using NULL instead of 0 where applicable
|
||||
|
||||
halloc-1.2.0
|
||||
* added missing <string.h> include to halloc.c
|
||||
|
||||
* improved standard compliance thanks to the feedback
|
||||
received from Stan Tobias. Two things were fixed -
|
||||
|
||||
- hblock_t structure no longer uses zero-sized 'data'
|
||||
array, which happened to be common, but non-standard
|
||||
extension;
|
||||
|
||||
- secondly, added the code to test the behaviour of
|
||||
realloc(ptr, 0). Standard allows it NOT to act as
|
||||
free(), in which case halloc will use its own version
|
||||
of allocator calling free() when neccessary.
|
||||
|
||||
halloc-1.1.0
|
||||
* initial public release (rewrite of hhmalloc library)
|
||||
|
||||
=============================================================================
|
||||
Copyright (c) 2004-2010, Alex Pankratov (ap@swapped.cc). All rights reserved.
|
||||
|
43
nestegg/halloc/halloc.h
Normal file
43
nestegg/halloc/halloc.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
|
||||
*
|
||||
* Hierarchical memory allocator, 1.2.1
|
||||
* http://swapped.cc/halloc
|
||||
*/
|
||||
|
||||
/*
|
||||
* The program is distributed under terms of BSD license.
|
||||
* You can obtain the copy of the license by visiting:
|
||||
*
|
||||
* http://www.opensource.org/licenses/bsd-license.php
|
||||
*/
|
||||
|
||||
#ifndef _LIBP_HALLOC_H_
|
||||
#define _LIBP_HALLOC_H_
|
||||
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
/*
|
||||
* Core API
|
||||
*/
|
||||
void * halloc (void * block, size_t len);
|
||||
void hattach(void * block, void * parent);
|
||||
|
||||
/*
|
||||
* standard malloc/free api
|
||||
*/
|
||||
void * h_malloc (size_t len);
|
||||
void * h_calloc (size_t n, size_t len);
|
||||
void * h_realloc(void * p, size_t len);
|
||||
void h_free (void * p);
|
||||
char * h_strdup (const char * str);
|
||||
|
||||
/*
|
||||
* the underlying allocator
|
||||
*/
|
||||
typedef void * (* realloc_t)(void * ptr, size_t len);
|
||||
|
||||
extern realloc_t halloc_allocator;
|
||||
|
||||
#endif
|
||||
|
36
nestegg/halloc/src/align.h
Normal file
36
nestegg/halloc/src/align.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
|
||||
*
|
||||
* Hierarchical memory allocator, 1.2.1
|
||||
* http://swapped.cc/halloc
|
||||
*/
|
||||
|
||||
/*
|
||||
* The program is distributed under terms of BSD license.
|
||||
* You can obtain the copy of the license by visiting:
|
||||
*
|
||||
* http://www.opensource.org/licenses/bsd-license.php
|
||||
*/
|
||||
|
||||
#ifndef _LIBP_ALIGN_H_
|
||||
#define _LIBP_ALIGN_H_
|
||||
|
||||
/*
|
||||
* a type with the most strict alignment requirements
|
||||
*/
|
||||
union max_align
|
||||
{
|
||||
char c;
|
||||
short s;
|
||||
long l;
|
||||
int i;
|
||||
float f;
|
||||
double d;
|
||||
void * v;
|
||||
void (*q)(void);
|
||||
};
|
||||
|
||||
typedef union max_align max_align_t;
|
||||
|
||||
#endif
|
||||
|
254
nestegg/halloc/src/halloc.c
Normal file
254
nestegg/halloc/src/halloc.c
Normal file
@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (c) 2004i-2010 Alex Pankratov. All rights reserved.
|
||||
*
|
||||
* Hierarchical memory allocator, 1.2.1
|
||||
* http://swapped.cc/halloc
|
||||
*/
|
||||
|
||||
/*
|
||||
* The program is distributed under terms of BSD license.
|
||||
* You can obtain the copy of the license by visiting:
|
||||
*
|
||||
* http://www.opensource.org/licenses/bsd-license.php
|
||||
*/
|
||||
|
||||
#include <stdlib.h> /* realloc */
|
||||
#include <string.h> /* memset & co */
|
||||
|
||||
#include "../halloc.h"
|
||||
#include "align.h"
|
||||
#include "hlist.h"
|
||||
|
||||
/*
|
||||
* block control header
|
||||
*/
|
||||
typedef struct hblock
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
#define HH_MAGIC 0x20040518L
|
||||
long magic;
|
||||
#endif
|
||||
hlist_item_t siblings; /* 2 pointers */
|
||||
hlist_head_t children; /* 1 pointer */
|
||||
max_align_t data[1]; /* not allocated, see below */
|
||||
|
||||
} hblock_t;
|
||||
|
||||
#define sizeof_hblock offsetof(hblock_t, data)
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
realloc_t halloc_allocator = NULL;
|
||||
|
||||
#define allocator halloc_allocator
|
||||
|
||||
/*
|
||||
* static methods
|
||||
*/
|
||||
static void _set_allocator(void);
|
||||
static void * _realloc(void * ptr, size_t n);
|
||||
|
||||
static int _relate(hblock_t * b, hblock_t * p);
|
||||
static void _free_children(hblock_t * p);
|
||||
|
||||
/*
|
||||
* Core API
|
||||
*/
|
||||
void * halloc(void * ptr, size_t len)
|
||||
{
|
||||
hblock_t * p;
|
||||
|
||||
/* set up default allocator */
|
||||
if (! allocator)
|
||||
{
|
||||
_set_allocator();
|
||||
assert(allocator);
|
||||
}
|
||||
|
||||
/* calloc */
|
||||
if (! ptr)
|
||||
{
|
||||
if (! len)
|
||||
return NULL;
|
||||
|
||||
p = allocator(0, len + sizeof_hblock);
|
||||
if (! p)
|
||||
return NULL;
|
||||
#ifndef NDEBUG
|
||||
p->magic = HH_MAGIC;
|
||||
#endif
|
||||
hlist_init(&p->children);
|
||||
hlist_init_item(&p->siblings);
|
||||
|
||||
return p->data;
|
||||
}
|
||||
|
||||
p = structof(ptr, hblock_t, data);
|
||||
assert(p->magic == HH_MAGIC);
|
||||
|
||||
/* realloc */
|
||||
if (len)
|
||||
{
|
||||
p = allocator(p, len + sizeof_hblock);
|
||||
if (! p)
|
||||
return NULL;
|
||||
|
||||
hlist_relink(&p->siblings);
|
||||
hlist_relink_head(&p->children);
|
||||
|
||||
return p->data;
|
||||
}
|
||||
|
||||
/* free */
|
||||
_free_children(p);
|
||||
hlist_del(&p->siblings);
|
||||
allocator(p, 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void hattach(void * block, void * parent)
|
||||
{
|
||||
hblock_t * b, * p;
|
||||
|
||||
if (! block)
|
||||
{
|
||||
assert(! parent);
|
||||
return;
|
||||
}
|
||||
|
||||
/* detach */
|
||||
b = structof(block, hblock_t, data);
|
||||
assert(b->magic == HH_MAGIC);
|
||||
|
||||
hlist_del(&b->siblings);
|
||||
|
||||
if (! parent)
|
||||
return;
|
||||
|
||||
/* attach */
|
||||
p = structof(parent, hblock_t, data);
|
||||
assert(p->magic == HH_MAGIC);
|
||||
|
||||
/* sanity checks */
|
||||
assert(b != p); /* trivial */
|
||||
assert(! _relate(p, b)); /* heavy ! */
|
||||
|
||||
hlist_add(&p->children, &b->siblings);
|
||||
}
|
||||
|
||||
/*
|
||||
* malloc/free api
|
||||
*/
|
||||
void * h_malloc(size_t len)
|
||||
{
|
||||
return halloc(0, len);
|
||||
}
|
||||
|
||||
void * h_calloc(size_t n, size_t len)
|
||||
{
|
||||
void * ptr = halloc(0, len*=n);
|
||||
return ptr ? memset(ptr, 0, len) : NULL;
|
||||
}
|
||||
|
||||
void * h_realloc(void * ptr, size_t len)
|
||||
{
|
||||
return halloc(ptr, len);
|
||||
}
|
||||
|
||||
void h_free(void * ptr)
|
||||
{
|
||||
halloc(ptr, 0);
|
||||
}
|
||||
|
||||
char * h_strdup(const char * str)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
char * ptr = halloc(0, len + 1);
|
||||
return ptr ? (ptr[len] = 0, memcpy(ptr, str, len)) : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* static stuff
|
||||
*/
|
||||
static void _set_allocator(void)
|
||||
{
|
||||
void * p;
|
||||
assert(! allocator);
|
||||
|
||||
/*
|
||||
* the purpose of the test below is to check the behaviour
|
||||
* of realloc(ptr, 0), which is defined in the standard
|
||||
* as an implementation-specific. if it returns zero,
|
||||
* then it's equivalent to free(). it can however return
|
||||
* non-zero, in which case it cannot be used for freeing
|
||||
* memory blocks and we'll need to supply our own version
|
||||
*
|
||||
* Thanks to Stan Tobias for pointing this tricky part out.
|
||||
*/
|
||||
allocator = realloc;
|
||||
if (! (p = malloc(1)))
|
||||
/* hmm */
|
||||
return;
|
||||
|
||||
if ((p = realloc(p, 0)))
|
||||
{
|
||||
/* realloc cannot be used as free() */
|
||||
allocator = _realloc;
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
static void * _realloc(void * ptr, size_t n)
|
||||
{
|
||||
/*
|
||||
* free'ing realloc()
|
||||
*/
|
||||
if (n)
|
||||
return realloc(ptr, n);
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _relate(hblock_t * b, hblock_t * p)
|
||||
{
|
||||
hlist_item_t * i;
|
||||
|
||||
if (!b || !p)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* since there is no 'parent' pointer, which would've allowed
|
||||
* O(log(n)) upward traversal, the check must use O(n) downward
|
||||
* iteration of the entire hierarchy; and this can be VERY SLOW
|
||||
*/
|
||||
hlist_for_each(i, &p->children)
|
||||
{
|
||||
hblock_t * q = structof(i, hblock_t, siblings);
|
||||
if (q == b || _relate(b, q))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _free_children(hblock_t * p)
|
||||
{
|
||||
hlist_item_t * i, * tmp;
|
||||
|
||||
#ifndef NDEBUG
|
||||
/*
|
||||
* this catches loops in hierarchy with almost zero
|
||||
* overhead (compared to _relate() running time)
|
||||
*/
|
||||
assert(p && p->magic == HH_MAGIC);
|
||||
p->magic = 0;
|
||||
#endif
|
||||
hlist_for_each_safe(i, tmp, &p->children)
|
||||
{
|
||||
hblock_t * q = structof(i, hblock_t, siblings);
|
||||
_free_children(q);
|
||||
allocator(q, 0);
|
||||
}
|
||||
}
|
||||
|
136
nestegg/halloc/src/hlist.h
Normal file
136
nestegg/halloc/src/hlist.h
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
|
||||
*
|
||||
* Hierarchical memory allocator, 1.2.1
|
||||
* http://swapped.cc/halloc
|
||||
*/
|
||||
|
||||
/*
|
||||
* The program is distributed under terms of BSD license.
|
||||
* You can obtain the copy of the license by visiting:
|
||||
*
|
||||
* http://www.opensource.org/licenses/bsd-license.php
|
||||
*/
|
||||
|
||||
#ifndef _LIBP_HLIST_H_
|
||||
#define _LIBP_HLIST_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include "macros.h" /* static_inline */
|
||||
|
||||
/*
|
||||
* weak double-linked list w/ tail sentinel
|
||||
*/
|
||||
typedef struct hlist_head hlist_head_t;
|
||||
typedef struct hlist_item hlist_item_t;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
struct hlist_head
|
||||
{
|
||||
hlist_item_t * next;
|
||||
};
|
||||
|
||||
struct hlist_item
|
||||
{
|
||||
hlist_item_t * next;
|
||||
hlist_item_t ** prev;
|
||||
};
|
||||
|
||||
/*
|
||||
* shared tail sentinel
|
||||
*/
|
||||
struct hlist_item hlist_null;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
#define __hlist_init(h) { &hlist_null }
|
||||
#define __hlist_init_item(i) { &hlist_null, &(i).next }
|
||||
|
||||
static_inline void hlist_init(hlist_head_t * h);
|
||||
static_inline void hlist_init_item(hlist_item_t * i);
|
||||
|
||||
/* static_inline void hlist_purge(hlist_head_t * h); */
|
||||
|
||||
/* static_inline bool_t hlist_empty(const hlist_head_t * h); */
|
||||
|
||||
/* static_inline hlist_item_t * hlist_head(const hlist_head_t * h); */
|
||||
|
||||
/* static_inline hlist_item_t * hlist_next(const hlist_item_t * i); */
|
||||
/* static_inline hlist_item_t * hlist_prev(const hlist_item_t * i,
|
||||
const hlist_head_t * h); */
|
||||
|
||||
static_inline void hlist_add(hlist_head_t * h, hlist_item_t * i);
|
||||
|
||||
/* static_inline void hlist_add_prev(hlist_item_t * l, hlist_item_t * i); */
|
||||
/* static_inline void hlist_add_next(hlist_item_t * l, hlist_item_t * i); */
|
||||
|
||||
static_inline void hlist_del(hlist_item_t * i);
|
||||
|
||||
static_inline void hlist_relink(hlist_item_t * i);
|
||||
static_inline void hlist_relink_head(hlist_head_t * h);
|
||||
|
||||
#define hlist_for_each(i, h) \
|
||||
for (i = (h)->next; i != &hlist_null; i = i->next)
|
||||
|
||||
#define hlist_for_each_safe(i, tmp, h) \
|
||||
for (i = (h)->next, tmp = i->next; \
|
||||
i!= &hlist_null; \
|
||||
i = tmp, tmp = i->next)
|
||||
|
||||
/*
|
||||
* static
|
||||
*/
|
||||
static_inline void hlist_init(hlist_head_t * h)
|
||||
{
|
||||
assert(h);
|
||||
h->next = &hlist_null;
|
||||
}
|
||||
|
||||
static_inline void hlist_init_item(hlist_item_t * i)
|
||||
{
|
||||
assert(i);
|
||||
i->prev = &i->next;
|
||||
i->next = &hlist_null;
|
||||
}
|
||||
|
||||
static_inline void hlist_add(hlist_head_t * h, hlist_item_t * i)
|
||||
{
|
||||
hlist_item_t * next;
|
||||
assert(h && i);
|
||||
|
||||
next = i->next = h->next;
|
||||
next->prev = &i->next;
|
||||
h->next = i;
|
||||
i->prev = &h->next;
|
||||
}
|
||||
|
||||
static_inline void hlist_del(hlist_item_t * i)
|
||||
{
|
||||
hlist_item_t * next;
|
||||
assert(i);
|
||||
|
||||
next = i->next;
|
||||
next->prev = i->prev;
|
||||
*i->prev = next;
|
||||
|
||||
hlist_init_item(i);
|
||||
}
|
||||
|
||||
static_inline void hlist_relink(hlist_item_t * i)
|
||||
{
|
||||
assert(i);
|
||||
*i->prev = i;
|
||||
i->next->prev = &i->next;
|
||||
}
|
||||
|
||||
static_inline void hlist_relink_head(hlist_head_t * h)
|
||||
{
|
||||
assert(h);
|
||||
h->next->prev = &h->next;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
36
nestegg/halloc/src/macros.h
Normal file
36
nestegg/halloc/src/macros.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
|
||||
*
|
||||
* Hierarchical memory allocator, 1.2.1
|
||||
* http://swapped.cc/halloc
|
||||
*/
|
||||
|
||||
/*
|
||||
* The program is distributed under terms of BSD license.
|
||||
* You can obtain the copy of the license by visiting:
|
||||
*
|
||||
* http://www.opensource.org/licenses/bsd-license.php
|
||||
*/
|
||||
|
||||
#ifndef _LIBP_MACROS_H_
|
||||
#define _LIBP_MACROS_H_
|
||||
|
||||
#include <stddef.h> /* offsetof */
|
||||
|
||||
/*
|
||||
restore pointer to the structure by a pointer to its field
|
||||
*/
|
||||
#define structof(p,t,f) ((t*)(- offsetof(t,f) + (char*)(p)))
|
||||
|
||||
/*
|
||||
* redefine for the target compiler
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#define static_inline static __inline
|
||||
#else
|
||||
#define static_inline static __inline__
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
292
nestegg/include/nestegg/nestegg.h
Normal file
292
nestegg/include/nestegg/nestegg.h
Normal file
@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright © 2010 Mozilla Foundation
|
||||
*
|
||||
* This program is made available under an ISC-style license. See the
|
||||
* accompanying file LICENSE for details.
|
||||
*/
|
||||
#ifndef NESTEGG_671cac2a_365d_ed69_d7a3_4491d3538d79
|
||||
#define NESTEGG_671cac2a_365d_ed69_d7a3_4491d3538d79
|
||||
|
||||
#include "vpx/vpx_integer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @mainpage
|
||||
|
||||
@section intro Introduction
|
||||
|
||||
This is the documentation fot the <tt>libnestegg</tt> C API.
|
||||
<tt>libnestegg</tt> is a demultiplexing library for <a
|
||||
href="http://www.matroska.org/">Matroska</a> and <a
|
||||
href="http://www.webmproject.org/">WebMedia</a> media files.
|
||||
|
||||
@section example Example code
|
||||
|
||||
@code
|
||||
nestegg * demux_ctx;
|
||||
nestegg_init(&demux_ctx, io, NULL);
|
||||
|
||||
nestegg_packet * pkt;
|
||||
while ((r = nestegg_read_packet(demux_ctx, &pkt)) > 0) {
|
||||
unsigned int track;
|
||||
|
||||
nestegg_packet_track(pkt, &track);
|
||||
|
||||
// This example decodes the first track only.
|
||||
if (track == 0) {
|
||||
unsigned int chunk, chunks;
|
||||
|
||||
nestegg_packet_count(pkt, &chunks);
|
||||
|
||||
// Decode each chunk of data.
|
||||
for (chunk = 0; chunk < chunks; ++chunk) {
|
||||
unsigned char * data;
|
||||
size_t data_size;
|
||||
|
||||
nestegg_packet_data(pkt, chunk, &data, &data_size);
|
||||
|
||||
example_codec_decode(codec_ctx, data, data_size);
|
||||
}
|
||||
}
|
||||
|
||||
nestegg_free_packet(pkt);
|
||||
}
|
||||
|
||||
nestegg_destroy(demux_ctx);
|
||||
@endcode
|
||||
*/
|
||||
|
||||
|
||||
/** @file
|
||||
The <tt>libnestegg</tt> C API. */
|
||||
|
||||
#define NESTEGG_TRACK_VIDEO 0 /**< Track is of type video. */
|
||||
#define NESTEGG_TRACK_AUDIO 1 /**< Track is of type audio. */
|
||||
|
||||
#define NESTEGG_CODEC_VP8 0 /**< Track uses Google On2 VP8 codec. */
|
||||
#define NESTEGG_CODEC_VORBIS 1 /**< Track uses Xiph Vorbis codec. */
|
||||
|
||||
#define NESTEGG_SEEK_SET 0 /**< Seek offset relative to beginning of stream. */
|
||||
#define NESTEGG_SEEK_CUR 1 /**< Seek offset relative to current position in stream. */
|
||||
#define NESTEGG_SEEK_END 2 /**< Seek offset relative to end of stream. */
|
||||
|
||||
#define NESTEGG_LOG_DEBUG 1 /**< Debug level log message. */
|
||||
#define NESTEGG_LOG_INFO 10 /**< Informational level log message. */
|
||||
#define NESTEGG_LOG_WARNING 100 /**< Warning level log message. */
|
||||
#define NESTEGG_LOG_ERROR 1000 /**< Error level log message. */
|
||||
#define NESTEGG_LOG_CRITICAL 10000 /**< Critical level log message. */
|
||||
|
||||
typedef struct nestegg nestegg; /**< Opaque handle referencing the stream state. */
|
||||
typedef struct nestegg_packet nestegg_packet; /**< Opaque handle referencing a packet of data. */
|
||||
|
||||
/** User supplied IO context. */
|
||||
typedef struct {
|
||||
/** User supplied read callback.
|
||||
@param buffer Buffer to read data into.
|
||||
@param length Length of supplied buffer in bytes.
|
||||
@param userdata The #userdata supplied by the user.
|
||||
@retval 1 Read succeeded.
|
||||
@retval 0 End of stream.
|
||||
@retval -1 Error. */
|
||||
int (* read)(void * buffer, size_t length, void * userdata);
|
||||
|
||||
/** User supplied seek callback.
|
||||
@param offset Offset within the stream to seek to.
|
||||
@param whence Seek direction. One of #NESTEGG_SEEK_SET,
|
||||
#NESTEGG_SEEK_CUR, or #NESTEGG_SEEK_END.
|
||||
@param userdata The #userdata supplied by the user.
|
||||
@retval 0 Seek succeeded.
|
||||
@retval -1 Error. */
|
||||
int (* seek)(int64_t offset, int whence, void * userdata);
|
||||
|
||||
/** User supplied tell callback.
|
||||
@param userdata The #userdata supplied by the user.
|
||||
@returns Current position within the stream.
|
||||
@retval -1 Error. */
|
||||
int64_t (* tell)(void * userdata);
|
||||
|
||||
/** User supplied pointer to be passed to the IO callbacks. */
|
||||
void * userdata;
|
||||
} nestegg_io;
|
||||
|
||||
/** Parameters specific to a video track. */
|
||||
typedef struct {
|
||||
unsigned int width; /**< Width of the video frame in pixels. */
|
||||
unsigned int height; /**< Height of the video frame in pixels. */
|
||||
unsigned int display_width; /**< Display width of the video frame in pixels. */
|
||||
unsigned int display_height; /**< Display height of the video frame in pixels. */
|
||||
unsigned int crop_bottom; /**< Pixels to crop from the bottom of the frame. */
|
||||
unsigned int crop_top; /**< Pixels to crop from the top of the frame. */
|
||||
unsigned int crop_left; /**< Pixels to crop from the left of the frame. */
|
||||
unsigned int crop_right; /**< Pixels to crop from the right of the frame. */
|
||||
} nestegg_video_params;
|
||||
|
||||
/** Parameters specific to an audio track. */
|
||||
typedef struct {
|
||||
double rate; /**< Sampling rate in Hz. */
|
||||
unsigned int channels; /**< Number of audio channels. */
|
||||
unsigned int depth; /**< Bits per sample. */
|
||||
} nestegg_audio_params;
|
||||
|
||||
/** Logging callback function pointer. */
|
||||
typedef void (* nestegg_log)(nestegg * context, unsigned int severity, char const * format, ...);
|
||||
|
||||
/** Initialize a nestegg context. During initialization the parser will
|
||||
read forward in the stream processing all elements until the first
|
||||
block of media is reached. All track metadata has been processed at this point.
|
||||
@param context Storage for the new nestegg context. @see nestegg_destroy
|
||||
@param io User supplied IO context.
|
||||
@param callback Optional logging callback function pointer. May be NULL.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_init(nestegg ** context, nestegg_io io, nestegg_log callback);
|
||||
|
||||
/** Destroy a nestegg context and free associated memory.
|
||||
@param context #nestegg context to be freed. @see nestegg_init */
|
||||
void nestegg_destroy(nestegg * context);
|
||||
|
||||
/** Query the duration of the media stream in nanoseconds.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param duration Storage for the queried duration.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_duration(nestegg * context, uint64_t * duration);
|
||||
|
||||
/** Query the tstamp scale of the media stream in nanoseconds.
|
||||
Timecodes presented by nestegg have been scaled by this value
|
||||
before presentation to the caller.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param scale Storage for the queried scale factor.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_tstamp_scale(nestegg * context, uint64_t * scale);
|
||||
|
||||
/** Query the number of tracks in the media stream.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param tracks Storage for the queried track count.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_count(nestegg * context, unsigned int * tracks);
|
||||
|
||||
/** Seek @a track to @a tstamp. Stream seek will terminate at the earliest
|
||||
key point in the stream at or before @a tstamp. Other tracks in the
|
||||
stream will output packets with unspecified but nearby timestamps.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@param tstamp Absolute timestamp in nanoseconds.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_seek(nestegg * context, unsigned int track, uint64_t tstamp);
|
||||
|
||||
/** Query the type specified by @a track.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@retval #NESTEGG_TRACK_VIDEO Track type is video.
|
||||
@retval #NESTEGG_TRACK_AUDIO Track type is audio.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_type(nestegg * context, unsigned int track);
|
||||
|
||||
/** Query the codec ID specified by @a track.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@retval #NESTEGG_CODEC_VP8 Track codec is VP8.
|
||||
@retval #NESTEGG_CODEC_VORBIS Track codec is Vorbis.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_codec_id(nestegg * context, unsigned int track);
|
||||
|
||||
/** Query the number of codec initialization chunks for @a track. Each
|
||||
chunk of data should be passed to the codec initialization functions in
|
||||
the order returned.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@param count Storage for the queried chunk count.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_codec_data_count(nestegg * context, unsigned int track,
|
||||
unsigned int * count);
|
||||
|
||||
/** Get a pointer to chunk number @a item of codec initialization data for
|
||||
@a track.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@param item Zero based chunk item number.
|
||||
@param data Storage for the queried data pointer.
|
||||
The data is owned by the #nestegg context.
|
||||
@param length Storage for the queried data size.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_codec_data(nestegg * context, unsigned int track, unsigned int item,
|
||||
unsigned char ** data, size_t * length);
|
||||
|
||||
/** Query the video parameters specified by @a track.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@param params Storage for the queried video parameters.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_video_params(nestegg * context, unsigned int track,
|
||||
nestegg_video_params * params);
|
||||
|
||||
/** Query the audio parameters specified by @a track.
|
||||
@param context Stream context initialized by #nestegg_init.
|
||||
@param track Zero based track number.
|
||||
@param params Storage for the queried audio parameters.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_track_audio_params(nestegg * context, unsigned int track,
|
||||
nestegg_audio_params * params);
|
||||
|
||||
/** Read a packet of media data. A packet consists of one or more chunks of
|
||||
data associated with a single track. nestegg_read_packet should be
|
||||
called in a loop while the return value is 1 to drive the stream parser
|
||||
forward. @see nestegg_free_packet
|
||||
@param context Context returned by #nestegg_init.
|
||||
@param packet Storage for the returned nestegg_packet.
|
||||
@retval 1 Additional packets may be read in subsequent calls.
|
||||
@retval 0 End of stream.
|
||||
@retval -1 Error. */
|
||||
int nestegg_read_packet(nestegg * context, nestegg_packet ** packet);
|
||||
|
||||
/** Destroy a nestegg_packet and free associated memory.
|
||||
@param packet #nestegg_packet to be freed. @see nestegg_read_packet */
|
||||
void nestegg_free_packet(nestegg_packet * packet);
|
||||
|
||||
/** Query the track number of @a packet.
|
||||
@param packet Packet initialized by #nestegg_read_packet.
|
||||
@param track Storage for the queried zero based track index.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_packet_track(nestegg_packet * packet, unsigned int * track);
|
||||
|
||||
/** Query the time stamp in nanoseconds of @a packet.
|
||||
@param packet Packet initialized by #nestegg_read_packet.
|
||||
@param tstamp Storage for the queried timestamp in nanoseconds.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_packet_tstamp(nestegg_packet * packet, uint64_t * tstamp);
|
||||
|
||||
/** Query the number of data chunks contained in @a packet.
|
||||
@param packet Packet initialized by #nestegg_read_packet.
|
||||
@param count Storage for the queried timestamp in nanoseconds.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_packet_count(nestegg_packet * packet, unsigned int * count);
|
||||
|
||||
/** Get a pointer to chunk number @a item of packet data.
|
||||
@param packet Packet initialized by #nestegg_read_packet.
|
||||
@param item Zero based chunk item number.
|
||||
@param data Storage for the queried data pointer.
|
||||
The data is owned by the #nestegg_packet packet.
|
||||
@param length Storage for the queried data size.
|
||||
@retval 0 Success.
|
||||
@retval -1 Error. */
|
||||
int nestegg_packet_data(nestegg_packet * packet, unsigned int item,
|
||||
unsigned char ** data, size_t * length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NESTEGG_671cac2a_365d_ed69_d7a3_4491d3538d79 */
|
43
nestegg/m4/as-ac-expand.m4
Normal file
43
nestegg/m4/as-ac-expand.m4
Normal file
@ -0,0 +1,43 @@
|
||||
dnl as-ac-expand.m4 0.2.0
|
||||
dnl autostars m4 macro for expanding directories using configure's prefix
|
||||
dnl thomas@apestaart.org
|
||||
|
||||
dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR)
|
||||
dnl example
|
||||
dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir)
|
||||
dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local
|
||||
|
||||
AC_DEFUN([AS_AC_EXPAND],
|
||||
[
|
||||
EXP_VAR=[$1]
|
||||
FROM_VAR=[$2]
|
||||
|
||||
dnl first expand prefix and exec_prefix if necessary
|
||||
prefix_save=$prefix
|
||||
exec_prefix_save=$exec_prefix
|
||||
|
||||
dnl if no prefix given, then use /usr/local, the default prefix
|
||||
if test "x$prefix" = "xNONE"; then
|
||||
prefix="$ac_default_prefix"
|
||||
fi
|
||||
dnl if no exec_prefix given, then use prefix
|
||||
if test "x$exec_prefix" = "xNONE"; then
|
||||
exec_prefix=$prefix
|
||||
fi
|
||||
|
||||
full_var="$FROM_VAR"
|
||||
dnl loop until it doesn't change anymore
|
||||
while true; do
|
||||
new_full_var="`eval echo $full_var`"
|
||||
if test "x$new_full_var" = "x$full_var"; then break; fi
|
||||
full_var=$new_full_var
|
||||
done
|
||||
|
||||
dnl clean up
|
||||
full_var=$new_full_var
|
||||
AC_SUBST([$1], "$full_var")
|
||||
|
||||
dnl restore prefix and exec_prefix
|
||||
prefix=$prefix_save
|
||||
exec_prefix=$exec_prefix_save
|
||||
])
|
695
nestegg/m4/ax_create_stdint_h.m4
Normal file
695
nestegg/m4/ax_create_stdint_h.m4
Normal file
@ -0,0 +1,695 @@
|
||||
dnl @synopsis AX_CREATE_STDINT_H [( HEADER-TO-GENERATE [, HEDERS-TO-CHECK])]
|
||||
dnl
|
||||
dnl the "ISO C9X: 7.18 Integer types <stdint.h>" section requires the
|
||||
dnl existence of an include file <stdint.h> that defines a set of
|
||||
dnl typedefs, especially uint8_t,int32_t,uintptr_t. Many older
|
||||
dnl installations will not provide this file, but some will have the
|
||||
dnl very same definitions in <inttypes.h>. In other enviroments we can
|
||||
dnl use the inet-types in <sys/types.h> which would define the typedefs
|
||||
dnl int8_t and u_int8_t respectivly.
|
||||
dnl
|
||||
dnl This macros will create a local "_stdint.h" or the headerfile given
|
||||
dnl as an argument. In many cases that file will just "#include
|
||||
dnl <stdint.h>" or "#include <inttypes.h>", while in other environments
|
||||
dnl it will provide the set of basic 'stdint's definitions/typedefs:
|
||||
dnl
|
||||
dnl int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,intptr_t,uintptr_t
|
||||
dnl int_least32_t.. int_fast32_t.. intmax_t
|
||||
dnl
|
||||
dnl which may or may not rely on the definitions of other files, or
|
||||
dnl using the AC_CHECK_SIZEOF macro to determine the actual sizeof each
|
||||
dnl type.
|
||||
dnl
|
||||
dnl if your header files require the stdint-types you will want to
|
||||
dnl create an installable file mylib-int.h that all your other
|
||||
dnl installable header may include. So if you have a library package
|
||||
dnl named "mylib", just use
|
||||
dnl
|
||||
dnl AX_CREATE_STDINT_H(mylib-int.h)
|
||||
dnl
|
||||
dnl in configure.ac and go to install that very header file in
|
||||
dnl Makefile.am along with the other headers (mylib.h) - and the
|
||||
dnl mylib-specific headers can simply use "#include <mylib-int.h>" to
|
||||
dnl obtain the stdint-types.
|
||||
dnl
|
||||
dnl Remember, if the system already had a valid <stdint.h>, the
|
||||
dnl generated file will include it directly. No need for fuzzy
|
||||
dnl HAVE_STDINT_H things... (oops, GCC 4.2.x has deliberatly disabled
|
||||
dnl its stdint.h for non-c99 compilation and the c99-mode is not the
|
||||
dnl default. Therefore this macro will not use the compiler's stdint.h
|
||||
dnl - please complain to the GCC developers).
|
||||
dnl
|
||||
dnl @category C
|
||||
dnl @author Guido U. Draheim <guidod@gmx.de>
|
||||
dnl @version 2006-10-13
|
||||
dnl @license GPLWithACException
|
||||
|
||||
AC_DEFUN([AX_CHECK_DATA_MODEL],[
|
||||
AC_CHECK_SIZEOF(char)
|
||||
AC_CHECK_SIZEOF(short)
|
||||
AC_CHECK_SIZEOF(int)
|
||||
AC_CHECK_SIZEOF(long)
|
||||
AC_CHECK_SIZEOF(void*)
|
||||
ac_cv_char_data_model=""
|
||||
ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char"
|
||||
ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short"
|
||||
ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int"
|
||||
ac_cv_long_data_model=""
|
||||
ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int"
|
||||
ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long"
|
||||
ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp"
|
||||
AC_MSG_CHECKING([data model])
|
||||
case "$ac_cv_char_data_model/$ac_cv_long_data_model" in
|
||||
122/242) ac_cv_data_model="IP16" ; n="standard 16bit machine" ;;
|
||||
122/244) ac_cv_data_model="LP32" ; n="standard 32bit machine" ;;
|
||||
122/*) ac_cv_data_model="i16" ; n="unusual int16 model" ;;
|
||||
124/444) ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;;
|
||||
124/488) ac_cv_data_model="LP64" ; n="standard 64bit unixish" ;;
|
||||
124/448) ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;;
|
||||
124/*) ac_cv_data_model="i32" ; n="unusual int32 model" ;;
|
||||
128/888) ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;;
|
||||
128/*) ac_cv_data_model="i64" ; n="unusual int64 model" ;;
|
||||
222/*2) ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;;
|
||||
333/*3) ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;;
|
||||
444/*4) ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;;
|
||||
666/*6) ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;;
|
||||
888/*8) ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;;
|
||||
222/*|333/*|444/*|666/*|888/*) :
|
||||
ac_cv_data_model="iDSP" ; n="unusual dsptype" ;;
|
||||
*) ac_cv_data_model="none" ; n="very unusual model" ;;
|
||||
esac
|
||||
AC_MSG_RESULT([$ac_cv_data_model ($ac_cv_long_data_model, $n)])
|
||||
])
|
||||
|
||||
dnl AX_CHECK_HEADER_STDINT_X([HEADERLIST][,ACTION-IF])
|
||||
AC_DEFUN([AX_CHECK_HEADER_STDINT_X],[
|
||||
AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[
|
||||
ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h)
|
||||
AC_MSG_RESULT([(..)])
|
||||
for i in m4_ifval([$1],[$1],[stdint.h inttypes.h sys/inttypes.h sys/types.h])
|
||||
do
|
||||
unset ac_cv_type_uintptr_t
|
||||
unset ac_cv_type_uint64_t
|
||||
AC_CHECK_TYPE(uintptr_t,[ac_cv_header_stdint_x=$i],continue,[#include <$i>])
|
||||
AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
|
||||
m4_ifvaln([$1],[$1]) break
|
||||
done
|
||||
AC_MSG_CHECKING([for stdint uintptr_t])
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([AX_CHECK_HEADER_STDINT_O],[
|
||||
AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[
|
||||
ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h)
|
||||
AC_MSG_RESULT([(..)])
|
||||
for i in m4_ifval([$1],[$1],[inttypes.h sys/inttypes.h sys/types.h stdint.h])
|
||||
do
|
||||
unset ac_cv_type_uint32_t
|
||||
unset ac_cv_type_uint64_t
|
||||
AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],continue,[#include <$i>])
|
||||
AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
|
||||
m4_ifvaln([$1],[$1]) break
|
||||
break;
|
||||
done
|
||||
AC_MSG_CHECKING([for stdint uint32_t])
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([AX_CHECK_HEADER_STDINT_U],[
|
||||
AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[
|
||||
ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h)
|
||||
AC_MSG_RESULT([(..)])
|
||||
for i in m4_ifval([$1],[$1],[sys/types.h inttypes.h sys/inttypes.h]) ; do
|
||||
unset ac_cv_type_u_int32_t
|
||||
unset ac_cv_type_u_int64_t
|
||||
AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],continue,[#include <$i>])
|
||||
AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>])
|
||||
m4_ifvaln([$1],[$1]) break
|
||||
break;
|
||||
done
|
||||
AC_MSG_CHECKING([for stdint u_int32_t])
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([AX_CREATE_STDINT_H],
|
||||
[# ------ AX CREATE STDINT H -------------------------------------
|
||||
AC_MSG_CHECKING([for stdint types])
|
||||
ac_stdint_h=`echo ifelse($1, , _stdint.h, $1)`
|
||||
# try to shortcircuit - if the default include path of the compiler
|
||||
# can find a "stdint.h" header then we assume that all compilers can.
|
||||
AC_CACHE_VAL([ac_cv_header_stdint_t],[
|
||||
old_CXXFLAGS="$CXXFLAGS" ; CXXFLAGS=""
|
||||
old_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS=""
|
||||
old_CFLAGS="$CFLAGS" ; CFLAGS=""
|
||||
AC_TRY_COMPILE([#include <stdint.h>],[int_least32_t v = 0;],
|
||||
[ac_cv_stdint_result="(assuming C99 compatible system)"
|
||||
ac_cv_header_stdint_t="stdint.h"; ],
|
||||
[ac_cv_header_stdint_t=""])
|
||||
if test "$GCC" = "yes" && test ".$ac_cv_header_stdint_t" = "."; then
|
||||
CFLAGS="-std=c99"
|
||||
AC_TRY_COMPILE([#include <stdint.h>],[int_least32_t v = 0;],
|
||||
[AC_MSG_WARN(your GCC compiler has a defunct stdint.h for its default-mode)])
|
||||
fi
|
||||
CXXFLAGS="$old_CXXFLAGS"
|
||||
CPPFLAGS="$old_CPPFLAGS"
|
||||
CFLAGS="$old_CFLAGS" ])
|
||||
|
||||
v="... $ac_cv_header_stdint_h"
|
||||
if test "$ac_stdint_h" = "stdint.h" ; then
|
||||
AC_MSG_RESULT([(are you sure you want them in ./stdint.h?)])
|
||||
elif test "$ac_stdint_h" = "inttypes.h" ; then
|
||||
AC_MSG_RESULT([(are you sure you want them in ./inttypes.h?)])
|
||||
elif test "_$ac_cv_header_stdint_t" = "_" ; then
|
||||
AC_MSG_RESULT([(putting them into $ac_stdint_h)$v])
|
||||
else
|
||||
ac_cv_header_stdint="$ac_cv_header_stdint_t"
|
||||
AC_MSG_RESULT([$ac_cv_header_stdint (shortcircuit)])
|
||||
fi
|
||||
|
||||
if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit..
|
||||
|
||||
dnl .....intro message done, now do a few system checks.....
|
||||
dnl btw, all old CHECK_TYPE macros do automatically "DEFINE" a type,
|
||||
dnl therefore we use the autoconf implementation detail CHECK_TYPE_NEW
|
||||
dnl instead that is triggered with 3 or more arguments (see types.m4)
|
||||
|
||||
inttype_headers=`echo $2 | sed -e 's/,/ /g'`
|
||||
|
||||
ac_cv_stdint_result="(no helpful system typedefs seen)"
|
||||
AX_CHECK_HEADER_STDINT_X(dnl
|
||||
stdint.h inttypes.h sys/inttypes.h $inttype_headers,
|
||||
ac_cv_stdint_result="(seen uintptr_t$and64 in $i)")
|
||||
|
||||
if test "_$ac_cv_header_stdint_x" = "_" ; then
|
||||
AX_CHECK_HEADER_STDINT_O(dnl,
|
||||
inttypes.h sys/inttypes.h stdint.h $inttype_headers,
|
||||
ac_cv_stdint_result="(seen uint32_t$and64 in $i)")
|
||||
fi
|
||||
|
||||
if test "_$ac_cv_header_stdint_x" = "_" ; then
|
||||
if test "_$ac_cv_header_stdint_o" = "_" ; then
|
||||
AX_CHECK_HEADER_STDINT_U(dnl,
|
||||
sys/types.h inttypes.h sys/inttypes.h $inttype_headers,
|
||||
ac_cv_stdint_result="(seen u_int32_t$and64 in $i)")
|
||||
fi fi
|
||||
|
||||
dnl if there was no good C99 header file, do some typedef checks...
|
||||
if test "_$ac_cv_header_stdint_x" = "_" ; then
|
||||
AC_MSG_CHECKING([for stdint datatype model])
|
||||
AC_MSG_RESULT([(..)])
|
||||
AX_CHECK_DATA_MODEL
|
||||
fi
|
||||
|
||||
if test "_$ac_cv_header_stdint_x" != "_" ; then
|
||||
ac_cv_header_stdint="$ac_cv_header_stdint_x"
|
||||
elif test "_$ac_cv_header_stdint_o" != "_" ; then
|
||||
ac_cv_header_stdint="$ac_cv_header_stdint_o"
|
||||
elif test "_$ac_cv_header_stdint_u" != "_" ; then
|
||||
ac_cv_header_stdint="$ac_cv_header_stdint_u"
|
||||
else
|
||||
ac_cv_header_stdint="stddef.h"
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for extra inttypes in chosen header])
|
||||
AC_MSG_RESULT([($ac_cv_header_stdint)])
|
||||
dnl see if int_least and int_fast types are present in _this_ header.
|
||||
unset ac_cv_type_int_least32_t
|
||||
unset ac_cv_type_int_fast32_t
|
||||
AC_CHECK_TYPE(int_least32_t,,,[#include <$ac_cv_header_stdint>])
|
||||
AC_CHECK_TYPE(int_fast32_t,,,[#include<$ac_cv_header_stdint>])
|
||||
AC_CHECK_TYPE(intmax_t,,,[#include <$ac_cv_header_stdint>])
|
||||
|
||||
fi # shortcircut to system "stdint.h"
|
||||
# ------------------ PREPARE VARIABLES ------------------------------
|
||||
if test "$GCC" = "yes" ; then
|
||||
ac_cv_stdint_message="using gnu compiler "`$CC --version | head -1`
|
||||
else
|
||||
ac_cv_stdint_message="using $CC"
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([make use of $ac_cv_header_stdint in $ac_stdint_h dnl
|
||||
$ac_cv_stdint_result])
|
||||
|
||||
dnl -----------------------------------------------------------------
|
||||
# ----------------- DONE inttypes.h checks START header -------------
|
||||
AC_CONFIG_COMMANDS([$ac_stdint_h],[
|
||||
AC_MSG_NOTICE(creating $ac_stdint_h : $_ac_stdint_h)
|
||||
ac_stdint=$tmp/_stdint.h
|
||||
|
||||
echo "#ifndef" $_ac_stdint_h >$ac_stdint
|
||||
echo "#define" $_ac_stdint_h "1" >>$ac_stdint
|
||||
echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint
|
||||
echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint
|
||||
echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint
|
||||
if test "_$ac_cv_header_stdint_t" != "_" ; then
|
||||
echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint
|
||||
echo "#include <stdint.h>" >>$ac_stdint
|
||||
echo "#endif" >>$ac_stdint
|
||||
echo "#endif" >>$ac_stdint
|
||||
else
|
||||
|
||||
cat >>$ac_stdint <<STDINT_EOF
|
||||
|
||||
/* ................... shortcircuit part ........................... */
|
||||
|
||||
#if defined HAVE_STDINT_H || defined _STDINT_HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#include <stddef.h>
|
||||
|
||||
/* .................... configured part ............................ */
|
||||
|
||||
STDINT_EOF
|
||||
|
||||
echo "/* whether we have a C99 compatible stdint header file */" >>$ac_stdint
|
||||
if test "_$ac_cv_header_stdint_x" != "_" ; then
|
||||
ac_header="$ac_cv_header_stdint_x"
|
||||
echo "#define _STDINT_HEADER_INTPTR" '"'"$ac_header"'"' >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HEADER_INTPTR */" >>$ac_stdint
|
||||
fi
|
||||
|
||||
echo "/* whether we have a C96 compatible inttypes header file */" >>$ac_stdint
|
||||
if test "_$ac_cv_header_stdint_o" != "_" ; then
|
||||
ac_header="$ac_cv_header_stdint_o"
|
||||
echo "#define _STDINT_HEADER_UINT32" '"'"$ac_header"'"' >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HEADER_UINT32 */" >>$ac_stdint
|
||||
fi
|
||||
|
||||
echo "/* whether we have a BSD compatible inet types header */" >>$ac_stdint
|
||||
if test "_$ac_cv_header_stdint_u" != "_" ; then
|
||||
ac_header="$ac_cv_header_stdint_u"
|
||||
echo "#define _STDINT_HEADER_U_INT32" '"'"$ac_header"'"' >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HEADER_U_INT32 */" >>$ac_stdint
|
||||
fi
|
||||
|
||||
echo "" >>$ac_stdint
|
||||
|
||||
if test "_$ac_header" != "_" ; then if test "$ac_header" != "stddef.h" ; then
|
||||
echo "#include <$ac_header>" >>$ac_stdint
|
||||
echo "" >>$ac_stdint
|
||||
fi fi
|
||||
|
||||
echo "/* which 64bit typedef has been found */" >>$ac_stdint
|
||||
if test "$ac_cv_type_uint64_t" = "yes" ; then
|
||||
echo "#define _STDINT_HAVE_UINT64_T" "1" >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HAVE_UINT64_T */" >>$ac_stdint
|
||||
fi
|
||||
if test "$ac_cv_type_u_int64_t" = "yes" ; then
|
||||
echo "#define _STDINT_HAVE_U_INT64_T" "1" >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HAVE_U_INT64_T */" >>$ac_stdint
|
||||
fi
|
||||
echo "" >>$ac_stdint
|
||||
|
||||
echo "/* which type model has been detected */" >>$ac_stdint
|
||||
if test "_$ac_cv_char_data_model" != "_" ; then
|
||||
echo "#define _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint
|
||||
echo "#define _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint
|
||||
echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint
|
||||
fi
|
||||
echo "" >>$ac_stdint
|
||||
|
||||
echo "/* whether int_least types were detected */" >>$ac_stdint
|
||||
if test "$ac_cv_type_int_least32_t" = "yes"; then
|
||||
echo "#define _STDINT_HAVE_INT_LEAST32_T" "1" >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HAVE_INT_LEAST32_T */" >>$ac_stdint
|
||||
fi
|
||||
echo "/* whether int_fast types were detected */" >>$ac_stdint
|
||||
if test "$ac_cv_type_int_fast32_t" = "yes"; then
|
||||
echo "#define _STDINT_HAVE_INT_FAST32_T" "1" >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HAVE_INT_FAST32_T */" >>$ac_stdint
|
||||
fi
|
||||
echo "/* whether intmax_t type was detected */" >>$ac_stdint
|
||||
if test "$ac_cv_type_intmax_t" = "yes"; then
|
||||
echo "#define _STDINT_HAVE_INTMAX_T" "1" >>$ac_stdint
|
||||
else
|
||||
echo "/* #undef _STDINT_HAVE_INTMAX_T */" >>$ac_stdint
|
||||
fi
|
||||
echo "" >>$ac_stdint
|
||||
|
||||
cat >>$ac_stdint <<STDINT_EOF
|
||||
/* .................... detections part ............................ */
|
||||
|
||||
/* whether we need to define bitspecific types from compiler base types */
|
||||
#ifndef _STDINT_HEADER_INTPTR
|
||||
#ifndef _STDINT_HEADER_UINT32
|
||||
#ifndef _STDINT_HEADER_U_INT32
|
||||
#define _STDINT_NEED_INT_MODEL_T
|
||||
#else
|
||||
#define _STDINT_HAVE_U_INT_TYPES
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _STDINT_HAVE_U_INT_TYPES
|
||||
#undef _STDINT_NEED_INT_MODEL_T
|
||||
#endif
|
||||
|
||||
#ifdef _STDINT_CHAR_MODEL
|
||||
#if _STDINT_CHAR_MODEL+0 == 122 || _STDINT_CHAR_MODEL+0 == 124
|
||||
#ifndef _STDINT_BYTE_MODEL
|
||||
#define _STDINT_BYTE_MODEL 12
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _STDINT_HAVE_INT_LEAST32_T
|
||||
#define _STDINT_NEED_INT_LEAST_T
|
||||
#endif
|
||||
|
||||
#ifndef _STDINT_HAVE_INT_FAST32_T
|
||||
#define _STDINT_NEED_INT_FAST_T
|
||||
#endif
|
||||
|
||||
#ifndef _STDINT_HEADER_INTPTR
|
||||
#define _STDINT_NEED_INTPTR_T
|
||||
#ifndef _STDINT_HAVE_INTMAX_T
|
||||
#define _STDINT_NEED_INTMAX_T
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* .................... definition part ............................ */
|
||||
|
||||
/* some system headers have good uint64_t */
|
||||
#ifndef _HAVE_UINT64_T
|
||||
#if defined _STDINT_HAVE_UINT64_T || defined HAVE_UINT64_T
|
||||
#define _HAVE_UINT64_T
|
||||
#elif defined _STDINT_HAVE_U_INT64_T || defined HAVE_U_INT64_T
|
||||
#define _HAVE_UINT64_T
|
||||
typedef u_int64_t uint64_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _HAVE_UINT64_T
|
||||
/* .. here are some common heuristics using compiler runtime specifics */
|
||||
#if defined __STDC_VERSION__ && defined __STDC_VERSION__ >= 199901L
|
||||
#define _HAVE_UINT64_T
|
||||
#define _HAVE_LONGLONG_UINT64_T
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
#elif !defined __STRICT_ANSI__
|
||||
#if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__
|
||||
#define _HAVE_UINT64_T
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
#elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__
|
||||
/* note: all ELF-systems seem to have loff-support which needs 64-bit */
|
||||
#if !defined _NO_LONGLONG
|
||||
#define _HAVE_UINT64_T
|
||||
#define _HAVE_LONGLONG_UINT64_T
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
#endif
|
||||
|
||||
#elif defined __alpha || (defined __mips && defined _ABIN32)
|
||||
#if !defined _NO_LONGLONG
|
||||
typedef long int64_t;
|
||||
typedef unsigned long uint64_t;
|
||||
#endif
|
||||
/* compiler/cpu type to define int64_t */
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined _STDINT_HAVE_U_INT_TYPES
|
||||
/* int8_t int16_t int32_t defined by inet code, redeclare the u_intXX types */
|
||||
typedef u_int8_t uint8_t;
|
||||
typedef u_int16_t uint16_t;
|
||||
typedef u_int32_t uint32_t;
|
||||
|
||||
/* glibc compatibility */
|
||||
#ifndef __int8_t_defined
|
||||
#define __int8_t_defined
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _STDINT_NEED_INT_MODEL_T
|
||||
/* we must guess all the basic types. Apart from byte-adressable system, */
|
||||
/* there a few 32-bit-only dsp-systems that we guard with BYTE_MODEL 8-} */
|
||||
/* (btw, those nibble-addressable systems are way off, or so we assume) */
|
||||
|
||||
dnl /* have a look at "64bit and data size neutrality" at */
|
||||
dnl /* http://unix.org/version2/whatsnew/login_64bit.html */
|
||||
dnl /* (the shorthand "ILP" types always have a "P" part) */
|
||||
|
||||
#if defined _STDINT_BYTE_MODEL
|
||||
#if _STDINT_LONG_MODEL+0 == 242
|
||||
/* 2:4:2 = IP16 = a normal 16-bit system */
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned long uint32_t;
|
||||
#ifndef __int8_t_defined
|
||||
#define __int8_t_defined
|
||||
typedef char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef long int32_t;
|
||||
#endif
|
||||
#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL == 444
|
||||
/* 2:4:4 = LP32 = a 32-bit system derived from a 16-bit */
|
||||
/* 4:4:4 = ILP32 = a normal 32-bit system */
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#ifndef __int8_t_defined
|
||||
#define __int8_t_defined
|
||||
typedef char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef int int32_t;
|
||||
#endif
|
||||
#elif _STDINT_LONG_MODEL+0 == 484 || _STDINT_LONG_MODEL+0 == 488
|
||||
/* 4:8:4 = IP32 = a 32-bit system prepared for 64-bit */
|
||||
/* 4:8:8 = LP64 = a normal 64-bit system */
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#ifndef __int8_t_defined
|
||||
#define __int8_t_defined
|
||||
typedef char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef int int32_t;
|
||||
#endif
|
||||
/* this system has a "long" of 64bit */
|
||||
#ifndef _HAVE_UINT64_T
|
||||
#define _HAVE_UINT64_T
|
||||
typedef unsigned long uint64_t;
|
||||
typedef long int64_t;
|
||||
#endif
|
||||
#elif _STDINT_LONG_MODEL+0 == 448
|
||||
/* LLP64 a 64-bit system derived from a 32-bit system */
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#ifndef __int8_t_defined
|
||||
#define __int8_t_defined
|
||||
typedef char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef int int32_t;
|
||||
#endif
|
||||
/* assuming the system has a "long long" */
|
||||
#ifndef _HAVE_UINT64_T
|
||||
#define _HAVE_UINT64_T
|
||||
#define _HAVE_LONGLONG_UINT64_T
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef long long int64_t;
|
||||
#endif
|
||||
#else
|
||||
#define _STDINT_NO_INT32_T
|
||||
#endif
|
||||
#else
|
||||
#define _STDINT_NO_INT8_T
|
||||
#define _STDINT_NO_INT32_T
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* quote from SunOS-5.8 sys/inttypes.h:
|
||||
* Use at your own risk. As of February 1996, the committee is squarely
|
||||
* behind the fixed sized types; the "least" and "fast" types are still being
|
||||
* discussed. The probability that the "fast" types may be removed before
|
||||
* the standard is finalized is high enough that they are not currently
|
||||
* implemented.
|
||||
*/
|
||||
|
||||
#if defined _STDINT_NEED_INT_LEAST_T
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
#ifdef _HAVE_UINT64_T
|
||||
typedef int64_t int_least64_t;
|
||||
#endif
|
||||
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
#ifdef _HAVE_UINT64_T
|
||||
typedef uint64_t uint_least64_t;
|
||||
#endif
|
||||
/* least types */
|
||||
#endif
|
||||
|
||||
#if defined _STDINT_NEED_INT_FAST_T
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
#ifdef _HAVE_UINT64_T
|
||||
typedef int64_t int_fast64_t;
|
||||
#endif
|
||||
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef unsigned uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
#ifdef _HAVE_UINT64_T
|
||||
typedef uint64_t uint_fast64_t;
|
||||
#endif
|
||||
/* fast types */
|
||||
#endif
|
||||
|
||||
#ifdef _STDINT_NEED_INTMAX_T
|
||||
#ifdef _HAVE_UINT64_T
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
#else
|
||||
typedef long intmax_t;
|
||||
typedef unsigned long uintmax_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _STDINT_NEED_INTPTR_T
|
||||
#ifndef __intptr_t_defined
|
||||
#define __intptr_t_defined
|
||||
/* we encourage using "long" to store pointer values, never use "int" ! */
|
||||
#if _STDINT_LONG_MODEL+0 == 242 || _STDINT_LONG_MODEL+0 == 484
|
||||
typedef unsigned int uintptr_t;
|
||||
typedef int intptr_t;
|
||||
#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL+0 == 444
|
||||
typedef unsigned long uintptr_t;
|
||||
typedef long intptr_t;
|
||||
#elif _STDINT_LONG_MODEL+0 == 448 && defined _HAVE_UINT64_T
|
||||
typedef uint64_t uintptr_t;
|
||||
typedef int64_t intptr_t;
|
||||
#else /* matches typical system types ILP32 and LP64 - but not IP16 or LLP64 */
|
||||
typedef unsigned long uintptr_t;
|
||||
typedef long intptr_t;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* The ISO C99 standard specifies that in C++ implementations these
|
||||
should only be defined if explicitly requested. */
|
||||
#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS
|
||||
#ifndef UINT32_C
|
||||
|
||||
/* Signed. */
|
||||
# define INT8_C(c) c
|
||||
# define INT16_C(c) c
|
||||
# define INT32_C(c) c
|
||||
# ifdef _HAVE_LONGLONG_UINT64_T
|
||||
# define INT64_C(c) c ## L
|
||||
# else
|
||||
# define INT64_C(c) c ## LL
|
||||
# endif
|
||||
|
||||
/* Unsigned. */
|
||||
# define UINT8_C(c) c ## U
|
||||
# define UINT16_C(c) c ## U
|
||||
# define UINT32_C(c) c ## U
|
||||
# ifdef _HAVE_LONGLONG_UINT64_T
|
||||
# define UINT64_C(c) c ## UL
|
||||
# else
|
||||
# define UINT64_C(c) c ## ULL
|
||||
# endif
|
||||
|
||||
/* Maximal type. */
|
||||
# ifdef _HAVE_LONGLONG_UINT64_T
|
||||
# define INTMAX_C(c) c ## L
|
||||
# define UINTMAX_C(c) c ## UL
|
||||
# else
|
||||
# define INTMAX_C(c) c ## LL
|
||||
# define UINTMAX_C(c) c ## ULL
|
||||
# endif
|
||||
|
||||
/* literalnumbers */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* These limits are merily those of a two complement byte-oriented system */
|
||||
|
||||
/* Minimum of signed integral types. */
|
||||
# define INT8_MIN (-128)
|
||||
# define INT16_MIN (-32767-1)
|
||||
# define INT32_MIN (-2147483647-1)
|
||||
# define INT64_MIN (-__INT64_C(9223372036854775807)-1)
|
||||
/* Maximum of signed integral types. */
|
||||
# define INT8_MAX (127)
|
||||
# define INT16_MAX (32767)
|
||||
# define INT32_MAX (2147483647)
|
||||
# define INT64_MAX (__INT64_C(9223372036854775807))
|
||||
|
||||
/* Maximum of unsigned integral types. */
|
||||
# define UINT8_MAX (255)
|
||||
# define UINT16_MAX (65535)
|
||||
# define UINT32_MAX (4294967295U)
|
||||
# define UINT64_MAX (__UINT64_C(18446744073709551615))
|
||||
|
||||
/* Minimum of signed integral types having a minimum size. */
|
||||
# define INT_LEAST8_MIN INT8_MIN
|
||||
# define INT_LEAST16_MIN INT16_MIN
|
||||
# define INT_LEAST32_MIN INT32_MIN
|
||||
# define INT_LEAST64_MIN INT64_MIN
|
||||
/* Maximum of signed integral types having a minimum size. */
|
||||
# define INT_LEAST8_MAX INT8_MAX
|
||||
# define INT_LEAST16_MAX INT16_MAX
|
||||
# define INT_LEAST32_MAX INT32_MAX
|
||||
# define INT_LEAST64_MAX INT64_MAX
|
||||
|
||||
/* Maximum of unsigned integral types having a minimum size. */
|
||||
# define UINT_LEAST8_MAX UINT8_MAX
|
||||
# define UINT_LEAST16_MAX UINT16_MAX
|
||||
# define UINT_LEAST32_MAX UINT32_MAX
|
||||
# define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
/* shortcircuit*/
|
||||
#endif
|
||||
/* once */
|
||||
#endif
|
||||
#endif
|
||||
STDINT_EOF
|
||||
fi
|
||||
if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then
|
||||
AC_MSG_NOTICE([$ac_stdint_h is unchanged])
|
||||
else
|
||||
ac_dir=`AS_DIRNAME(["$ac_stdint_h"])`
|
||||
AS_MKDIR_P(["$ac_dir"])
|
||||
rm -f $ac_stdint_h
|
||||
mv $ac_stdint $ac_stdint_h
|
||||
fi
|
||||
],[# variables for create stdint.h replacement
|
||||
PACKAGE="$PACKAGE"
|
||||
VERSION="$VERSION"
|
||||
ac_stdint_h="$ac_stdint_h"
|
||||
_ac_stdint_h=AS_TR_CPP(_$PACKAGE-$ac_stdint_h)
|
||||
ac_cv_stdint_message="$ac_cv_stdint_message"
|
||||
ac_cv_header_stdint_t="$ac_cv_header_stdint_t"
|
||||
ac_cv_header_stdint_x="$ac_cv_header_stdint_x"
|
||||
ac_cv_header_stdint_o="$ac_cv_header_stdint_o"
|
||||
ac_cv_header_stdint_u="$ac_cv_header_stdint_u"
|
||||
ac_cv_type_uint64_t="$ac_cv_type_uint64_t"
|
||||
ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t"
|
||||
ac_cv_char_data_model="$ac_cv_char_data_model"
|
||||
ac_cv_long_data_model="$ac_cv_long_data_model"
|
||||
ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t"
|
||||
ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t"
|
||||
ac_cv_type_intmax_t="$ac_cv_type_intmax_t"
|
||||
])
|
||||
])
|
157
nestegg/m4/pkg.m4
Normal file
157
nestegg/m4/pkg.m4
Normal file
@ -0,0 +1,157 @@
|
||||
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||
#
|
||||
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
||||
# ----------------------------------
|
||||
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
||||
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||
m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
|
||||
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
|
||||
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
||||
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
|
||||
fi
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
_pkg_min_version=m4_default([$1], [0.9.0])
|
||||
AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
PKG_CONFIG=""
|
||||
fi
|
||||
|
||||
fi[]dnl
|
||||
])# PKG_PROG_PKG_CONFIG
|
||||
|
||||
# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
#
|
||||
# Check to see whether a particular set of modules exists. Similar
|
||||
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
|
||||
#
|
||||
#
|
||||
# Similar to PKG_CHECK_MODULES, make sure that the first instance of
|
||||
# this or PKG_CHECK_MODULES is called, or make sure to call
|
||||
# PKG_CHECK_EXISTS manually
|
||||
# --------------------------------------------------------------
|
||||
AC_DEFUN([PKG_CHECK_EXISTS],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
|
||||
m4_ifval([$2], [$2], [:])
|
||||
m4_ifvaln([$3], [else
|
||||
$3])dnl
|
||||
fi])
|
||||
|
||||
|
||||
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
|
||||
# ---------------------------------------------
|
||||
m4_define([_PKG_CONFIG],
|
||||
[if test -n "$PKG_CONFIG"; then
|
||||
if test -n "$$1"; then
|
||||
pkg_cv_[]$1="$$1"
|
||||
else
|
||||
PKG_CHECK_EXISTS([$3],
|
||||
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
|
||||
[pkg_failed=yes])
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi[]dnl
|
||||
])# _PKG_CONFIG
|
||||
|
||||
# _PKG_SHORT_ERRORS_SUPPORTED
|
||||
# -----------------------------
|
||||
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi[]dnl
|
||||
])# _PKG_SHORT_ERRORS_SUPPORTED
|
||||
|
||||
|
||||
# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||
# [ACTION-IF-NOT-FOUND])
|
||||
#
|
||||
#
|
||||
# Note that if there is a possibility the first call to
|
||||
# PKG_CHECK_MODULES might not happen, you should be sure to include an
|
||||
# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
|
||||
#
|
||||
#
|
||||
# --------------------------------------------------------------
|
||||
AC_DEFUN([PKG_CHECK_MODULES],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
|
||||
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
|
||||
|
||||
pkg_failed=no
|
||||
AC_MSG_CHECKING([for $1])
|
||||
|
||||
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
|
||||
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
|
||||
|
||||
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
|
||||
and $1[]_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details.])
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
_PKG_SHORT_ERRORS_SUPPORTED
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
|
||||
else
|
||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
|
||||
|
||||
ifelse([$4], , [AC_MSG_ERROR(dnl
|
||||
[Package requirements ($2) were not met:
|
||||
|
||||
$$1_PKG_ERRORS
|
||||
|
||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||
installed software in a non-standard prefix.
|
||||
|
||||
_PKG_TEXT
|
||||
])],
|
||||
[AC_MSG_RESULT([no])
|
||||
$4])
|
||||
elif test $pkg_failed = untried; then
|
||||
ifelse([$4], , [AC_MSG_FAILURE(dnl
|
||||
[The pkg-config script could not be found or is too old. Make sure it
|
||||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||
path to pkg-config.
|
||||
|
||||
_PKG_TEXT
|
||||
|
||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
|
||||
[$4])
|
||||
else
|
||||
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
|
||||
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
|
||||
AC_MSG_RESULT([yes])
|
||||
ifelse([$3], , :, [$3])
|
||||
fi[]dnl
|
||||
])# PKG_CHECK_MODULES
|
13
nestegg/nestegg-uninstalled.pc.in
Normal file
13
nestegg/nestegg-uninstalled.pc.in
Normal file
@ -0,0 +1,13 @@
|
||||
# nestegg uninstalled pkg-config file
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: nestegg
|
||||
Description: WebM/Matroska demuxer
|
||||
Version: @VERSION@
|
||||
Conflicts:
|
||||
Libs: -L${libdir} -lnestegg
|
||||
Cflags: -I${includedir}
|
13
nestegg/nestegg.pc.in
Normal file
13
nestegg/nestegg.pc.in
Normal file
@ -0,0 +1,13 @@
|
||||
# nestegg installed pkg-config file
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: nestegg
|
||||
Description: WebM/Matroska demuxer
|
||||
Version: @VERSION@
|
||||
Conflicts:
|
||||
Libs: -L${libdir} -lnestegg
|
||||
Cflags: -I${includedir}
|
1938
nestegg/src/nestegg.c
Normal file
1938
nestegg/src/nestegg.c
Normal file
File diff suppressed because it is too large
Load Diff
248
nestegg/test/test.c
Normal file
248
nestegg/test/test.c
Normal file
@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright © 2010 Mozilla Foundation
|
||||
*
|
||||
* This program is made available under an ISC-style license. See the
|
||||
* accompanying file LICENSE for details.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "nestegg/nestegg.h"
|
||||
|
||||
#undef DEBUG
|
||||
#define SEEK_TEST
|
||||
|
||||
static int
|
||||
stdio_read(void * p, size_t length, void * fp)
|
||||
{
|
||||
size_t r;
|
||||
|
||||
r = fread(p, length, 1, fp);
|
||||
if (r == 0 && feof(fp))
|
||||
return 0;
|
||||
return r == 0 ? -1 : 1;
|
||||
}
|
||||
|
||||
static int
|
||||
stdio_seek(int64_t offset, int whence, void * fp)
|
||||
{
|
||||
return fseek(fp, offset, whence);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
stdio_tell(void * fp)
|
||||
{
|
||||
return ftell(fp);
|
||||
}
|
||||
|
||||
static void
|
||||
log_callback(nestegg * ctx, unsigned int severity, char const * fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char const * sev = NULL;
|
||||
|
||||
#ifndef DEBUG
|
||||
if (severity < NESTEGG_LOG_WARNING)
|
||||
return;
|
||||
#endif
|
||||
|
||||
switch (severity) {
|
||||
case NESTEGG_LOG_DEBUG:
|
||||
sev = "debug: ";
|
||||
break;
|
||||
case NESTEGG_LOG_WARNING:
|
||||
sev = "warning: ";
|
||||
break;
|
||||
case NESTEGG_LOG_CRITICAL:
|
||||
sev = "critical:";
|
||||
break;
|
||||
default:
|
||||
sev = "unknown: ";
|
||||
}
|
||||
|
||||
fprintf(stderr, "%p %s ", (void *) ctx, sev);
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char * argv[])
|
||||
{
|
||||
FILE * fp;
|
||||
int r, type;
|
||||
nestegg * ctx;
|
||||
nestegg_audio_params aparams;
|
||||
nestegg_packet * pkt;
|
||||
nestegg_video_params vparams;
|
||||
size_t length, size;
|
||||
uint64_t duration, tstamp, pkt_tstamp;
|
||||
unsigned char * codec_data, * ptr;
|
||||
unsigned int cnt, i, j, track, tracks, pkt_cnt, pkt_track;
|
||||
unsigned int data_items = 0;
|
||||
nestegg_io io = {
|
||||
stdio_read,
|
||||
stdio_seek,
|
||||
stdio_tell,
|
||||
NULL
|
||||
};
|
||||
|
||||
if (argc != 2)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
fp = fopen(argv[1], "rb");
|
||||
if (!fp)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
io.userdata = fp;
|
||||
|
||||
ctx = NULL;
|
||||
r = nestegg_init(&ctx, io, log_callback);
|
||||
if (r != 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
nestegg_track_count(ctx, &tracks);
|
||||
nestegg_duration(ctx, &duration);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "media has %u tracks and duration %fs\n", tracks, duration / 1e9);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < tracks; ++i) {
|
||||
type = nestegg_track_type(ctx, i);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "track %u: type: %d codec: %d", i,
|
||||
type, nestegg_track_codec_id(ctx, i));
|
||||
#endif
|
||||
nestegg_track_codec_data_count(ctx, i, &data_items);
|
||||
for (j = 0; j < data_items; ++j) {
|
||||
nestegg_track_codec_data(ctx, i, j, &codec_data, &length);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, " (%p, %u)", codec_data, (unsigned int) length);
|
||||
#endif
|
||||
}
|
||||
if (type == NESTEGG_TRACK_VIDEO) {
|
||||
nestegg_track_video_params(ctx, i, &vparams);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, " video: %ux%u (d: %ux%u %ux%ux%ux%u)",
|
||||
vparams.width, vparams.height,
|
||||
vparams.display_width, vparams.display_height,
|
||||
vparams.crop_top, vparams.crop_left, vparams.crop_bottom, vparams.crop_right);
|
||||
#endif
|
||||
} else if (type == NESTEGG_TRACK_AUDIO) {
|
||||
nestegg_track_audio_params(ctx, i, &aparams);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, " audio: %.2fhz %u bit %u channels",
|
||||
aparams.rate, aparams.depth, aparams.channels);
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SEEK_TEST
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "seek to middle\n");
|
||||
#endif
|
||||
r = nestegg_track_seek(ctx, 0, duration / 2);
|
||||
if (r == 0) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "middle ");
|
||||
#endif
|
||||
r = nestegg_read_packet(ctx, &pkt);
|
||||
if (r == 1) {
|
||||
nestegg_packet_track(pkt, &track);
|
||||
nestegg_packet_count(pkt, &cnt);
|
||||
nestegg_packet_tstamp(pkt, &tstamp);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "* t %u pts %f frames %u\n", track, tstamp / 1e9, cnt);
|
||||
#endif
|
||||
nestegg_free_packet(pkt);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "middle seek failed\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "seek to ~end\n");
|
||||
#endif
|
||||
r = nestegg_track_seek(ctx, 0, duration - (duration / 10));
|
||||
if (r == 0) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "end ");
|
||||
#endif
|
||||
r = nestegg_read_packet(ctx, &pkt);
|
||||
if (r == 1) {
|
||||
nestegg_packet_track(pkt, &track);
|
||||
nestegg_packet_count(pkt, &cnt);
|
||||
nestegg_packet_tstamp(pkt, &tstamp);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "* t %u pts %f frames %u\n", track, tstamp / 1e9, cnt);
|
||||
#endif
|
||||
nestegg_free_packet(pkt);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "end seek failed\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "seek to ~start\n");
|
||||
#endif
|
||||
r = nestegg_track_seek(ctx, 0, duration / 10);
|
||||
if (r == 0) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "start ");
|
||||
#endif
|
||||
r = nestegg_read_packet(ctx, &pkt);
|
||||
if (r == 1) {
|
||||
nestegg_packet_track(pkt, &track);
|
||||
nestegg_packet_count(pkt, &cnt);
|
||||
nestegg_packet_tstamp(pkt, &tstamp);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "* t %u pts %f frames %u\n", track, tstamp / 1e9, cnt);
|
||||
#endif
|
||||
nestegg_free_packet(pkt);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "start seek failed\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
while (nestegg_read_packet(ctx, &pkt) > 0) {
|
||||
nestegg_packet_track(pkt, &pkt_track);
|
||||
nestegg_packet_count(pkt, &pkt_cnt);
|
||||
nestegg_packet_tstamp(pkt, &pkt_tstamp);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "t %u pts %f frames %u: ", pkt_track, pkt_tstamp / 1e9, pkt_cnt);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < pkt_cnt; ++i) {
|
||||
nestegg_packet_data(pkt, i, &ptr, &size);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "%u ", (unsigned int) size);
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
|
||||
nestegg_free_packet(pkt);
|
||||
}
|
||||
|
||||
nestegg_destroy(ctx);
|
||||
fclose(fp);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -22,7 +22,7 @@ else
|
||||
vpx.sln: $(wildcard *.vcproj)
|
||||
@echo " [CREATE] $@"
|
||||
$(SRC_PATH_BARE)/build/make/gen_msvs_sln.sh \
|
||||
$(if $(filter %vpx.vcproj,$^),--dep=ivfdec:vpx) \
|
||||
$(if $(filter %vpx.vcproj,$^),--dep=vpxdec:vpx) \
|
||||
$(if $(filter %vpx.vcproj,$^),--dep=xma:vpx) \
|
||||
--ver=$(CONFIG_VS_VERSION)\
|
||||
--target=$(TOOLCHAIN)\
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#if USE_POSIX_MMAP
|
||||
#include <sys/types.h>
|
||||
@ -30,10 +31,31 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "vpx_version.h"
|
||||
#include "vpx/vp8cx.h"
|
||||
#include "vpx_ports/mem_ops.h"
|
||||
#include "vpx_ports/vpx_timer.h"
|
||||
#include "y4minput.h"
|
||||
#include "libmkv/EbmlWriter.h"
|
||||
#include "libmkv/EbmlIDs.h"
|
||||
|
||||
/* Need special handling of these functions on Windows */
|
||||
#if defined(_MSC_VER)
|
||||
/* MSVS doesn't define off_t, and uses _f{seek,tell}i64 */
|
||||
typedef __int64 off_t;
|
||||
#define fseeko _fseeki64
|
||||
#define ftello _ftelli64
|
||||
#elif defined(_WIN32)
|
||||
/* MinGW defines off_t, and uses f{seek,tell}o64 */
|
||||
#define fseeko fseeko64
|
||||
#define ftello ftello64
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define LITERALU64(n) n
|
||||
#else
|
||||
#define LITERALU64(n) n##LLU
|
||||
#endif
|
||||
|
||||
static const char *exec_name;
|
||||
|
||||
@ -395,8 +417,331 @@ static void write_ivf_frame_header(FILE *outfile,
|
||||
fwrite(header, 1, 12, outfile);
|
||||
}
|
||||
|
||||
|
||||
typedef off_t EbmlLoc;
|
||||
|
||||
|
||||
struct cue_entry
|
||||
{
|
||||
unsigned int time;
|
||||
uint64_t loc;
|
||||
};
|
||||
|
||||
|
||||
struct EbmlGlobal
|
||||
{
|
||||
FILE *stream;
|
||||
uint64_t last_pts_ms;
|
||||
vpx_rational_t framerate;
|
||||
|
||||
/* These pointers are to the start of an element */
|
||||
off_t position_reference;
|
||||
off_t seek_info_pos;
|
||||
off_t segment_info_pos;
|
||||
off_t track_pos;
|
||||
off_t cue_pos;
|
||||
off_t cluster_pos;
|
||||
|
||||
/* These pointers are to the size field of the element */
|
||||
EbmlLoc startSegment;
|
||||
EbmlLoc startCluster;
|
||||
|
||||
uint32_t cluster_timecode;
|
||||
int cluster_open;
|
||||
|
||||
struct cue_entry *cue_list;
|
||||
unsigned int cues;
|
||||
|
||||
};
|
||||
|
||||
|
||||
void Ebml_Write(EbmlGlobal *glob, const void *buffer_in, unsigned long len)
|
||||
{
|
||||
fwrite(buffer_in, 1, len, glob->stream);
|
||||
}
|
||||
|
||||
|
||||
void Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in, unsigned long len)
|
||||
{
|
||||
const unsigned char *q = (const unsigned char *)buffer_in + len - 1;
|
||||
|
||||
for(; len; len--)
|
||||
Ebml_Write(glob, q--, 1);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc,
|
||||
unsigned long class_id)
|
||||
{
|
||||
//todo this is always taking 8 bytes, this may need later optimization
|
||||
//this is a key that says lenght unknown
|
||||
unsigned long long unknownLen = LITERALU64(0x01FFFFFFFFFFFFFF);
|
||||
|
||||
Ebml_WriteID(glob, class_id);
|
||||
*ebmlLoc = ftello(glob->stream);
|
||||
Ebml_Serialize(glob, &unknownLen, 8);
|
||||
}
|
||||
|
||||
static void
|
||||
Ebml_EndSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc)
|
||||
{
|
||||
off_t pos;
|
||||
uint64_t size;
|
||||
|
||||
/* Save the current stream pointer */
|
||||
pos = ftello(glob->stream);
|
||||
|
||||
/* Calculate the size of this element */
|
||||
size = pos - *ebmlLoc - 8;
|
||||
size |= LITERALU64(0x0100000000000000);
|
||||
|
||||
/* Seek back to the beginning of the element and write the new size */
|
||||
fseeko(glob->stream, *ebmlLoc, SEEK_SET);
|
||||
Ebml_Serialize(glob, &size, 8);
|
||||
|
||||
/* Reset the stream pointer */
|
||||
fseeko(glob->stream, pos, SEEK_SET);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
write_webm_seek_element(EbmlGlobal *ebml, unsigned long id, off_t pos)
|
||||
{
|
||||
uint64_t offset = pos - ebml->position_reference;
|
||||
EbmlLoc start;
|
||||
Ebml_StartSubElement(ebml, &start, Seek);
|
||||
Ebml_SerializeBinary(ebml, SeekID, id);
|
||||
Ebml_SerializeUnsigned64(ebml, SeekPosition, offset);
|
||||
Ebml_EndSubElement(ebml, &start);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
write_webm_seek_info(EbmlGlobal *ebml)
|
||||
{
|
||||
|
||||
off_t pos;
|
||||
|
||||
/* Save the current stream pointer */
|
||||
pos = ftello(ebml->stream);
|
||||
|
||||
if(ebml->seek_info_pos)
|
||||
fseeko(ebml->stream, ebml->seek_info_pos, SEEK_SET);
|
||||
else
|
||||
ebml->seek_info_pos = pos;
|
||||
|
||||
{
|
||||
EbmlLoc start;
|
||||
|
||||
Ebml_StartSubElement(ebml, &start, SeekHead);
|
||||
write_webm_seek_element(ebml, Tracks, ebml->track_pos);
|
||||
write_webm_seek_element(ebml, Cues, ebml->cue_pos);
|
||||
write_webm_seek_element(ebml, Info, ebml->segment_info_pos);
|
||||
Ebml_EndSubElement(ebml, &start);
|
||||
}
|
||||
{
|
||||
//segment info
|
||||
EbmlLoc startInfo;
|
||||
uint64_t frame_time;
|
||||
|
||||
frame_time = (uint64_t)1000 * ebml->framerate.den
|
||||
/ ebml->framerate.num;
|
||||
ebml->segment_info_pos = ftello(ebml->stream);
|
||||
Ebml_StartSubElement(ebml, &startInfo, Info);
|
||||
Ebml_SerializeUnsigned(ebml, TimecodeScale, 1000000);
|
||||
Ebml_SerializeFloat(ebml, Segment_Duration,
|
||||
ebml->last_pts_ms + frame_time);
|
||||
Ebml_SerializeString(ebml, 0x4D80, "vpxenc" VERSION_STRING);
|
||||
Ebml_SerializeString(ebml, 0x5741, "vpxenc" VERSION_STRING);
|
||||
Ebml_EndSubElement(ebml, &startInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
write_webm_file_header(EbmlGlobal *glob,
|
||||
const vpx_codec_enc_cfg_t *cfg,
|
||||
const struct vpx_rational *fps)
|
||||
{
|
||||
{
|
||||
EbmlLoc start;
|
||||
Ebml_StartSubElement(glob, &start, EBML);
|
||||
Ebml_SerializeUnsigned(glob, EBMLVersion, 1);
|
||||
Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1); //EBML Read Version
|
||||
Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4); //EBML Max ID Length
|
||||
Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8); //EBML Max Size Length
|
||||
Ebml_SerializeString(glob, DocType, "webm"); //Doc Type
|
||||
Ebml_SerializeUnsigned(glob, DocTypeVersion, 2); //Doc Type Version
|
||||
Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2); //Doc Type Read Version
|
||||
Ebml_EndSubElement(glob, &start);
|
||||
}
|
||||
{
|
||||
Ebml_StartSubElement(glob, &glob->startSegment, Segment); //segment
|
||||
glob->position_reference = ftello(glob->stream);
|
||||
glob->framerate = *fps;
|
||||
write_webm_seek_info(glob);
|
||||
|
||||
{
|
||||
EbmlLoc trackStart;
|
||||
glob->track_pos = ftello(glob->stream);
|
||||
Ebml_StartSubElement(glob, &trackStart, Tracks);
|
||||
{
|
||||
unsigned int trackNumber = 1;
|
||||
uint64_t trackID = 0;
|
||||
|
||||
EbmlLoc start;
|
||||
Ebml_StartSubElement(glob, &start, TrackEntry);
|
||||
Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
|
||||
Ebml_SerializeUnsigned(glob, TrackUID, trackID);
|
||||
Ebml_SerializeUnsigned(glob, TrackType, 1); //video is always 1
|
||||
Ebml_SerializeString(glob, CodecID, "V_VP8");
|
||||
{
|
||||
unsigned int pixelWidth = cfg->g_w;
|
||||
unsigned int pixelHeight = cfg->g_h;
|
||||
float frameRate = (float)fps->num/(float)fps->den;
|
||||
|
||||
EbmlLoc videoStart;
|
||||
Ebml_StartSubElement(glob, &videoStart, Video);
|
||||
Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
|
||||
Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
|
||||
Ebml_SerializeFloat(glob, FrameRate, frameRate);
|
||||
Ebml_EndSubElement(glob, &videoStart); //Video
|
||||
}
|
||||
Ebml_EndSubElement(glob, &start); //Track Entry
|
||||
}
|
||||
Ebml_EndSubElement(glob, &trackStart);
|
||||
}
|
||||
// segment element is open
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
write_webm_block(EbmlGlobal *glob,
|
||||
const vpx_codec_enc_cfg_t *cfg,
|
||||
const vpx_codec_cx_pkt_t *pkt)
|
||||
{
|
||||
unsigned long block_length;
|
||||
unsigned char track_number;
|
||||
unsigned short block_timecode = 0;
|
||||
unsigned char flags;
|
||||
uint64_t pts_ms;
|
||||
int start_cluster = 0, is_keyframe;
|
||||
|
||||
/* Calculate the PTS of this frame in milliseconds */
|
||||
pts_ms = pkt->data.frame.pts * 1000
|
||||
* (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den;
|
||||
if(pts_ms <= glob->last_pts_ms)
|
||||
pts_ms = glob->last_pts_ms + 1;
|
||||
glob->last_pts_ms = pts_ms;
|
||||
|
||||
/* Calculate the relative time of this block */
|
||||
if(pts_ms - glob->cluster_timecode > SHRT_MAX)
|
||||
start_cluster = 1;
|
||||
else
|
||||
block_timecode = pts_ms - glob->cluster_timecode;
|
||||
|
||||
is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY);
|
||||
if(start_cluster || is_keyframe)
|
||||
{
|
||||
if(glob->cluster_open)
|
||||
Ebml_EndSubElement(glob, &glob->startCluster);
|
||||
|
||||
/* Open the new cluster */
|
||||
block_timecode = 0;
|
||||
glob->cluster_open = 1;
|
||||
glob->cluster_timecode = pts_ms;
|
||||
glob->cluster_pos = ftello(glob->stream);
|
||||
Ebml_StartSubElement(glob, &glob->startCluster, Cluster); //cluster
|
||||
Ebml_SerializeUnsigned(glob, Timecode, glob->cluster_timecode);
|
||||
|
||||
/* Save a cue point if this is a keyframe. */
|
||||
if(is_keyframe)
|
||||
{
|
||||
struct cue_entry *cue;
|
||||
|
||||
glob->cue_list = realloc(glob->cue_list,
|
||||
(glob->cues+1) * sizeof(struct cue_entry));
|
||||
cue = &glob->cue_list[glob->cues];
|
||||
cue->time = glob->cluster_timecode;
|
||||
cue->loc = glob->cluster_pos;
|
||||
glob->cues++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the Simple Block */
|
||||
Ebml_WriteID(glob, SimpleBlock);
|
||||
|
||||
block_length = pkt->data.frame.sz + 4;
|
||||
block_length |= 0x10000000;
|
||||
Ebml_Serialize(glob, &block_length, 4);
|
||||
|
||||
track_number = 1;
|
||||
track_number |= 0x80;
|
||||
Ebml_Write(glob, &track_number, 1);
|
||||
|
||||
Ebml_Serialize(glob, &block_timecode, 2);
|
||||
|
||||
flags = 0;
|
||||
if(is_keyframe)
|
||||
flags |= 0x80;
|
||||
if(pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE)
|
||||
flags |= 0x08;
|
||||
Ebml_Write(glob, &flags, 1);
|
||||
|
||||
Ebml_Write(glob, pkt->data.frame.buf, pkt->data.frame.sz);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
write_webm_file_footer(EbmlGlobal *glob)
|
||||
{
|
||||
|
||||
if(glob->cluster_open)
|
||||
Ebml_EndSubElement(glob, &glob->startCluster);
|
||||
|
||||
{
|
||||
EbmlLoc start;
|
||||
int i;
|
||||
|
||||
glob->cue_pos = ftello(glob->stream);
|
||||
Ebml_StartSubElement(glob, &start, Cues);
|
||||
for(i=0; i<glob->cues; i++)
|
||||
{
|
||||
struct cue_entry *cue = &glob->cue_list[i];
|
||||
EbmlLoc start;
|
||||
|
||||
Ebml_StartSubElement(glob, &start, CuePoint);
|
||||
{
|
||||
EbmlLoc start;
|
||||
|
||||
Ebml_SerializeUnsigned(glob, CueTime, cue->time);
|
||||
|
||||
Ebml_StartSubElement(glob, &start, CueTrackPositions);
|
||||
Ebml_SerializeUnsigned(glob, CueTrack, 1);
|
||||
Ebml_SerializeUnsigned64(glob, CueClusterPosition,
|
||||
cue->loc - glob->position_reference);
|
||||
//Ebml_SerializeUnsigned(glob, CueBlockNumber, cue->blockNumber);
|
||||
Ebml_EndSubElement(glob, &start);
|
||||
}
|
||||
Ebml_EndSubElement(glob, &start);
|
||||
}
|
||||
Ebml_EndSubElement(glob, &start);
|
||||
}
|
||||
|
||||
Ebml_EndSubElement(glob, &glob->startSegment);
|
||||
|
||||
/* Patch up the seek info block */
|
||||
write_webm_seek_info(glob);
|
||||
fseeko(glob->stream, 0, SEEK_END);
|
||||
}
|
||||
|
||||
|
||||
#include "args.h"
|
||||
|
||||
static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
|
||||
"Output filename");
|
||||
static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
|
||||
"Input file is YV12 ");
|
||||
static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
|
||||
@ -423,10 +768,15 @@ static const arg_def_t verbosearg = ARG_DEF("v", "verbose", 0,
|
||||
"Show encoder parameters");
|
||||
static const arg_def_t psnrarg = ARG_DEF(NULL, "psnr", 0,
|
||||
"Show PSNR in status line");
|
||||
static const arg_def_t framerate = ARG_DEF(NULL, "fps", 1,
|
||||
"Stream frame rate (rate/scale)");
|
||||
static const arg_def_t use_ivf = ARG_DEF(NULL, "ivf", 0,
|
||||
"Output IVF (default is WebM)");
|
||||
static const arg_def_t *main_args[] =
|
||||
{
|
||||
&codecarg, &passes, &pass_arg, &fpf_name, &limit, &deadline, &best_dl, &good_dl, &rt_dl,
|
||||
&verbosearg, &psnrarg,
|
||||
&outputfile, &codecarg, &passes, &pass_arg, &fpf_name, &limit, &deadline,
|
||||
&best_dl, &good_dl, &rt_dl,
|
||||
&verbosearg, &psnrarg, &use_ivf, &framerate,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -450,7 +800,7 @@ static const arg_def_t lag_in_frames = ARG_DEF(NULL, "lag-in-frames", 1,
|
||||
static const arg_def_t *global_args[] =
|
||||
{
|
||||
&use_yv12, &use_i420, &usage, &threads, &profile,
|
||||
&width, &height, &timebase, &error_resilient,
|
||||
&width, &height, &timebase, &framerate, &error_resilient,
|
||||
&lag_in_frames, NULL
|
||||
};
|
||||
|
||||
@ -560,7 +910,8 @@ static void usage_exit()
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "Usage: %s <options> src_filename dst_filename\n", exec_name);
|
||||
fprintf(stderr, "Usage: %s <options> -o dst_filename src_filename \n",
|
||||
exec_name);
|
||||
|
||||
fprintf(stderr, "\nOptions:\n");
|
||||
arg_show_usage(stdout, main_args);
|
||||
@ -614,10 +965,13 @@ int main(int argc, const char **argv_)
|
||||
static const int *ctrl_args_map = NULL;
|
||||
int verbose = 0, show_psnr = 0;
|
||||
int arg_use_i420 = 1;
|
||||
int arg_have_timebase = 0;
|
||||
unsigned long cx_time = 0;
|
||||
unsigned int file_type, fourcc;
|
||||
y4m_input y4m;
|
||||
struct vpx_rational arg_framerate = {30, 1};
|
||||
int arg_have_framerate = 0;
|
||||
int write_webm = 1;
|
||||
EbmlGlobal ebml = {0};
|
||||
|
||||
exec_name = argv_[0];
|
||||
|
||||
@ -689,6 +1043,15 @@ int main(int argc, const char **argv_)
|
||||
arg_limit = arg_parse_uint(&arg);
|
||||
else if (arg_match(&arg, &psnrarg, argi))
|
||||
show_psnr = 1;
|
||||
else if (arg_match(&arg, &framerate, argi))
|
||||
{
|
||||
arg_framerate = arg_parse_rational(&arg);
|
||||
arg_have_framerate = 1;
|
||||
}
|
||||
else if (arg_match(&arg, &use_ivf, argi))
|
||||
write_webm = 0;
|
||||
else if (arg_match(&arg, &outputfile, argi))
|
||||
out_fn = arg.val;
|
||||
else
|
||||
argj++;
|
||||
}
|
||||
@ -720,6 +1083,11 @@ int main(int argc, const char **argv_)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Change the default timebase to a high enough value so that the encoder
|
||||
* will always create strictly increasing timestamps.
|
||||
*/
|
||||
cfg.g_timebase.den = 1000;
|
||||
|
||||
/* Now parse the remainder of the parameters. */
|
||||
for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step)
|
||||
{
|
||||
@ -735,10 +1103,7 @@ int main(int argc, const char **argv_)
|
||||
else if (arg_match(&arg, &height, argi))
|
||||
cfg.g_h = arg_parse_uint(&arg);
|
||||
else if (arg_match(&arg, &timebase, argi))
|
||||
{
|
||||
cfg.g_timebase = arg_parse_rational(&arg);
|
||||
arg_have_timebase = 1;
|
||||
}
|
||||
else if (arg_match(&arg, &error_resilient, argi))
|
||||
cfg.g_error_resilient = arg_parse_uint(&arg);
|
||||
else if (arg_match(&arg, &lag_in_frames, argi))
|
||||
@ -851,11 +1216,13 @@ int main(int argc, const char **argv_)
|
||||
|
||||
/* Handle non-option arguments */
|
||||
in_fn = argv[0];
|
||||
out_fn = argv[1];
|
||||
|
||||
if (!in_fn || !out_fn)
|
||||
if (!in_fn)
|
||||
usage_exit();
|
||||
|
||||
if(!out_fn)
|
||||
die("Error: Output file is required (specify with -o)\n");
|
||||
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
|
||||
for (pass = one_pass_only ? one_pass_only - 1 : 0; pass < arg_passes; pass++)
|
||||
@ -883,16 +1250,16 @@ int main(int argc, const char **argv_)
|
||||
file_type = FILE_TYPE_Y4M;
|
||||
cfg.g_w = y4m.pic_w;
|
||||
cfg.g_h = y4m.pic_h;
|
||||
|
||||
/* Use the frame rate from the file only if none was specified
|
||||
* on the command-line.
|
||||
*/
|
||||
if (!arg_have_timebase)
|
||||
if (!arg_have_framerate)
|
||||
{
|
||||
cfg.g_timebase.num = y4m.fps_d;
|
||||
cfg.g_timebase.den = y4m.fps_n;
|
||||
/* And don't reset it in the second pass.*/
|
||||
arg_have_timebase = 1;
|
||||
arg_framerate.num = y4m.fps_n;
|
||||
arg_framerate.den = y4m.fps_d;
|
||||
}
|
||||
|
||||
arg_use_i420 = 0;
|
||||
}
|
||||
else
|
||||
@ -972,13 +1339,6 @@ int main(int argc, const char **argv_)
|
||||
else
|
||||
vpx_img_alloc(&raw, arg_use_i420 ? VPX_IMG_FMT_I420 : VPX_IMG_FMT_YV12,
|
||||
cfg.g_w, cfg.g_h, 1);
|
||||
|
||||
// This was added so that ivfenc will create monotically increasing
|
||||
// timestamps. Since we create new timestamps for alt-reference frames
|
||||
// we need to make room in the series of timestamps. Since there can
|
||||
// only be 1 alt-ref frame ( current bitstream) multiplying by 2
|
||||
// gives us enough room.
|
||||
cfg.g_timebase.den *= 2;
|
||||
}
|
||||
|
||||
outfile = strcmp(out_fn, "-") ? fopen(out_fn, "wb") : stdout;
|
||||
@ -989,6 +1349,12 @@ int main(int argc, const char **argv_)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if(write_webm && fseek(outfile, 0, SEEK_CUR))
|
||||
{
|
||||
fprintf(stderr, "WebM output to pipes not supported.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (stats_fn)
|
||||
{
|
||||
if (!stats_open_file(&stats, stats_fn, pass))
|
||||
@ -1018,7 +1384,13 @@ int main(int argc, const char **argv_)
|
||||
|
||||
#endif
|
||||
|
||||
write_ivf_file_header(outfile, &cfg, codec->fourcc, 0);
|
||||
if(write_webm)
|
||||
{
|
||||
ebml.stream = outfile;
|
||||
write_webm_file_header(&ebml, &cfg, &arg_framerate);
|
||||
}
|
||||
else
|
||||
write_ivf_file_header(outfile, &cfg, codec->fourcc, 0);
|
||||
|
||||
|
||||
/* Construct Encoder Context */
|
||||
@ -1047,6 +1419,7 @@ int main(int argc, const char **argv_)
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt;
|
||||
struct vpx_usec_timer timer;
|
||||
int64_t frame_start;
|
||||
|
||||
if (!arg_limit || frames_in < arg_limit)
|
||||
{
|
||||
@ -1065,10 +1438,12 @@ int main(int argc, const char **argv_)
|
||||
|
||||
vpx_usec_timer_start(&timer);
|
||||
|
||||
// since we halved our timebase we need to double the timestamps
|
||||
// and duration we pass in.
|
||||
vpx_codec_encode(&encoder, frame_avail ? &raw : NULL, (frames_in - 1) * 2,
|
||||
2, 0, arg_deadline);
|
||||
frame_start = (cfg.g_timebase.den * (int64_t)(frames_in - 1)
|
||||
* arg_framerate.den) / cfg.g_timebase.num / arg_framerate.num;
|
||||
vpx_codec_encode(&encoder, frame_avail ? &raw : NULL, frame_start,
|
||||
cfg.g_timebase.den * arg_framerate.den
|
||||
/ cfg.g_timebase.num / arg_framerate.num,
|
||||
0, arg_deadline);
|
||||
vpx_usec_timer_mark(&timer);
|
||||
cx_time += vpx_usec_timer_elapsed(&timer);
|
||||
ctx_exit_on_error(&encoder, "Failed to encode frame");
|
||||
@ -1084,8 +1459,15 @@ int main(int argc, const char **argv_)
|
||||
frames_out++;
|
||||
fprintf(stderr, " %6luF",
|
||||
(unsigned long)pkt->data.frame.sz);
|
||||
write_ivf_frame_header(outfile, pkt);
|
||||
fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile);
|
||||
if(write_webm)
|
||||
{
|
||||
write_webm_block(&ebml, &cfg, pkt);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_ivf_frame_header(outfile, pkt);
|
||||
fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile);
|
||||
}
|
||||
nbytes += pkt->data.raw.sz;
|
||||
break;
|
||||
case VPX_CODEC_STATS_PKT:
|
||||
@ -1116,14 +1498,11 @@ int main(int argc, const char **argv_)
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/* this bitrate calc is simplified and relies on the fact that this
|
||||
* application uses 1/timebase for framerate.
|
||||
*/
|
||||
fprintf(stderr,
|
||||
"\rPass %d/%d frame %4d/%-4d %7ldB %7ldb/f %7"PRId64"b/s"
|
||||
" %7lu %s (%.2f fps)\033[K", pass + 1,
|
||||
arg_passes, frames_in, frames_out, nbytes, nbytes * 8 / frames_in,
|
||||
nbytes * 8 *(int64_t)cfg.g_timebase.den/2/ cfg.g_timebase.num / frames_in,
|
||||
nbytes * 8 *(int64_t)arg_framerate.num / arg_framerate.den / frames_in,
|
||||
cx_time > 9999999 ? cx_time / 1000 : cx_time,
|
||||
cx_time > 9999999 ? "ms" : "us",
|
||||
(float)frames_in * 1000000.0 / (float)cx_time);
|
||||
@ -1132,8 +1511,15 @@ int main(int argc, const char **argv_)
|
||||
|
||||
fclose(infile);
|
||||
|
||||
if (!fseek(outfile, 0, SEEK_SET))
|
||||
write_ivf_file_header(outfile, &cfg, codec->fourcc, frames_out);
|
||||
if(write_webm)
|
||||
{
|
||||
write_webm_file_footer(&ebml);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!fseek(outfile, 0, SEEK_SET))
|
||||
write_ivf_file_header(outfile, &cfg, codec->fourcc, frames_out);
|
||||
}
|
||||
|
||||
fclose(outfile);
|
||||
stats_close(&stats);
|
Loading…
x
Reference in New Issue
Block a user