Import vpxenc from libvpx as a starting point

dev
Kristian Høgsberg 13 years ago
parent 5fb70bf301
commit 89060c0a8b
  1. 2
      Makefile.am
  2. 3
      configure.ac
  3. 231
      wcap-decode/EbmlIDs.h
  4. 171
      wcap-decode/EbmlWriter.c
  5. 38
      wcap-decode/EbmlWriter.h
  6. 265
      wcap-decode/args.c
  7. 54
      wcap-decode/args.h
  8. 234
      wcap-decode/mem_ops.h
  9. 157
      wcap-decode/mem_ops_aligned.h
  10. 30
      wcap-decode/tools_common.c
  11. 16
      wcap-decode/tools_common.h
  12. 120
      wcap-decode/vpx_timer.h
  13. 2544
      wcap-decode/vpxenc.c
  14. 218
      wcap-decode/wcap-decode.c
  15. 871
      wcap-decode/y4minput.c
  16. 60
      wcap-decode/y4minput.h

@ -1,3 +1,3 @@
SUBDIRS = shared src clients data protocol tests SUBDIRS = shared src clients wcap-decode data protocol tests
DISTCHECK_CONFIGURE_FLAGS = --disable-setuid-install DISTCHECK_CONFIGURE_FLAGS = --disable-setuid-install

@ -27,6 +27,8 @@ AC_SUBST(DLOPEN_LIBS)
PKG_CHECK_MODULES(COMPOSITOR, PKG_CHECK_MODULES(COMPOSITOR,
[wayland-server egl >= 7.10 glesv2 xkbcommon pixman-1]) [wayland-server egl >= 7.10 glesv2 xkbcommon pixman-1])
PKG_CHECK_MODULES(WCAP, [cairo vpx])
AC_CHECK_PROG(RSVG_CONVERT, rsvg-convert, rsvg-convert) AC_CHECK_PROG(RSVG_CONVERT, rsvg-convert, rsvg-convert)
AM_CONDITIONAL(HAVE_RSVG_CONVERT, test -n "$RSVG_CONVERT") AM_CONDITIONAL(HAVE_RSVG_CONVERT, test -n "$RSVG_CONVERT")
@ -196,6 +198,7 @@ AC_CONFIG_FILES([Makefile
src/Makefile src/Makefile
src/xwayland/Makefile src/xwayland/Makefile
clients/Makefile clients/Makefile
wcap-decode/Makefile
data/Makefile data/Makefile
protocol/Makefile protocol/Makefile
tests/Makefile]) tests/Makefile])

@ -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

@ -0,0 +1,171 @@
// 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>
#include <limits.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, sizeof(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)
{
int len;
if (class_id >= 0x01000000)
len = 4;
else if (class_id >= 0x00010000)
len = 3;
else if (class_id >= 0x00000100)
len = 2;
else
len = 1;
Ebml_Serialize(glob, (void *)&class_id, sizeof(class_id), len);
}
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, sizeof(sizeSerialized), 1);
Ebml_Serialize(glob, &ui, sizeof(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, sizeof(sizeSerialized), 1);
Ebml_Serialize(glob, &ui, sizeof(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, sizeof(len), 1);
Ebml_Serialize(glob, &d, sizeof(d), 8);
}
void Ebml_WriteSigned16(EbmlGlobal *glob, short val)
{
signed long out = ((val & 0x003FFFFF) | 0x00200000) << 8;
Ebml_Serialize(glob, &out, sizeof(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)
{
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

@ -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 *, int, 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

@ -0,0 +1,265 @@
/*
* 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 <stdlib.h>
#include <string.h>
#include <limits.h>
#include "args.h"
#ifdef _MSC_VER
#define snprintf _snprintf
#endif
#if defined(__GNUC__) && __GNUC__
extern void die(const char *fmt, ...) __attribute__((noreturn));
#else
extern void die(const char *fmt, ...);
#endif
struct arg arg_init(char **argv)
{
struct arg a;
a.argv = argv;
a.argv_step = 1;
a.name = NULL;
a.val = NULL;
a.def = NULL;
return a;
}
int arg_match(struct arg *arg_, const struct arg_def *def, char **argv)
{
struct arg arg;
if (!argv[0] || argv[0][0] != '-')
return 0;
arg = arg_init(argv);
if (def->short_name
&& strlen(arg.argv[0]) == strlen(def->short_name) + 1
&& !strcmp(arg.argv[0] + 1, def->short_name))
{
arg.name = arg.argv[0] + 1;
arg.val = def->has_val ? arg.argv[1] : NULL;
arg.argv_step = def->has_val ? 2 : 1;
}
else if (def->long_name)
{
const size_t name_len = strlen(def->long_name);
if (strlen(arg.argv[0]) >= name_len + 2
&& arg.argv[0][1] == '-'
&& !strncmp(arg.argv[0] + 2, def->long_name, name_len)
&& (arg.argv[0][name_len+2] == '='
|| arg.argv[0][name_len+2] == '\0'))
{
arg.name = arg.argv[0] + 2;
arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL;
arg.argv_step = 1;
}
}
if (arg.name && !arg.val && def->has_val)
die("Error: option %s requires argument.\n", arg.name);
if (arg.name && arg.val && !def->has_val)
die("Error: option %s requires no argument.\n", arg.name);
if (arg.name
&& (arg.val || !def->has_val))
{
arg.def = def;
*arg_ = arg;
return 1;
}
return 0;
}
const char *arg_next(struct arg *arg)
{
if (arg->argv[0])
arg->argv += arg->argv_step;
return *arg->argv;
}
char **argv_dup(int argc, const char **argv)
{
char **new_argv = malloc((argc + 1) * sizeof(*argv));
memcpy(new_argv, argv, argc * sizeof(*argv));
new_argv[argc] = NULL;
return new_argv;
}
void arg_show_usage(FILE *fp, const struct arg_def *const *defs)
{
char option_text[40] = {0};
for (; *defs; defs++)
{
const struct arg_def *def = *defs;
char *short_val = def->has_val ? " <arg>" : "";
char *long_val = def->has_val ? "=<arg>" : "";
if (def->short_name && def->long_name)
{
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);
else if (def->long_name)
snprintf(option_text, 37, " --%s%s",
def->long_name, long_val);
fprintf(fp, " %-37s\t%s\n", option_text, def->desc);
if(def->enums)
{
const struct arg_enum_list *listptr;
fprintf(fp, " %-37s\t ", "");
for(listptr = def->enums; listptr->name; listptr++)
fprintf(fp, "%s%s", listptr->name,
listptr[1].name ? ", " : "\n");
}
}
}
unsigned int arg_parse_uint(const struct arg *arg)
{
long int rawval;
char *endptr;
rawval = strtol(arg->val, &endptr, 10);
if (arg->val[0] != '\0' && endptr[0] == '\0')
{
if (rawval >= 0 && rawval <= UINT_MAX)
return rawval;
die("Option %s: Value %ld out of range for unsigned int\n",
arg->name, rawval);
}
die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
return 0;
}
int arg_parse_int(const struct arg *arg)
{
long int rawval;
char *endptr;
rawval = strtol(arg->val, &endptr, 10);
if (arg->val[0] != '\0' && endptr[0] == '\0')
{
if (rawval >= INT_MIN && rawval <= INT_MAX)
return rawval;
die("Option %s: Value %ld out of range for signed int\n",
arg->name, rawval);
}
die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
return 0;
}
struct vpx_rational
{
int num; /**< fraction numerator */
int den; /**< fraction denominator */
};
struct vpx_rational arg_parse_rational(const struct arg *arg)
{
long int rawval;
char *endptr;
struct vpx_rational rat;
/* parse numerator */
rawval = strtol(arg->val, &endptr, 10);
if (arg->val[0] != '\0' && endptr[0] == '/')
{
if (rawval >= INT_MIN && rawval <= INT_MAX)
rat.num = rawval;
else die("Option %s: Value %ld out of range for signed int\n",
arg->name, rawval);
}
else die("Option %s: Expected / at '%c'\n", arg->name, *endptr);
/* parse denominator */
rawval = strtol(endptr + 1, &endptr, 10);
if (arg->val[0] != '\0' && endptr[0] == '\0')
{
if (rawval >= INT_MIN && rawval <= INT_MAX)
rat.den = rawval;
else die("Option %s: Value %ld out of range for signed int\n",
arg->name, rawval);
}
else die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
return rat;
}
int arg_parse_enum(const struct arg *arg)
{
const struct arg_enum_list *listptr;
long int rawval;
char *endptr;
/* First see if the value can be parsed as a raw value */
rawval = strtol(arg->val, &endptr, 10);
if (arg->val[0] != '\0' && endptr[0] == '\0')
{
/* Got a raw value, make sure it's valid */
for(listptr = arg->def->enums; listptr->name; listptr++)
if(listptr->val == rawval)
return rawval;
}
/* Next see if it can be parsed as a string */
for(listptr = arg->def->enums; listptr->name; listptr++)
if(!strcmp(arg->val, listptr->name))
return listptr->val;
die("Option %s: Invalid value '%s'\n", arg->name, arg->val);
return 0;
}
int arg_parse_enum_or_int(const struct arg *arg)
{
if(arg->def->enums)
return arg_parse_enum(arg);
return arg_parse_int(arg);
}

@ -0,0 +1,54 @@
/*
* 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 ARGS_H
#define ARGS_H
#include <stdio.h>
struct arg
{
char **argv;
const char *name;
const char *val;
unsigned int argv_step;
const struct arg_def *def;
};
struct arg_enum_list
{
const char *name;
int val;
};
#define ARG_ENUM_LIST_END {0}
typedef struct arg_def
{
const char *short_name;
const char *long_name;
int has_val;
const char *desc;
const struct arg_enum_list *enums;
} arg_def_t;
#define ARG_DEF(s,l,v,d) {s,l,v,d, NULL}
#define ARG_DEF_ENUM(s,l,v,d,e) {s,l,v,d,e}
#define ARG_DEF_LIST_END {0}
struct arg arg_init(char **argv);
int arg_match(struct arg *arg_, const struct arg_def *def, char **argv);
const char *arg_next(struct arg *arg);
void arg_show_usage(FILE *fp, const struct arg_def *const *defs);
char **argv_dup(int argc, const char **argv);
unsigned int arg_parse_uint(const struct arg *arg);
int arg_parse_int(const struct arg *arg);
struct vpx_rational arg_parse_rational(const struct arg *arg);
int arg_parse_enum_or_int(const struct arg *arg);
#endif

@ -0,0 +1,234 @@
/*
* 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.
*/
/* \file
* \brief Provides portable memory access primitives
*
* This function provides portable primitives for getting and setting of
* signed and unsigned integers in 16, 24, and 32 bit sizes. The operations
* can be performed on unaligned data regardless of hardware support for
* unaligned accesses.
*
* The type used to pass the integral values may be changed by defining
* MEM_VALUE_T with the appropriate type. The type given must be an integral
* numeric type.
*
* The actual functions instantiated have the MEM_VALUE_T type name pasted
* on to the symbol name. This allows the developer to instantiate these
* operations for multiple types within the same translation unit. This is
* of somewhat questionable utility, but the capability exists nonetheless.
* Users not making use of this functionality should call the functions
* without the type name appended, and the preprocessor will take care of
* it.
*
* NOTE: This code is not supported on platforms where char > 1 octet ATM.
*/
#ifndef MAU_T
/* Minimum Access Unit for this target */
#define MAU_T unsigned char
#endif
#ifndef MEM_VALUE_T
#define MEM_VALUE_T int
#endif
#undef MEM_VALUE_T_SZ_BITS
#define MEM_VALUE_T_SZ_BITS (sizeof(MEM_VALUE_T) << 3)
#undef mem_ops_wrap_symbol
#define mem_ops_wrap_symbol(fn) mem_ops_wrap_symbol2(fn, MEM_VALUE_T)
#undef mem_ops_wrap_symbol2
#define mem_ops_wrap_symbol2(fn,typ) mem_ops_wrap_symbol3(fn,typ)
#undef mem_ops_wrap_symbol3
#define mem_ops_wrap_symbol3(fn,typ) fn##_as_##typ
/*
* Include aligned access routines
*/
#define INCLUDED_BY_MEM_OPS_H
#include "mem_ops_aligned.h"
#undef INCLUDED_BY_MEM_OPS_H
#undef mem_get_be16
#define mem_get_be16 mem_ops_wrap_symbol(mem_get_be16)
static unsigned MEM_VALUE_T mem_get_be16(const void *vmem)
{
unsigned MEM_VALUE_T val;
const MAU_T *mem = (const MAU_T *)vmem;
val = mem[0] << 8;
val |= mem[1];
return val;
}
#undef mem_get_be24
#define mem_get_be24 mem_ops_wrap_symbol(mem_get_be24)
static unsigned MEM_VALUE_T mem_get_be24(const void *vmem)
{
unsigned MEM_VALUE_T val;
const MAU_T *mem = (const MAU_T *)vmem;
val = mem[0] << 16;
val |= mem[1] << 8;
val |= mem[2];
return val;
}
#undef mem_get_be32
#define mem_get_be32 mem_ops_wrap_symbol(mem_get_be32)
static unsigned MEM_VALUE_T mem_get_be32(const void *vmem)
{
unsigned MEM_VALUE_T val;
const MAU_T *mem = (const MAU_T *)vmem;
val = mem[0] << 24;
val |= mem[1] << 16;
val |= mem[2] << 8;
val |= mem[3];
return val;
}
#undef mem_get_le16
#define mem_get_le16 mem_ops_wrap_symbol(mem_get_le16)
static unsigned MEM_VALUE_T mem_get_le16(const void *vmem)
{
unsigned MEM_VALUE_T val;
const MAU_T *mem = (const MAU_T *)vmem;
val = mem[1] << 8;
val |= mem[0];
return val;
}
#undef mem_get_le24
#define mem_get_le24 mem_ops_wrap_symbol(mem_get_le24)
static unsigned MEM_VALUE_T mem_get_le24(const void *vmem)
{
unsigned MEM_VALUE_T val;
const MAU_T *mem = (const MAU_T *)vmem;
val = mem[2] << 16;
val |= mem[1] << 8;
val |= mem[0];
return val;
}
#undef mem_get_le32
#define mem_get_le32 mem_ops_wrap_symbol(mem_get_le32)
static unsigned MEM_VALUE_T mem_get_le32(const void *vmem)
{
unsigned MEM_VALUE_T val;
const MAU_T *mem = (const MAU_T *)vmem;
val = mem[3] << 24;
val |= mem[2] << 16;
val |= mem[1] << 8;
val |= mem[0];
return val;
}
#define mem_get_s_generic(end,sz) \
static signed MEM_VALUE_T mem_get_s##end##sz(const void *vmem) {\
const MAU_T *mem = (const MAU_T*)vmem;\
signed MEM_VALUE_T val = mem_get_##end##sz(mem);\
return (val << (MEM_VALUE_T_SZ_BITS - sz)) >> (MEM_VALUE_T_SZ_BITS - sz);\
}
#undef mem_get_sbe16
#define mem_get_sbe16 mem_ops_wrap_symbol(mem_get_sbe16)
mem_get_s_generic(be, 16);
#undef mem_get_sbe24
#define mem_get_sbe24 mem_ops_wrap_symbol(mem_get_sbe24)
mem_get_s_generic(be, 24);
#undef mem_get_sbe32
#define mem_get_sbe32 mem_ops_wrap_symbol(mem_get_sbe32)
mem_get_s_generic(be, 32);
#undef mem_get_sle16
#define mem_get_sle16 mem_ops_wrap_symbol(mem_get_sle16)
mem_get_s_generic(le, 16);
#undef mem_get_sle24
#define mem_get_sle24 mem_ops_wrap_symbol(mem_get_sle24)
mem_get_s_generic(le, 24);
#undef mem_get_sle32
#define mem_get_sle32 mem_ops_wrap_symbol(mem_get_sle32)
mem_get_s_generic(le, 32);
#undef mem_put_be16
#define mem_put_be16 mem_ops_wrap_symbol(mem_put_be16)
static void mem_put_be16(void *vmem, MEM_VALUE_T val)
{
MAU_T *mem = (MAU_T *)vmem;
mem[0] = (val >> 8) & 0xff;
mem[1] = (val >> 0) & 0xff;
}
#undef mem_put_be24
#define mem_put_be24 mem_ops_wrap_symbol(mem_put_be24)
static void mem_put_be24(void *vmem, MEM_VALUE_T val)
{
MAU_T *mem = (MAU_T *)vmem;
mem[0] = (val >> 16) & 0xff;
mem[1] = (val >> 8) & 0xff;
mem[2] = (val >> 0) & 0xff;
}
#undef mem_put_be32
#define mem_put_be32 mem_ops_wrap_symbol(mem_put_be32)
static void mem_put_be32(void *vmem, MEM_VALUE_T val)
{
MAU_T *mem = (MAU_T *)vmem;
mem[0] = (val >> 24) & 0xff;
mem[1] = (val >> 16) & 0xff;
mem[2] = (val >> 8) & 0xff;
mem[3] = (val >> 0) & 0xff;
}
#undef mem_put_le16
#define mem_put_le16 mem_ops_wrap_symbol(mem_put_le16)
static void mem_put_le16(void *vmem, MEM_VALUE_T val)
{
MAU_T *mem = (MAU_T *)vmem;
mem[0] = (val >> 0) & 0xff;
mem[1] = (val >> 8) & 0xff;
}
#undef mem_put_le24
#define mem_put_le24 mem_ops_wrap_symbol(mem_put_le24)
static void mem_put_le24(void *vmem, MEM_VALUE_T val)
{
MAU_T *mem = (MAU_T *)vmem;
mem[0] = (val >> 0) & 0xff;
mem[1] = (val >> 8) & 0xff;
mem[2] = (val >> 16) & 0xff;
}
#undef mem_put_le32
#define mem_put_le32 mem_ops_wrap_symbol(mem_put_le32)
static void mem_put_le32(void *vmem, MEM_VALUE_T val)
{
MAU_T *mem = (MAU_T *)vmem;
mem[0] = (val >> 0) & 0xff;
mem[1] = (val >> 8) & 0xff;
mem[2] = (val >> 16) & 0xff;
mem[3] = (val >> 24) & 0xff;
}

@ -0,0 +1,157 @@
/*
* 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.
*/
/* \file
* \brief Provides portable memory access primitives for operating on aligned
* data
*
* This file is split from mem_ops.h for easier maintenance. See mem_ops.h
* for a more detailed description of these primitives.
*/
#ifndef INCLUDED_BY_MEM_OPS_H
#error Include mem_ops.h, not mem_ops_aligned.h directly.
#endif
/* Architectures that provide instructions for doing this byte swapping
* could redefine these macros.
*/
#define swap_endian_16(val,raw) do {\
val = ((raw>>8) & 0x00ff) \
| ((raw<<8) & 0xff00);\
} while(0)
#define swap_endian_32(val,raw) do {\
val = ((raw>>24) & 0x000000ff) \
| ((raw>>8) & 0x0000ff00) \
| ((raw<<8) & 0x00ff0000) \
| ((raw<<24) & 0xff000000); \
} while(0)
#define swap_endian_16_se(val,raw) do {\
swap_endian_16(val,raw);\
val = ((val << 16) >> 16);\
} while(0)
#define swap_endian_32_se(val,raw) swap_endian_32(val,raw)
#define mem_get_ne_aligned_generic(end,sz) \
static unsigned MEM_VALUE_T mem_get_##end##sz##_aligned(const void *vmem) {\
const uint##sz##_t *mem = (const uint##sz##_t *)vmem;\
return *mem;\
}
#define mem_get_sne_aligned_generic(end,sz) \
static signed MEM_VALUE_T mem_get_s##end##sz##_aligned(const void *vmem) {\
const int##sz##_t *mem = (const int##sz##_t *)vmem;\
return *mem;\
}
#define mem_get_se_aligned_generic(end,sz) \
static unsigned MEM_VALUE_T mem_get_##end##sz##_aligned(const void *vmem) {\
const uint##sz##_t *mem = (const uint##sz##_t *)vmem;\
unsigned MEM_VALUE_T val, raw = *mem;\
swap_endian_##sz(val,raw);\
return val;\
}
#define mem_get_sse_aligned_generic(end,sz) \
static signed MEM_VALUE_T mem_get_s##end##sz##_aligned(const void *vmem) {\
const int##sz##_t *mem = (const int##sz##_t *)vmem;\
unsigned MEM_VALUE_T val, raw = *mem;\
swap_endian_##sz##_se(val,raw);\
return val;\
}
#define mem_put_ne_aligned_generic(end,sz) \
static void mem_put_##end##sz##_aligned(void *vmem, MEM_VALUE_T val) {\
uint##sz##_t *mem = (uint##sz##_t *)vmem;\
*mem = (uint##sz##_t)val;\
}
#define mem_put_se_aligned_generic(end,sz) \
static void mem_put_##end##sz##_aligned(void *vmem, MEM_VALUE_T val) {\
uint##sz##_t *mem = (uint##sz##_t *)vmem, raw;\
swap_endian_##sz(raw,val);\
*mem = (uint##sz##_t)raw;\
}
#include "vpx_config.h"
#if CONFIG_BIG_ENDIAN
#define mem_get_be_aligned_generic(sz) mem_get_ne_aligned_generic(be,sz)
#define mem_get_sbe_aligned_generic(sz) mem_get_sne_aligned_generic(be,sz)
#define mem_get_le_aligned_generic(sz) mem_get_se_aligned_generic(le,sz)
#define mem_get_sle_aligned_generic(sz) mem_get_sse_aligned_generic(le,sz)
#define mem_put_be_aligned_generic(sz) mem_put_ne_aligned_generic(be,sz)
#define mem_put_le_aligned_generic(sz) mem_put_se_aligned_generic(le,sz)
#else
#define mem_get_be_aligned_generic(sz) mem_get_se_aligned_generic(be,sz)
#define mem_get_sbe_aligned_generic(sz) mem_get_sse_aligned_generic(be,sz)
#define mem_get_le_aligned_generic(sz) mem_get_ne_aligned_generic(le,sz)
#define mem_get_sle_aligned_generic(sz) mem_get_sne_aligned_generic(le,sz)
#define mem_put_be_aligned_generic(sz) mem_put_se_aligned_generic(be,sz)
#define mem_put_le_aligned_generic(sz) mem_put_ne_aligned_generic(le,sz)
#endif
#undef mem_get_be16_aligned
#define mem_get_be16_aligned mem_ops_wrap_symbol(mem_get_be16_aligned)
mem_get_be_aligned_generic(16);
#undef mem_get_be32_aligned
#define mem_get_be32_aligned mem_ops_wrap_symbol(mem_get_be32_aligned)
mem_get_be_aligned_generic(32);
#undef mem_get_le16_aligned
#define mem_get_le16_aligned mem_ops_wrap_symbol(mem_get_le16_aligned)
mem_get_le_aligned_generic(16);
#undef mem_get_le32_aligned
#define mem_get_le32_aligned mem_ops_wrap_symbol(mem_get_le32_aligned)
mem_get_le_aligned_generic(32);
#undef mem_get_sbe16_aligned
#define mem_get_sbe16_aligned mem_ops_wrap_symbol(mem_get_sbe16_aligned)
mem_get_sbe_aligned_generic(16);
#undef mem_get_sbe32_aligned
#define mem_get_sbe32_aligned mem_ops_wrap_symbol(mem_get_sbe32_aligned)
mem_get_sbe_aligned_generic(32);
#undef mem_get_sle16_aligned
#define mem_get_sle16_aligned mem_ops_wrap_symbol(mem_get_sle16_aligned)
mem_get_sle_aligned_generic(16);
#undef mem_get_sle32_aligned
#define mem_get_sle32_aligned mem_ops_wrap_symbol(mem_get_sle32_aligned)
mem_get_sle_aligned_generic(32);
#undef mem_put_be16_aligned
#define mem_put_be16_aligned mem_ops_wrap_symbol(mem_put_be16_aligned)
mem_put_be_aligned_generic(16);
#undef mem_put_be32_aligned
#define mem_put_be32_aligned mem_ops_wrap_symbol(mem_put_be32_aligned)
mem_put_be_aligned_generic(32);
#undef mem_put_le16_aligned
#define mem_put_le16_aligned mem_ops_wrap_symbol(mem_put_le16_aligned)
mem_put_le_aligned_generic(16);
#undef mem_put_le32_aligned
#define mem_put_le32_aligned mem_ops_wrap_symbol(mem_put_le32_aligned)
mem_put_le_aligned_generic(32);
#undef mem_get_ne_aligned_generic
#undef mem_get_se_aligned_generic
#undef mem_get_sne_aligned_generic
#undef mem_get_sse_aligned_generic
#undef mem_put_ne_aligned_generic
#undef mem_put_se_aligned_generic
#undef swap_endian_16
#undef swap_endian_32
#undef swap_endian_16_se
#undef swap_endian_32_se

@ -0,0 +1,30 @@
/*
* 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 <stdio.h>
#include "tools_common.h"
#if defined(_WIN32) || defined(__OS2__)
#include <io.h>
#include <fcntl.h>
#ifdef __OS2__
#define _setmode setmode
#define _fileno fileno
#define _O_BINARY O_BINARY
#endif
#endif
FILE* set_binary_mode(FILE *stream)
{
(void)stream;
#if defined(_WIN32) || defined(__OS2__)
_setmode(_fileno(stream), _O_BINARY);
#endif
return stream;
}

@ -0,0 +1,16 @@
/*
* 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 TOOLS_COMMON_H
#define TOOLS_COMMON_H
/* Sets a stdio stream into binary mode */
FILE* set_binary_mode(FILE *stream);
#endif

@ -0,0 +1,120 @@
/*
* 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 VPX_TIMER_H
#define VPX_TIMER_H
#include "vpx/vpx_integer.h"
#if CONFIG_OS_SUPPORT
#if defined(_WIN32)
/*
* Win32 specific includes
*/
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#else
/*
* POSIX specific includes
*/
#include <sys/time.h>
/* timersub is not provided by msys at this time. */
#ifndef timersub
#define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
#endif
#endif
struct vpx_usec_timer
{
#if defined(_WIN32)
LARGE_INTEGER begin, end;
#else
struct timeval begin, end;
#endif
};
static void
vpx_usec_timer_start(struct vpx_usec_timer *t)
{
#if defined(_WIN32)
QueryPerformanceCounter(&t->begin);
#else
gettimeofday(&t->begin, NULL);
#endif
}
static void
vpx_usec_timer_mark(struct vpx_usec_timer *t)
{
#if defined(_WIN32)
QueryPerformanceCounter(&t->end);
#else
gettimeofday(&t->end, NULL);
#endif
}
static int64_t
vpx_usec_timer_elapsed(struct vpx_usec_timer *t)
{
#if defined(_WIN32)
LARGE_INTEGER freq, diff;
diff.QuadPart = t->end.QuadPart - t->begin.QuadPart;
QueryPerformanceFrequency(&freq);
return diff.QuadPart * 1000000 / freq.QuadPart;
#else
struct timeval diff;
timersub(&t->end, &t->begin, &diff);
return diff.tv_sec * 1000000 + diff.tv_usec;
#endif
}
#else /* CONFIG_OS_SUPPORT = 0*/
/* Empty timer functions if CONFIG_OS_SUPPORT = 0 */
#ifndef timersub
#define timersub(a, b, result)
#endif
struct vpx_usec_timer
{
void *dummy;
};
static void
vpx_usec_timer_start(struct vpx_usec_timer *t) { }
static void
vpx_usec_timer_mark(struct vpx_usec_timer *t) { }
static long
vpx_usec_timer_elapsed(struct vpx_usec_timer *t) { return 0; }
#endif /* CONFIG_OS_SUPPORT */
#endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,218 @@
/*
* Copyright © 2012 Intel Corporation
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of the copyright holders not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The copyright holders make
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <cairo.h>
struct wcap_header {
uint32_t width, height;
};
struct wcap_frame_header {
uint32_t msecs;
uint32_t nrects;
};
struct wcap_rectangle {
int32_t x1, y1, x2, y2;
};
struct wcap_decoder {
int fd;
size_t size;
void *map, *p, *end;
uint32_t *frame;
int width, height;
};
static void
wcap_decoder_decode_rectangle(struct wcap_decoder *decoder,
struct wcap_rectangle *rect)
{
uint32_t v, *p = decoder->p, *d;
int width = rect->x2 - rect->x1, height = rect->y2 - rect->y1;
int x, i, j, k, l, count = width * height;
d = decoder->frame + (rect->y2 - 1) * decoder->width;
x = rect->x1;
i = 0;
while (i < count) {
v = *p++;
l = v >> 24;
if (l < 0xe0) {
j = l + 1;
} else {
j = 1 << (l - 0xe0 + 7);
}
for (k = 0; k < j; k++) {
d[x] = (d[x] + v) | 0xff000000;
x++;
if (x == rect->x2) {
x = rect->x1;
d -= decoder->width;
}
}
i += j;
}
if (i != count)
printf("rle encoding longer than expected (%d expected %d)\n",
i, count);
decoder->p = p;
}
static int
wcap_decoder_get_frame(struct wcap_decoder *decoder)
{
struct wcap_rectangle *rects;
struct wcap_frame_header *header;
uint32_t *s;
uint32_t i;
int width, height;
if (decoder->p == decoder->end)
return 0;
header = decoder->p;
rects = (void *) (header + 1);
decoder->p = (uint32_t *) (rects + header->nrects);
for (i = 0; i < header->nrects; i++) {
width = rects[i].x2 - rects[i].x1;
height = rects[i].y2 - rects[i].y1;
wcap_decoder_decode_rectangle(decoder, &rects[i]);
}
return 1;
}
struct wcap_decoder *
wcap_decoder_create(const char *filename)
{
struct wcap_decoder *decoder;
struct wcap_header *header;
int frame_size;
struct stat buf;
decoder = malloc(sizeof *decoder);
if (decoder == NULL)
return NULL;
decoder->fd = open(filename, O_RDONLY);
if (decoder->fd == -1)
return NULL;
fstat(decoder->fd, &buf);
decoder->size = buf.st_size;
decoder->map = mmap(NULL, decoder->size,
PROT_READ, MAP_PRIVATE, decoder->fd, 0);
header = decoder->map;
decoder->width = header->width;
decoder->height = header->height;
decoder->p = header + 1;
decoder->end = decoder->map + decoder->size;
frame_size = header->width * header->height * 4;
decoder->frame = malloc(frame_size);
memset(decoder->frame, 0, frame_size);
return decoder;
}
void
wcap_decoder_destroy(struct wcap_decoder *decoder)
{
munmap(decoder->map, decoder->size);
free(decoder->frame);
free(decoder);
}
static void
write_png(struct wcap_decoder *decoder, const char *filename)
{
cairo_surface_t *surface;
surface = cairo_image_surface_create_for_data((unsigned char *) decoder->frame,
CAIRO_FORMAT_ARGB32,
decoder->width,
decoder->height,
decoder->width * 4);
cairo_surface_write_to_png(surface, filename);
cairo_surface_destroy(surface);
}
static void
write_all_pngs(struct wcap_decoder *decoder, int frame)
{
char filename[200];
int i;
i = 0;
while (wcap_decoder_get_frame(decoder)) {
if (i == frame || frame == -1) {
snprintf(filename, sizeof filename,
"wcap-frame-%d.png", i);
write_png(decoder, filename);
printf("wrote %s\n", filename);
}
i++;
}
}
int main(int argc, char *argv[])
{
struct wcap_decoder *decoder;
int i, output_frame;
if (argc != 2 && argc != 3) {
fprintf(stderr, "usage: wcap-decode WCAP_FILE [FRAME]\n");
return 1;
}
decoder = wcap_decoder_create(argv[1]);
output_frame = -1;
if (argc == 3)
output_frame = strtol(argv[2], NULL, 0);
if (0)
write_all_pngs(decoder, -1);
else
write_webm(decoder);
printf("wcap file: size %dx%d, %d frames\n",
decoder->width, decoder->height, i);
wcap_decoder_destroy(decoder);
}

@ -0,0 +1,871 @@
/*
* 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.
*
* Based on code from the OggTheora software codec source code,
* Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors.
*/
#include <stdlib.h>
#include <string.h>
#include "y4minput.h"
static int y4m_parse_tags(y4m_input *_y4m,char *_tags){
int got_w;
int got_h;
int got_fps;
int got_interlace;
int got_par;
int got_chroma;
char *p;
char *q;
got_w=got_h=got_fps=got_interlace=got_par=got_chroma=0;
for(p=_tags;;p=q){
/*Skip any leading spaces.*/
while(*p==' ')p++;
/*If that's all we have, stop.*/
if(p[0]=='\0')break;
/*Find the end of this tag.*/
for(q=p+1;*q!='\0'&&*q!=' ';q++);
/*Process the tag.*/
switch(p[0]){
case 'W':{
if(sscanf(p+1,"%d",&_y4m->pic_w)!=1)return -1;
got_w=1;
}break;
case 'H':{
if(sscanf(p+1,"%d",&_y4m->pic_h)!=1)return -1;
got_h=1;
}break;
case 'F':{
if(sscanf(p+1,"%d:%d",&_y4m->fps_n,&_y4m->fps_d)!=2){
return -1;
}
got_fps=1;
}break;
case 'I':{
_y4m->interlace=p[1];
got_interlace=1;
}break;
case 'A':{
if(sscanf(p+1,"%d:%d",&_y4m->par_n,&_y4m->par_d)!=2){
return -1;
}
got_par=1;
}break;
case 'C':{
if(q-p>16)return -1;
memcpy(_y4m->chroma_type,p+1,q-p-1);
_y4m->chroma_type[q-p-1]='\0';
got_chroma=1;
}break;
/*Ignore unknown tags.*/
}
}
if(!got_w||!got_h||!got_fps)return -1;
if(!got_interlace)_y4m->interlace='?';
if(!got_par)_y4m->par_n=_y4m->par_d=0;
/*Chroma-type is not specified in older files, e.g., those generated by
mplayer.*/
if(!got_chroma)strcpy(_y4m->chroma_type,"420");
return 0;
}
/*All anti-aliasing filters in the following conversion functions are based on
one of two window functions:
The 6-tap Lanczos window (for down-sampling and shifts):
sinc(\pi*t)*sinc(\pi*t/3), |t|<3 (sinc(t)==sin(t)/t)
0, |t|>=3
The 4-tap Mitchell window (for up-sampling):
7|t|^3-12|t|^2+16/3, |t|<1
-(7/3)|x|^3+12|x|^2-20|x|+32/3, |t|<2
0, |t|>=2
The number of taps is intentionally kept small to reduce computational
overhead and limit ringing.
The taps from these filters are scaled so that their sum is 1, and the result
is scaled by 128 and rounded to integers to create a filter whose
intermediate values fit inside 16 bits.
Coefficients are rounded in such a way as to ensure their sum is still 128,
which is usually equivalent to normal rounding.
Conversions which require both horizontal and vertical filtering could
have these steps pipelined, for less memory consumption and better cache
performance, but we do them separately for simplicity.*/
#define OC_MINI(_a,_b) ((_a)>(_b)?(_b):(_a))
#define OC_MAXI(_a,_b) ((_a)<(_b)?(_b):(_a))
#define OC_CLAMPI(_a,_b,_c) (OC_MAXI(_a,OC_MINI(_b,_c)))
/*420jpeg chroma samples are sited like:
Y-------Y-------Y-------Y-------
| | | |
| BR | | BR |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| | | |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| BR | | BR |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| | | |
| | | |
420mpeg2 chroma samples are sited like:
Y-------Y-------Y-------Y-------
| | | |
BR | BR |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| | | |
| | | |
Y-------Y-------Y-------Y-------
| | | |
BR | BR |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| | | |
| | | |
We use a resampling filter to shift the site locations one quarter pixel (at
the chroma plane's resolution) to the right.
The 4:2:2 modes look exactly the same, except there are twice as many chroma
lines, and they are vertically co-sited with the luma samples in both the
mpeg2 and jpeg cases (thus requiring no vertical resampling).*/
static void y4m_42xmpeg2_42xjpeg_helper(unsigned char *_dst,
const unsigned char *_src,int _c_w,int _c_h){
int y;
int x;
for(y=0;y<_c_h;y++){
/*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
window.*/
for(x=0;x<OC_MINI(_c_w,2);x++){
_dst[x]=(unsigned char)OC_CLAMPI(0,(4*_src[0]-17*_src[OC_MAXI(x-1,0)]+
114*_src[x]+35*_src[OC_MINI(x+1,_c_w-1)]-9*_src[OC_MINI(x+2,_c_w-1)]+
_src[OC_MINI(x+3,_c_w-1)]+64)>>7,255);
}
for(;x<_c_w-3;x++){
_dst[x]=(unsigned char)OC_CLAMPI(0,(4*_src[x-2]-17*_src[x-1]+
114*_src[x]+35*_src[x+1]-9*_src[x+2]+_src[x+3]+64)>>7,255);
}
for(;x<_c_w;x++){
_dst[x]=(unsigned char)OC_CLAMPI(0,(4*_src[x-2]-17*_src[x-1]+
114*_src[x]+35*_src[OC_MINI(x+1,_c_w-1)]-9*_src[OC_MINI(x+2,_c_w-1)]+
_src[_c_w-1]+64)>>7,255);
}
_dst+=_c_w;
_src+=_c_w;
}
}
/*Handles both 422 and 420mpeg2 to 422jpeg and 420jpeg, respectively.*/
static void y4m_convert_42xmpeg2_42xjpeg(y4m_input *_y4m,unsigned char *_dst,
unsigned char *_aux){
int c_w;
int c_h;
int c_sz;
int pli;
/*Skip past the luma data.*/
_dst+=_y4m->pic_w*_y4m->pic_h;
/*Compute the size of each chroma plane.*/
c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
c_sz=c_w*c_h;
for(pli=1;pli<3;pli++){
y4m_42xmpeg2_42xjpeg_helper(_dst,_aux,c_w,c_h);
_dst+=c_sz;
_aux+=c_sz;
}
}
/*This format is only used for interlaced content, but is included for
completeness.
420jpeg chroma samples are sited like:
Y-------Y-------Y-------Y-------
| | | |
| BR | | BR |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| | | |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| BR | | BR |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| | | |
| | | |
420paldv chroma samples are sited like:
YR------Y-------YR------Y-------
| | | |
| | | |
| | | |
YB------Y-------YB------Y-------
| | | |
| | | |
| | | |
YR------Y-------YR------Y-------
| | | |
| | | |
| | | |
YB------Y-------YB------Y-------
| | | |
| | | |
| | | |
We use a resampling filter to shift the site locations one quarter pixel (at
the chroma plane's resolution) to the right.
Then we use another filter to move the C_r location down one quarter pixel,
and the C_b location up one quarter pixel.*/
static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m,unsigned char *_dst,
unsigned char *_aux){
unsigned char *tmp;
int c_w;
int c_h;
int c_sz;
int pli;
int y;
int x;
/*Skip past the luma data.*/
_dst+=_y4m->pic_w*_y4m->pic_h;
/*Compute the size of each chroma plane.*/
c_w=(_y4m->pic_w+1)/2;
c_h=(_y4m->pic_h+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
c_sz=c_w*c_h;
tmp=_aux+2*c_sz;
for(pli=1;pli<3;pli++){
/*First do the horizontal re-sampling.
This is the same as the mpeg2 case, except that after the horizontal
case, we need to apply a second vertical filter.*/
y4m_42xmpeg2_42xjpeg_helper(tmp,_aux,c_w,c_h);
_aux+=c_sz;
switch(pli){
case 1:{
/*Slide C_b up a quarter-pel.
This is the same filter used above, but in the other order.*/
for(x=0;x<c_w;x++){
for(y=0;y<OC_MINI(c_h,3);y++){
_dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(tmp[0]
-9*tmp[OC_MAXI(y-2,0)*c_w]+35*tmp[OC_MAXI(y-1,0)*c_w]
+114*tmp[y*c_w]-17*tmp[OC_MINI(y+1,c_h-1)*c_w]
+4*tmp[OC_MINI(y+2,c_h-1)*c_w]+64)>>7,255);
}
for(;y<c_h-2;y++){
_dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(tmp[(y-3)*c_w]
-9*tmp[(y-2)*c_w]+35*tmp[(y-1)*c_w]+114*tmp[y*c_w]
-17*tmp[(y+1)*c_w]+4*tmp[(y+2)*c_w]+64)>>7,255);
}
for(;y<c_h;y++){
_dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(tmp[(y-3)*c_w]
-9*tmp[(y-2)*c_w]+35*tmp[(y-1)*c_w]+114*tmp[y*c_w]
-17*tmp[OC_MINI(y+1,c_h-1)*c_w]+4*tmp[(c_h-1)*c_w]+64)>>7,255);
}
_dst++;
tmp++;
}
_dst+=c_sz-c_w;
tmp-=c_w;
}break;
case 2:{
/*Slide C_r down a quarter-pel.
This is the same as the horizontal filter.*/
for(x=0;x<c_w;x++){
for(y=0;y<OC_MINI(c_h,2);y++){
_dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(4*tmp[0]
-17*tmp[OC_MAXI(y-1,0)*c_w]+114*tmp[y*c_w]
+35*tmp[OC_MINI(y+1,c_h-1)*c_w]-9*tmp[OC_MINI(y+2,c_h-1)*c_w]
+tmp[OC_MINI(y+3,c_h-1)*c_w]+64)>>7,255);
}
for(;y<c_h-3;y++){
_dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(4*tmp[(y-2)*c_w]
-17*tmp[(y-1)*c_w]+114*tmp[y*c_w]+35*tmp[(y+1)*c_w]
-9*tmp[(y+2)*c_w]+tmp[(y+3)*c_w]+64)>>7,255);
}
for(;y<c_h;y++){
_dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(4*tmp[(y-2)*c_w]
-17*tmp[(y-1)*c_w]+114*tmp[y*c_w]+35*tmp[OC_MINI(y+1,c_h-1)*c_w]
-9*tmp[OC_MINI(y+2,c_h-1)*c_w]+tmp[(c_h-1)*c_w]+64)>>7,255);
}
_dst++;
tmp++;
}
}break;
}
/*For actual interlaced material, this would have to be done separately on
each field, and the shift amounts would be different.
C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8,
C_b up 1/8 in the bottom field.
The corresponding filters would be:
Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128
Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/
}
}
/*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
This is used as a helper by several converation routines.*/
static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst,
const unsigned char *_src,int _c_w,int _c_h){
int y;
int x;
/*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
for(x=0;x<_c_w;x++){
for(y=0;y<OC_MINI(_c_h,2);y+=2){
_dst[(y>>1)*_c_w]=OC_CLAMPI(0,(64*_src[0]
+78*_src[OC_MINI(1,_c_h-1)*_c_w]
-17*_src[OC_MINI(2,_c_h-1)*_c_w]
+3*_src[OC_MINI(3,_c_h-1)*_c_w]+64)>>7,255);
}
for(;y<_c_h-3;y+=2){
_dst[(y>>1)*_c_w]=OC_CLAMPI(0,(3*(_src[(y-2)*_c_w]+_src[(y+3)*_c_w])
-17*(_src[(y-1)*_c_w]+_src[(y+2)*_c_w])
+78*(_src[y*_c_w]+_src[(y+1)*_c_w])+64)>>7,255);
}
for(;y<_c_h;y+=2){
_dst[(y>>1)*_c_w]=OC_CLAMPI(0,(3*(_src[(y-2)*_c_w]
+_src[(_c_h-1)*_c_w])-17*(_src[(y-1)*_c_w]
+_src[OC_MINI(y+2,_c_h-1)*_c_w])
+78*(_src[y*_c_w]+_src[OC_MINI(y+1,_c_h-1)*_c_w])+64)>>7,255);
}
_src++;
_dst++;
}
}
/*420jpeg chroma samples are sited like:
Y-------Y-------Y-------Y-------
| | | |
| BR | | BR |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| | | |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| BR | | BR |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| | | |
| | | |
422jpeg chroma samples are sited like:
Y---BR--Y-------Y---BR--Y-------
| | | |
| | | |
| | | |
Y---BR--Y-------Y---BR--Y-------
| | | |
| | | |
| | | |
Y---BR--Y-------Y---BR--Y-------
| | | |
| | | |
| | | |
Y---BR--Y-------Y---BR--Y-------
| | | |
| | | |
| | | |
We use a resampling filter to decimate the chroma planes by two in the
vertical direction.*/
static void y4m_convert_422jpeg_420jpeg(y4m_input *_y4m,unsigned char *_dst,
unsigned char *_aux){
int c_w;
int c_h;
int c_sz;
int dst_c_w;
int dst_c_h;
int dst_c_sz;
int pli;
/*Skip past the luma data.*/
_dst+=_y4m->pic_w*_y4m->pic_h;
/*Compute the size of each chroma plane.*/
c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
c_h=_y4m->pic_h;
dst_c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
c_sz=c_w*c_h;
dst_c_sz=dst_c_w*dst_c_h;
for(pli=1;pli<3;pli++){
y4m_422jpeg_420jpeg_helper(_dst,_aux,c_w,c_h);
_aux+=c_sz;
_dst+=dst_c_sz;
}
}
/*420jpeg chroma samples are sited like:
Y-------Y-------Y-------Y-------
| | | |
| BR | | BR |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| | | |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| BR | | BR |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| | | |
| | | |
422 chroma samples are sited like:
YBR-----Y-------YBR-----Y-------
| | | |
| | | |
| | | |
YBR-----Y-------YBR-----Y-------
| | | |
| | | |
| | | |
YBR-----Y-------YBR-----Y-------
| | | |
| | | |
| | | |
YBR-----Y-------YBR-----Y-------
| | | |
| | | |
| | | |
We use a resampling filter to shift the original site locations one quarter
pixel (at the original chroma resolution) to the right.
Then we use a second resampling filter to decimate the chroma planes by two
in the vertical direction.*/
static void y4m_convert_422_420jpeg(y4m_input *_y4m,unsigned char *_dst,
unsigned char *_aux){
unsigned char *tmp;
int c_w;
int c_h;
int c_sz;
int dst_c_h;
int dst_c_sz;
int pli;
/*Skip past the luma data.*/
_dst+=_y4m->pic_w*_y4m->pic_h;
/*Compute the size of each chroma plane.*/
c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
c_h=_y4m->pic_h;
dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
c_sz=c_w*c_h;
dst_c_sz=c_w*dst_c_h;
tmp=_aux+2*c_sz;
for(pli=1;pli<3;pli++){
/*In reality, the horizontal and vertical steps could be pipelined, for
less memory consumption and better cache performance, but we do them
separately for simplicity.*/
/*First do horizontal filtering (convert to 422jpeg)*/
y4m_42xmpeg2_42xjpeg_helper(tmp,_aux,c_w,c_h);
/*Now do the vertical filtering.*/
y4m_422jpeg_420jpeg_helper(_dst,tmp,c_w,c_h);
_aux+=c_sz;
_dst+=dst_c_sz;
}
}
/*420jpeg chroma samples are sited like:
Y-------Y-------Y-------Y-------
| | | |
| BR | | BR |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| | | |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| BR | | BR |
| | | |
Y-------Y-------Y-------Y-------
| | | |
| | | |
| | | |
411 chroma samples are sited like:
YBR-----Y-------Y-------Y-------
| | | |
| | | |
| | | |
YBR-----Y-------Y-------Y-------
| | | |
| | | |
| | | |
YBR-----Y-------Y-------Y-------
| | | |
| | | |
| | | |
YBR-----Y-------Y-------Y-------
| | | |
| | | |
| | | |
We use a filter to resample at site locations one eighth pixel (at the source
chroma plane's horizontal resolution) and five eighths of a pixel to the
right.
Then we use another filter to decimate the planes by 2 in the vertical
direction.*/
static void y4m_convert_411_420jpeg(y4m_input *_y4m,unsigned char *_dst,
unsigned char *_aux){
unsigned char *tmp;
int c_w;
int c_h;
int c_sz;
int dst_c_w;
int dst_c_h;
int dst_c_sz;
int tmp_sz;
int pli;
int y;
int x;
/*Skip past the luma data.*/
_dst+=_y4m->pic_w*_y4m->pic_h;
/*Compute the size of each chroma plane.*/
c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
c_h=_y4m->pic_h;
dst_c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
c_sz=c_w*c_h;
dst_c_sz=dst_c_w*dst_c_h;
tmp_sz=dst_c_w*c_h;
tmp=_aux+2*c_sz;
for(pli=1;pli<3;pli++){
/*In reality, the horizontal and vertical steps could be pipelined, for
less memory consumption and better cache performance, but we do them
separately for simplicity.*/
/*First do horizontal filtering (convert to 422jpeg)*/
for(y=0;y<c_h;y++){
/*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
4-tap Mitchell window.*/
for(x=0;x<OC_MINI(c_w,1);x++){
tmp[x<<1]=(unsigned char)OC_CLAMPI(0,(111*_aux[0]
+18*_aux[OC_MINI(1,c_w-1)]-_aux[OC_MINI(2,c_w-1)]+64)>>7,255);
tmp[x<<1|1]=(unsigned char)OC_CLAMPI(0,(47*_aux[0]
+86*_aux[OC_MINI(1,c_w-1)]-5*_aux[OC_MINI(2,c_w-1)]+64)>>7,255);
}
for(;x<c_w-2;x++){
tmp[x<<1]=(unsigned char)OC_CLAMPI(0,(_aux[x-1]+110*_aux[x]
+18*_aux[x+1]-_aux[x+2]+64)>>7,255);
tmp[x<<1|1]=(unsigned char)OC_CLAMPI(0,(-3*_aux[x-1]+50*_aux[x]
+86*_aux[x+1]-5*_aux[x+2]+64)>>7,255);
}
for(;x<c_w;x++){
tmp[x<<1]=(unsigned char)OC_CLAMPI(0,(_aux[x-1]+110*_aux[x]
+18*_aux[OC_MINI(x+1,c_w-1)]-_aux[c_w-1]+64)>>7,255);
if((x<<1|1)<dst_c_w){
tmp[x<<1|1]=(unsigned char)OC_CLAMPI(0,(-3*_aux[x-1]+50*_aux[x]
+86*_aux[OC_MINI(x+1,c_w-1)]-5*_aux[c_w-1]+64)>>7,255);
}
}
tmp+=dst_c_w;
_aux+=c_w;
}
tmp-=tmp_sz;
/*Now do the vertical filtering.*/
y4m_422jpeg_420jpeg_helper(_dst,tmp,dst_c_w,c_h);
_dst+=dst_c_sz;
}
}
/*Convert 444 to 420jpeg.*/
static void y4m_convert_444_420jpeg(y4m_input *_y4m,unsigned char *_dst,
unsigned char *_aux){
unsigned char *tmp;
int c_w;
int c_h;
int c_sz;
int dst_c_w;
int dst_c_h;
int dst_c_sz;
int tmp_sz;
int pli;
int y;
int x;
/*Skip past the luma data.*/
_dst+=_y4m->pic_w*_y4m->pic_h;
/*Compute the size of each chroma plane.*/
c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h;
c_h=_y4m->pic_h;
dst_c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
c_sz=c_w*c_h;
dst_c_sz=dst_c_w*dst_c_h;
tmp_sz=dst_c_w*c_h;
tmp=_aux+2*c_sz;
for(pli=1;pli<3;pli++){
/*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
for(y=0;y<c_h;y++){
for(x=0;x<OC_MINI(c_w,2);x+=2){
tmp[x>>1]=OC_CLAMPI(0,(64*_aux[0]+78*_aux[OC_MINI(1,c_w-1)]
-17*_aux[OC_MINI(2,c_w-1)]
+3*_aux[OC_MINI(3,c_w-1)]+64)>>7,255);
}
for(;x<c_w-3;x+=2){
tmp[x>>1]=OC_CLAMPI(0,(3*(_aux[x-2]+_aux[x+3])
-17*(_aux[x-1]+_aux[x+2])+78*(_aux[x]+_aux[x+1])+64)>>7,255);
}
for(;x<c_w;x+=2){
tmp[x>>1]=OC_CLAMPI(0,(3*(_aux[x-2]+_aux[c_w-1])-
17*(_aux[x-1]+_aux[OC_MINI(x+2,c_w-1)])+
78*(_aux[x]+_aux[OC_MINI(x+1,c_w-1)])+64)>>7,255);
}
tmp+=dst_c_w;
_aux+=c_w;
}
tmp-=tmp_sz;
/*Now do the vertical filtering.*/
y4m_422jpeg_420jpeg_helper(_dst,tmp,dst_c_w,c_h);
_dst+=dst_c_sz;
}
}
/*The image is padded with empty chroma components at 4:2:0.*/
static void y4m_convert_mono_420jpeg(y4m_input *_y4m,unsigned char *_dst,
unsigned char *_aux){
int c_sz;
_dst+=_y4m->pic_w*_y4m->pic_h;
c_sz=((_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h)*
((_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v);
memset(_dst,128,c_sz*2);
}
/*No conversion function needed.*/
static void y4m_convert_null(y4m_input *_y4m,unsigned char *_dst,
unsigned char *_aux){
}
int y4m_input_open(y4m_input *_y4m,FILE *_fin,char *_skip,int _nskip){
char buffer[80];
int ret;
int i;
/*Read until newline, or 80 cols, whichever happens first.*/
for(i=0;i<79;i++){
if(_nskip>0){
buffer[i]=*_skip++;
_nskip--;
}
else{
ret=fread(buffer+i,1,1,_fin);
if(ret<1)return -1;
}
if(buffer[i]=='\n')break;
}
/*We skipped too much header data.*/
if(_nskip>0)return -1;
if(i==79){
fprintf(stderr,"Error parsing header; not a YUV2MPEG2 file?\n");
return -1;
}
buffer[i]='\0';
if(memcmp(buffer,"YUV4MPEG",8)){
fprintf(stderr,"Incomplete magic for YUV4MPEG file.\n");
return -1;
}
if(buffer[8]!='2'){
fprintf(stderr,"Incorrect YUV input file version; YUV4MPEG2 required.\n");
}
ret=y4m_parse_tags(_y4m,buffer+5);
if(ret<0){
fprintf(stderr,"Error parsing YUV4MPEG2 header.\n");
return ret;
}
if(_y4m->interlace=='?'){
fprintf(stderr,"Warning: Input video interlacing format unknown; "
"assuming progressive scan.\n");
}
else if(_y4m->interlace!='p'){
fprintf(stderr,"Input video is interlaced; "
"Only progressive scan handled.\n");
return -1;
}
if(strcmp(_y4m->chroma_type,"420")==0||
strcmp(_y4m->chroma_type,"420jpeg")==0){
_y4m->src_c_dec_h=_y4m->dst_c_dec_h=_y4m->src_c_dec_v=_y4m->dst_c_dec_v=2;
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h
+2*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
/*Natively supported: no conversion required.*/
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz=0;
_y4m->convert=y4m_convert_null;
}
else if(strcmp(_y4m->chroma_type,"420mpeg2")==0){
_y4m->src_c_dec_h=_y4m->dst_c_dec_h=_y4m->src_c_dec_v=_y4m->dst_c_dec_v=2;
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
/*Chroma filter required: read into the aux buf first.*/
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz=
2*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
_y4m->convert=y4m_convert_42xmpeg2_42xjpeg;
}
else if(strcmp(_y4m->chroma_type,"420paldv")==0){
_y4m->src_c_dec_h=_y4m->dst_c_dec_h=_y4m->src_c_dec_v=_y4m->dst_c_dec_v=2;
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
/*Chroma filter required: read into the aux buf first.
We need to make two filter passes, so we need some extra space in the
aux buffer.*/
_y4m->aux_buf_sz=3*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
_y4m->aux_buf_read_sz=2*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2);
_y4m->convert=y4m_convert_42xpaldv_42xjpeg;
}
else if(strcmp(_y4m->chroma_type,"422jpeg")==0){
_y4m->src_c_dec_h=_y4m->dst_c_dec_h=2;
_y4m->src_c_dec_v=1;
_y4m->dst_c_dec_v=2;
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
/*Chroma filter required: read into the aux buf first.*/
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz=2*((_y4m->pic_w+1)/2)*_y4m->pic_h;
_y4m->convert=y4m_convert_422jpeg_420jpeg;
}
else if(strcmp(_y4m->chroma_type,"422")==0){
_y4m->src_c_dec_h=_y4m->dst_c_dec_h=2;
_y4m->src_c_dec_v=1;
_y4m->dst_c_dec_v=2;
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
/*Chroma filter required: read into the aux buf first.
We need to make two filter passes, so we need some extra space in the
aux buffer.*/
_y4m->aux_buf_read_sz=2*((_y4m->pic_w+1)/2)*_y4m->pic_h;
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz+((_y4m->pic_w+1)/2)*_y4m->pic_h;
_y4m->convert=y4m_convert_422_420jpeg;
}
else if(strcmp(_y4m->chroma_type,"411")==0){
_y4m->src_c_dec_h=4;
_y4m->dst_c_dec_h=2;
_y4m->src_c_dec_v=1;
_y4m->dst_c_dec_v=2;
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
/*Chroma filter required: read into the aux buf first.
We need to make two filter passes, so we need some extra space in the
aux buffer.*/
_y4m->aux_buf_read_sz=2*((_y4m->pic_w+3)/4)*_y4m->pic_h;
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz+((_y4m->pic_w+1)/2)*_y4m->pic_h;
_y4m->convert=y4m_convert_411_420jpeg;
}
else if(strcmp(_y4m->chroma_type,"444")==0){
_y4m->src_c_dec_h=1;
_y4m->dst_c_dec_h=2;
_y4m->src_c_dec_v=1;
_y4m->dst_c_dec_v=2;
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
/*Chroma filter required: read into the aux buf first.
We need to make two filter passes, so we need some extra space in the
aux buffer.*/
_y4m->aux_buf_read_sz=2*_y4m->pic_w*_y4m->pic_h;
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz+((_y4m->pic_w+1)/2)*_y4m->pic_h;
_y4m->convert=y4m_convert_444_420jpeg;
}
else if(strcmp(_y4m->chroma_type,"444alpha")==0){
_y4m->src_c_dec_h=1;
_y4m->dst_c_dec_h=2;
_y4m->src_c_dec_v=1;
_y4m->dst_c_dec_v=2;
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
/*Chroma filter required: read into the aux buf first.
We need to make two filter passes, so we need some extra space in the
aux buffer.
The extra plane also gets read into the aux buf.
It will be discarded.*/
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz=3*_y4m->pic_w*_y4m->pic_h;
_y4m->convert=y4m_convert_444_420jpeg;
}
else if(strcmp(_y4m->chroma_type,"mono")==0){
_y4m->src_c_dec_h=_y4m->src_c_dec_v=0;
_y4m->dst_c_dec_h=_y4m->dst_c_dec_v=2;
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h;
/*No extra space required, but we need to clear the chroma planes.*/
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz=0;
_y4m->convert=y4m_convert_mono_420jpeg;
}
else{
fprintf(stderr,"Unknown chroma sampling type: %s\n",_y4m->chroma_type);
return -1;
}
/*The size of the final frame buffers is always computed from the
destination chroma decimation type.*/
_y4m->dst_buf_sz=_y4m->pic_w*_y4m->pic_h
+2*((_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h)*
((_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v);
_y4m->dst_buf=(unsigned char *)malloc(_y4m->dst_buf_sz);
_y4m->aux_buf=(unsigned char *)malloc(_y4m->aux_buf_sz);
return 0;
}
void y4m_input_close(y4m_input *_y4m){
free(_y4m->dst_buf);
free(_y4m->aux_buf);
}
int y4m_input_fetch_frame(y4m_input *_y4m,FILE *_fin,vpx_image_t *_img){
char frame[6];
int pic_sz;
int c_w;
int c_h;
int c_sz;
int ret;
/*Read and skip the frame header.*/
ret=fread(frame,1,6,_fin);
if(ret<6)return 0;
if(memcmp(frame,"FRAME",5)){
fprintf(stderr,"Loss of framing in Y4M input data\n");
return -1;
}
if(frame[5]!='\n'){
char c;
int j;
for(j=0;j<79&&fread(&c,1,1,_fin)&&c!='\n';j++);
if(j==79){
fprintf(stderr,"Error parsing Y4M frame header\n");
return -1;
}
}
/*Read the frame data that needs no conversion.*/
if(fread(_y4m->dst_buf,1,_y4m->dst_buf_read_sz,_fin)!=_y4m->dst_buf_read_sz){
fprintf(stderr,"Error reading Y4M frame data.\n");
return -1;
}
/*Read the frame data that does need conversion.*/
if(fread(_y4m->aux_buf,1,_y4m->aux_buf_read_sz,_fin)!=_y4m->aux_buf_read_sz){
fprintf(stderr,"Error reading Y4M frame data.\n");
return -1;
}
/*Now convert the just read frame.*/
(*_y4m->convert)(_y4m,_y4m->dst_buf,_y4m->aux_buf);
/*Fill in the frame buffer pointers.
We don't use vpx_img_wrap() because it forces padding for odd picture
sizes, which would require a separate fread call for every row.*/
memset(_img,0,sizeof(*_img));
/*Y4M has the planes in Y'CbCr order, which libvpx calls Y, U, and V.*/
_img->fmt=IMG_FMT_I420;
_img->w=_img->d_w=_y4m->pic_w;
_img->h=_img->d_h=_y4m->pic_h;
/*This is hard-coded to 4:2:0 for now, as that's all VP8 supports.*/
_img->x_chroma_shift=1;
_img->y_chroma_shift=1;
_img->bps=12;
/*Set up the buffer pointers.*/
pic_sz=_y4m->pic_w*_y4m->pic_h;
c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h;
c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v;
c_sz=c_w*c_h;
_img->stride[PLANE_Y]=_y4m->pic_w;
_img->stride[PLANE_U]=_img->stride[PLANE_V]=c_w;
_img->planes[PLANE_Y]=_y4m->dst_buf;
_img->planes[PLANE_U]=_y4m->dst_buf+pic_sz;
_img->planes[PLANE_V]=_y4m->dst_buf+pic_sz+c_sz;
return 1;
}

@ -0,0 +1,60 @@
/*
* 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.
*
* Based on code from the OggTheora software codec source code,
* Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors.
*/
#if !defined(_y4minput_H)
# define _y4minput_H (1)
# include <stdio.h>
# include "vpx/vpx_image.h"
typedef struct y4m_input y4m_input;
/*The function used to perform chroma conversion.*/
typedef void (*y4m_convert_func)(y4m_input *_y4m,
unsigned char *_dst,unsigned char *_src);
struct y4m_input{
int pic_w;
int pic_h;
int fps_n;
int fps_d;
int par_n;
int par_d;
char interlace;
int src_c_dec_h;
int src_c_dec_v;
int dst_c_dec_h;
int dst_c_dec_v;
char chroma_type[16];
/*The size of each converted frame buffer.*/
size_t dst_buf_sz;
/*The amount to read directly into the converted frame buffer.*/
size_t dst_buf_read_sz;
/*The size of the auxilliary buffer.*/
size_t aux_buf_sz;
/*The amount to read into the auxilliary buffer.*/
size_t aux_buf_read_sz;
y4m_convert_func convert;
unsigned char *dst_buf;
unsigned char *aux_buf;
};
int y4m_input_open(y4m_input *_y4m,FILE *_fin,char *_skip,int _nskip);
void y4m_input_close(y4m_input *_y4m);
int y4m_input_fetch_frame(y4m_input *_y4m,FILE *_fin,vpx_image_t *img);
#endif
Loading…
Cancel
Save