remove the need for libtheora since we have ffmpeg to handle
theora videos
This commit is contained in:
@@ -9,6 +9,10 @@ ________________________________________________________________________________
|
|||||||
StepMania 5.0 alpha 2 | 201203??
|
StepMania 5.0 alpha 2 | 201203??
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
2012/03/12
|
||||||
|
----------
|
||||||
|
* Remove libtheora support since ffmpeg already supports theora videos. [cvpcs]
|
||||||
|
|
||||||
2012/03/10
|
2012/03/10
|
||||||
----------
|
----------
|
||||||
* Update ffmpeg support to v0.10. [cvpcs]
|
* Update ffmpeg support to v0.10. [cvpcs]
|
||||||
|
|||||||
@@ -28,29 +28,4 @@ LIB_POST=
|
|||||||
|
|
||||||
AM_CONDITIONAL(HAVE_FFMPEG, test "$have_ffmpeg" = "yes")
|
AM_CONDITIONAL(HAVE_FFMPEG, test "$have_ffmpeg" = "yes")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AC_ARG_WITH(theora, AS_HELP_STRING([--without-theora],[Disable Theora support]), with_theora=$withval, with_theora=yes)
|
|
||||||
|
|
||||||
have_vorbis=no
|
|
||||||
if test "$with_theora" = "yes"; then
|
|
||||||
AC_CHECK_LIB(ogg, ogg_stream_init, have_libogg=yes, have_libogg=no)
|
|
||||||
AC_CHECK_LIB(theora, theora_decode_init, have_libtheora=yes, have_libtheora=no, [-logg])
|
|
||||||
if test "$have_libtheora" = "yes" -a "$have_libogg" = "yes" -a "$have_ffmpeg" = "yes"; then
|
|
||||||
have_theora=yes
|
|
||||||
LIBS="$LIBS -ltheora -logg"
|
|
||||||
AC_DEFINE(HAVE_THEORA, 1, [Theora support available])
|
|
||||||
else
|
|
||||||
echo Not all theora libraries found.
|
|
||||||
|
|
||||||
# Special note for unintuitive requirement (for color space conversion).
|
|
||||||
if test "$have_libtheora" = "yes" -a "$have_libogg" = "yes"; then
|
|
||||||
echo Ogg Theora support requires ffmpeg.
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_CONDITIONAL(HAVE_THEORA, test "$have_theora" = "yes" )
|
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|||||||
Vendored
-557
@@ -1,557 +0,0 @@
|
|||||||
/********************************************************************
|
|
||||||
* *
|
|
||||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
|
||||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
|
||||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
|
||||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
|
||||||
* *
|
|
||||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
|
||||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
|
||||||
* *
|
|
||||||
********************************************************************
|
|
||||||
|
|
||||||
function:
|
|
||||||
last mod: $Id: codec.h 26239 2007-05-10 01:53:20Z gmaynard $
|
|
||||||
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
/**\mainpage
|
|
||||||
*
|
|
||||||
* \section intro Introduction
|
|
||||||
*
|
|
||||||
* This is the documentation for the <tt>libtheora</tt> C API.
|
|
||||||
* <tt>libtheora</tt> is the reference implementation for
|
|
||||||
* <a href="http://www.theora.org/">Theora</a>, a free video codec.
|
|
||||||
* Theora is derived from On2's VP3 codec with additional features and
|
|
||||||
* integration for Ogg multimedia formats by
|
|
||||||
* <a href="http://www.xiph.org/">the Xiph.Org Foundation</a>.
|
|
||||||
* Complete documentation of the format itself is available in
|
|
||||||
* <a href="http://www.theora.org/doc/Theora_I_spec.pdf">the Theora
|
|
||||||
* specification</a>.
|
|
||||||
*
|
|
||||||
* \subsection Organization
|
|
||||||
*
|
|
||||||
* <tt>libtheora</tt> is actually subdivided into three separate libraries:
|
|
||||||
* - <tt>libtheoraenc</tt>, containing routines exclusive to the encoder.
|
|
||||||
* You must link to this if you use any of the functions listed in
|
|
||||||
* \ref encfuncs.
|
|
||||||
* - <tt>libtheoradec</tt>, containing routines exclusive to the decoder.
|
|
||||||
* You must link to this if you use any of the functions listed in
|
|
||||||
* \ref decfuncs.
|
|
||||||
* - <tt>libtheorabase</tt>, containing routines shared by the encoder and the
|
|
||||||
* decoder.
|
|
||||||
* You must link to this if you use any of the functions in this API, not
|
|
||||||
* not just those listed in \ref basefuncs.*/
|
|
||||||
|
|
||||||
/**\file
|
|
||||||
* The shared <tt>libtheora</tt> C API.*/
|
|
||||||
|
|
||||||
#if !defined(_O_THEORA_CODEC_H_)
|
|
||||||
# define _O_THEORA_CODEC_H_ (1)
|
|
||||||
# include <ogg/ogg.h>
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**\name Error codes*/
|
|
||||||
/*@{*/
|
|
||||||
/**An invalid pointer was provided.*/
|
|
||||||
#define OC_FAULT (-1)
|
|
||||||
/**An invalid argument was provided.*/
|
|
||||||
#define OC_EINVAL (-10)
|
|
||||||
/**The contents of the header were incomplete, invalid, or unexpected.*/
|
|
||||||
#define OC_BADHEADER (-20)
|
|
||||||
/**The header does not belong to a Theora stream.*/
|
|
||||||
#define OC_NOTFORMAT (-21)
|
|
||||||
/**The bitstream version is too high.*/
|
|
||||||
#define OC_VERSION (-22)
|
|
||||||
/**The specified function is not implemented.*/
|
|
||||||
#define OC_IMPL (-23)
|
|
||||||
/**There were errors in the video data packet.*/
|
|
||||||
#define OC_BADPACKET (-24)
|
|
||||||
/*@}*/
|
|
||||||
|
|
||||||
/**The currently defined color space tags.
|
|
||||||
* See <a href="http://www.theora.org/doc/Theora_I_spec.pdf">the Theora
|
|
||||||
* specification</a>, Chapter 4, for exact details on the meaning of each of
|
|
||||||
* these color spaces.*/
|
|
||||||
typedef enum{
|
|
||||||
/**The color space was not specified at the encoder.
|
|
||||||
It may be conveyed by an external means.*/
|
|
||||||
OC_CS_UNSPECIFIED,
|
|
||||||
/**A color space designed for NTSC content.*/
|
|
||||||
OC_CS_ITU_REC_470M,
|
|
||||||
/**A color space designed for PAL/SECAM content.*/
|
|
||||||
OC_CS_ITU_REC_470BG,
|
|
||||||
/**The total number of currently defined color spaces.*/
|
|
||||||
OC_CS_NSPACES
|
|
||||||
}theora_colorspace;
|
|
||||||
|
|
||||||
/**The currently defined pixel format tags.
|
|
||||||
* See <a href="http://www.theora.org/doc/Theora_I_spec.pdf">the Theora
|
|
||||||
* specification</a>, Section 4.4, for details on the precise sample
|
|
||||||
* locations.*/
|
|
||||||
typedef enum{
|
|
||||||
/**Chroma decimation by 2 in both the X and Y directions (4:2:0).*/
|
|
||||||
OC_PF_420,
|
|
||||||
/**Currently reserved.*/
|
|
||||||
OC_PF_RSVD,
|
|
||||||
/**Chroma decimation by 2 in the X direction (4:2:2).*/
|
|
||||||
OC_PF_422,
|
|
||||||
/**No chroma decimation (4:4:4).*/
|
|
||||||
OC_PF_444,
|
|
||||||
/**The total number of currently defined pixel formats.*/
|
|
||||||
OC_PF_NFORMATS
|
|
||||||
}theora_pixel_fmt;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**A buffer for a single color plane in an uncompressed image.
|
|
||||||
* This contains the image data in a left-to-right, top-down format.
|
|
||||||
* Each row of pixels is stored contiguously in memory, but successive rows
|
|
||||||
* need not be.
|
|
||||||
* Use \a ystride to compute the offset of the next row.
|
|
||||||
* The encoder accepts both positive \a ystride values (top-down) and negative
|
|
||||||
* (bottom-up).
|
|
||||||
* The decoder currently always generates images with positive strides.
|
|
||||||
*/
|
|
||||||
typedef struct{
|
|
||||||
/**The width of this plane.*/
|
|
||||||
int width;
|
|
||||||
/**The height of this plane.*/
|
|
||||||
int height;
|
|
||||||
/**The offset in bytes between successive rows.*/
|
|
||||||
int ystride;
|
|
||||||
/**A pointer to the first row.*/
|
|
||||||
unsigned char *data;
|
|
||||||
}theora_img_plane;
|
|
||||||
|
|
||||||
/**A complete image buffer for an uncompressed frame.
|
|
||||||
* The chroma planes may be decimated by a factor of two in either direction,
|
|
||||||
* as indicated by theora_info#pixel_fmt.
|
|
||||||
* The width and height of the Y' plane must be multiples of 16.
|
|
||||||
* They may need to be cropped for display, using the rectangle specified by
|
|
||||||
* theora_info#pic_x, theora_info#pic_y, theora_info#pic_width, and
|
|
||||||
* theora_info#pic_height.
|
|
||||||
* All samples are 8 bits.
|
|
||||||
* \note The term YUV often used to describe a colorspace is ambiguous.
|
|
||||||
* The exact parameters of the RGB to YUV conversion process aside, in many
|
|
||||||
* contexts the U and V channels actually have opposite meanings.
|
|
||||||
* To avoid this confusion, we are explicit: the name of the color channels is
|
|
||||||
* Y'CbCr, and they appear in that order, always.
|
|
||||||
* The prime symbol denotes that the Y channel is non-linear.
|
|
||||||
* Cb and Cr stand for "Chroma blue" and "Chroma red" respectively.*/
|
|
||||||
typedef theora_img_plane theora_ycbcr_buffer[3];
|
|
||||||
|
|
||||||
/**Theora bitstream information.
|
|
||||||
* This contains the basic playback parameters for a stream, and corresponds to
|
|
||||||
* the initial 'info' header packet.
|
|
||||||
* To initialize an encoder, the application fills in this structure and
|
|
||||||
* passes it to theora_encode_alloc().
|
|
||||||
* A default encoding mode is chosen based on the values of the #quality and
|
|
||||||
* #target_bitrate fields.
|
|
||||||
* On decode, it is filled in by theora_decode_headerin(), and then passed to
|
|
||||||
* theora_decode_alloc().
|
|
||||||
*
|
|
||||||
* Encoded Theora frames must be a multiple of 16 in size;
|
|
||||||
* this is what the #frame_width and #frame_height members represent.
|
|
||||||
* To handle arbitrary picture sizes, a crop rectangle is specified in the
|
|
||||||
* #pic_x, #pic_y, #pic_width and #pic_height members.
|
|
||||||
*
|
|
||||||
* All frame buffers contain pointers to the full, padded frame.
|
|
||||||
* However, the current encoder <em>will not</em> reference pixels outside of
|
|
||||||
* the cropped picture region, and the application does not need to fill them
|
|
||||||
* in.
|
|
||||||
* The decoder <em>will</em> allocate storage for a full frame, but the
|
|
||||||
* application <em>should not</em> rely on the padding containing sensible
|
|
||||||
* data.
|
|
||||||
*
|
|
||||||
* It is also generally recommended that the offsets and sizes should still be
|
|
||||||
* multiples of 2 to avoid chroma sampling shifts.
|
|
||||||
* See <a href="http://www.theora.org/doc/Theora_I_spec.pdf">the Theora
|
|
||||||
* specification</a>, Section 4.4, for more details.
|
|
||||||
*
|
|
||||||
* Frame rate, in frames per second, is stored as a rational fraction, as is
|
|
||||||
* the pixel aspect ratio.
|
|
||||||
* Note that this refers to the aspect ratio of the individual pixels, not of
|
|
||||||
* the overall frame itself.
|
|
||||||
* The frame aspect ratio can be computed from pixel aspect ratio using the
|
|
||||||
* image dimensions.
|
|
||||||
*/
|
|
||||||
typedef struct{
|
|
||||||
/**\name Theora version
|
|
||||||
* Bitstream version information.*/
|
|
||||||
/*@{*/
|
|
||||||
unsigned char version_major;
|
|
||||||
unsigned char version_minor;
|
|
||||||
unsigned char version_subminor;
|
|
||||||
/*@}*/
|
|
||||||
/**The encoded frame width.
|
|
||||||
* This must be a multiple of 16, and less than 1048576.*/
|
|
||||||
ogg_uint32_t frame_width;
|
|
||||||
/**The encoded frame height.
|
|
||||||
* This must be a multiple of 16, and less than 1048576.*/
|
|
||||||
ogg_uint32_t frame_height;
|
|
||||||
/**The displayed picture width.
|
|
||||||
* This must be no larger than width.*/
|
|
||||||
ogg_uint32_t pic_width;
|
|
||||||
/**The displayed picture height.
|
|
||||||
* This must be no larger than height.*/
|
|
||||||
ogg_uint32_t pic_height;
|
|
||||||
/**The X offset of the displayed picture.
|
|
||||||
* This must be no larger than #frame_width-#pic_width or 255, whichever is
|
|
||||||
* smaller.*/
|
|
||||||
ogg_uint32_t pic_x;
|
|
||||||
/**The Y offset of the displayed picture.
|
|
||||||
* This must be no larger than #frame_height-#pic_height, and
|
|
||||||
* #frame_height-#pic_height-#pic_y must be no larger than 255.
|
|
||||||
* This offset is specified from the top of the image, as this API uses the
|
|
||||||
* standard graphics left-handed coordinate system.*/
|
|
||||||
ogg_uint32_t pic_y;
|
|
||||||
/**\name Frame rate
|
|
||||||
* The frame rate, as a fraction.
|
|
||||||
* If either is 0, the frame rate is undefined.*/
|
|
||||||
/*@{*/
|
|
||||||
ogg_uint32_t fps_numerator;
|
|
||||||
ogg_uint32_t fps_denominator;
|
|
||||||
/*@}*/
|
|
||||||
/**\name Aspect ratio
|
|
||||||
* The aspect ratio of the pixels.
|
|
||||||
* If either value is zero, the aspect ratio is undefined.
|
|
||||||
* If not specified by any external means, 1:1 should be assumed.*/
|
|
||||||
/*@{*/
|
|
||||||
ogg_uint32_t aspect_numerator;
|
|
||||||
ogg_uint32_t aspect_denominator;
|
|
||||||
/*@}*/
|
|
||||||
/**The color space.*/
|
|
||||||
theora_colorspace colorspace;
|
|
||||||
/**The pixel format.*/
|
|
||||||
theora_pixel_fmt pixel_fmt;
|
|
||||||
/**The target bit-rate in bits per second.
|
|
||||||
If initializing an encoder with this struct, set this field to a non-zero
|
|
||||||
value to activate CBR encoding by default.*/
|
|
||||||
/*TODO: Current encoder does not support CBR mode, or anything like it.
|
|
||||||
We also don't really know what nominal rate each quality level
|
|
||||||
corresponds to yet.*/
|
|
||||||
int target_bitrate;
|
|
||||||
/**The target quality level.
|
|
||||||
Valid values range from 0 to 63, inclusive, with higher values giving
|
|
||||||
higher quality.
|
|
||||||
If initializing an encoder with this struct, and #target_bitrate is set
|
|
||||||
to zero, VBR encoding at this quality will be activated by default.*/
|
|
||||||
/*Currently this is set so that a qi of 0 corresponds to distortions of 24
|
|
||||||
times the JND, and each increase by 16 halves that value.
|
|
||||||
This gives us fine discrimination at low qualities, yet effective rate
|
|
||||||
control at high qualities.
|
|
||||||
The qi value 63 is special, however.
|
|
||||||
For this, the highest quality, we use one half of a JND for our threshold.
|
|
||||||
Due to the lower bounds placed on allowable quantizers in Theora, we will
|
|
||||||
not actually be able to achieve quality this good, but this should
|
|
||||||
provide as close to visually lossless quality as Theora is capable of.
|
|
||||||
We could lift the quantizer restrictions without breaking VP3.1
|
|
||||||
compatibility, but this would result in quantized coefficients that are
|
|
||||||
too large for the current bitstream to be able to store.
|
|
||||||
We'd have to redesign the token syntax to store these large coefficients,
|
|
||||||
which would make transcoding complex.*/
|
|
||||||
int quality;
|
|
||||||
/**The amount to shift to extract the last keyframe number from the granule
|
|
||||||
* position.
|
|
||||||
* This can be at most 31.
|
|
||||||
* theora_info_init() will set this to a default value (currently <tt>6</tt>,
|
|
||||||
* which is good for streaming applications), but you can set it to 0 to
|
|
||||||
* make every frame a keyframe.
|
|
||||||
* The maximum distance between key frames is
|
|
||||||
* <tt>1<<#keyframe_granule_shift</tt>.
|
|
||||||
* The keyframe frequency can be more finely controlled with
|
|
||||||
* #OC_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE, which can also be adjusted
|
|
||||||
* during encoding (for example, to force the next frame to be a keyframe),
|
|
||||||
* but it cannot be set larger than the amount permitted by this field after
|
|
||||||
* the headers have been output.*/
|
|
||||||
int keyframe_granule_shift;
|
|
||||||
}theora_info;
|
|
||||||
|
|
||||||
/**The comment information.
|
|
||||||
*
|
|
||||||
* This structure holds the in-stream metadata corresponding to
|
|
||||||
* the 'comment' header packet.
|
|
||||||
* The comment header is meant to be used much like someone jotting a quick
|
|
||||||
* note on the label of a video.
|
|
||||||
* It should be a short, to the point text note that can be more than a couple
|
|
||||||
* words, but not more than a short paragraph.
|
|
||||||
*
|
|
||||||
* The metadata is stored as a series of (tag, value) pairs, in
|
|
||||||
* length-encoded string vectors.
|
|
||||||
* The first occurrence of the '=' character delimits the tag and value.
|
|
||||||
* A particular tag may occur more than once, and order is significant.
|
|
||||||
* The character set encoding for the strings is always UTF-8, but the tag
|
|
||||||
* names are limited to ASCII, and treated as case-insensitive.
|
|
||||||
* See <a href="http://www.theora.org/doc/Theora_I_spec.pdf">the Theora
|
|
||||||
* specification</a>, Section 6.3.3 for details.
|
|
||||||
*
|
|
||||||
* In filling in this structure, theora_decode_header() will null-terminate
|
|
||||||
* the user_comment strings for safety.
|
|
||||||
* However, the bitstream format itself treats them as 8-bit clean vectors,
|
|
||||||
* possibly containing null characters, and so the length array should be
|
|
||||||
* treated as their authoritative length.
|
|
||||||
*/
|
|
||||||
typedef struct theora_comment{
|
|
||||||
/**The array of comment string vectors.*/
|
|
||||||
char **user_comments;
|
|
||||||
/**An array of the corresponding length of each vector, in bytes.*/
|
|
||||||
int *comment_lengths;
|
|
||||||
/**The total number of comment strings.*/
|
|
||||||
int comments;
|
|
||||||
/**The null-terminated vendor string.
|
|
||||||
This identifies the software used to encode the stream.*/
|
|
||||||
char *vendor;
|
|
||||||
}theora_comment;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**A single base matrix.*/
|
|
||||||
typedef unsigned char theora_quant_base[64];
|
|
||||||
|
|
||||||
/**A set of \a qi ranges.*/
|
|
||||||
typedef struct{
|
|
||||||
/**The number of ranges in the set.*/
|
|
||||||
int nranges;
|
|
||||||
/**The size of each of the #nranges ranges.
|
|
||||||
These must sum to 63.*/
|
|
||||||
const int *sizes;
|
|
||||||
/**#nranges <tt>+1</tt> base matrices.
|
|
||||||
Matrices \a i and <tt>i+1</tt> form the endpoints of range \a i.*/
|
|
||||||
const theora_quant_base *base_matrices;
|
|
||||||
}theora_quant_ranges;
|
|
||||||
|
|
||||||
/**A complete set of quantization parameters.
|
|
||||||
The quantizer for each coefficient is calculated as:
|
|
||||||
\code
|
|
||||||
Q=MAX(MIN(qmin[qti][ci!=0],scale[ci!=0][qi]*base[qti][pli][qi][ci]/100),
|
|
||||||
1024).
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
\a qti is the quantization type index: 0 for intra, 1 for inter.
|
|
||||||
<tt>ci!=0</tt> is 0 for the DC coefficient and 1 for the AC coefficient.
|
|
||||||
\a qi is the quality index, ranging between 0 (low quality) and 63 (high
|
|
||||||
quality).
|
|
||||||
\a pli is the color plane index: 0 for Y', 1 for Cb, 2 for Cr.
|
|
||||||
\a ci is the DCT coefficient index.
|
|
||||||
Coefficient indices correspond to the normal 2D DCT block
|
|
||||||
ordering--row-major with low frequencies first--\em not zig-zag order.
|
|
||||||
|
|
||||||
Minimum quantizers are constant, and are given by:
|
|
||||||
\code
|
|
||||||
qmin[2][2]={{4,2},{8,4}}.
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
Parameters that can be stored in the bitstream are as follows:
|
|
||||||
- The two scale matrices ac_scale and dc_scale.
|
|
||||||
\code
|
|
||||||
scale[2][64]={dc_scale,ac_scale}.
|
|
||||||
\endcode
|
|
||||||
- The base matrices for each \a qi, \a qti and \a pli (up to 384 in all).
|
|
||||||
In order to avoid storing a full 384 base matrices, only a sparse set of
|
|
||||||
matrices is stored, and the rest are linearly interpolated.
|
|
||||||
This is done as follows.
|
|
||||||
For each \a qti and \a pli, a series of \a n \a qi ranges is defined.
|
|
||||||
The size of each \a qi range can vary arbitrarily, but they must sum to
|
|
||||||
63.
|
|
||||||
Then, <tt>n+1</tt> matrices are specified, one for each endpoint of the
|
|
||||||
ranges.
|
|
||||||
For interpolation purposes, each range's endpoints are the first \a qi
|
|
||||||
value it contains and one past the last \a qi value it contains.
|
|
||||||
Fractional values are rounded to the nearest integer, with ties rounded
|
|
||||||
away from zero.
|
|
||||||
|
|
||||||
Base matrices are stored by reference, so if the same matrices are used
|
|
||||||
multiple times, they will only appear once in the bitstream.
|
|
||||||
The bitstream is also capable of omitting an entire set of ranges and
|
|
||||||
its associated matrices if they are the same as either the previous
|
|
||||||
set (indexed in row-major order) or if the inter set is the same as the
|
|
||||||
intra set.
|
|
||||||
|
|
||||||
- Loop filter limit values.
|
|
||||||
The same limits are used for the loop filter in all color planes, despite
|
|
||||||
potentially differing levels of quantization in each.
|
|
||||||
|
|
||||||
For the current encoder, <tt>scale[ci!=0][qi]</tt> must be no greater
|
|
||||||
than <tt>scale[ci!=0][qi-1]</tt> and <tt>base[qti][pli][qi][ci]</tt> must
|
|
||||||
be no greater than <tt>base[qti][pli][qi-1][ci]</tt>.
|
|
||||||
These two conditions ensure that the actual quantizer for a given \a qti,
|
|
||||||
\a pli, and \a ci does not increase as \a qi increases.
|
|
||||||
This is not required by the decoder.*/
|
|
||||||
typedef struct{
|
|
||||||
/**The DC scaling factors.*/
|
|
||||||
ogg_uint16_t dc_scale[64];
|
|
||||||
/**The AC scaling factors.*/
|
|
||||||
ogg_uint16_t ac_scale[64];
|
|
||||||
/**The loop filter limit values.*/
|
|
||||||
unsigned char loop_filter_limits[64];
|
|
||||||
/**The \a qi ranges for each \a ci and \a pli.*/
|
|
||||||
theora_quant_ranges qi_ranges[2][3];
|
|
||||||
}theora_quant_info;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**The number of Huffman tables used by Theora.*/
|
|
||||||
#define OC_NHUFFMAN_TABLES (80)
|
|
||||||
/**The number of DCT token values in each table.*/
|
|
||||||
#define OC_NDCT_TOKENS (32)
|
|
||||||
|
|
||||||
/**A Huffman code for a Theora DCT token.
|
|
||||||
* Each set of Huffman codes in a given table must form a complete, prefix-free
|
|
||||||
* code.
|
|
||||||
* There is no requirement that all the tokens in a table have a valid code,
|
|
||||||
* but the current encoder is not optimized to take advantage of this.
|
|
||||||
* If there is not at least one table with a code for every token in each of
|
|
||||||
* the five groups of 16 tables, then the encoder may fail to encode certain
|
|
||||||
* frames.
|
|
||||||
* The complete table in the first group of 16 does not have to be in the same
|
|
||||||
* place as the complete table in the other groups, but the complete tables in
|
|
||||||
* the remaining four groups must all be in the same place.*/
|
|
||||||
typedef struct{
|
|
||||||
/**The bit pattern for the code, with the LSbit of the pattern aligned in
|
|
||||||
* the LSbit of the word.*/
|
|
||||||
ogg_uint32_t pattern;
|
|
||||||
/**The number of bits in the code.
|
|
||||||
* This must be between 0 and 32, inclusive.*/
|
|
||||||
int nbits;
|
|
||||||
}theora_huff_code;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**\defgroup basefuncs Functions Shared by Encode and Decode*/
|
|
||||||
/*@{*/
|
|
||||||
/**\name Basic shared functions*/
|
|
||||||
/*@{*/
|
|
||||||
/**Retrieves a human-readable string to identify the library vendor and
|
|
||||||
* version.
|
|
||||||
* \return the version string.*/
|
|
||||||
extern const char *theora_version_string(void);
|
|
||||||
/**Retrieves the library version number.
|
|
||||||
* This is the highest bitstream version that the encoder library will produce,
|
|
||||||
* or that the decoder library can decode.
|
|
||||||
* This number is composed of a 16-bit major version, 8-bit minor version
|
|
||||||
* and 8 bit sub-version, composed as follows:
|
|
||||||
* \code
|
|
||||||
* (VERSION_MAJOR<<16)+(VERSION_MINOR<<8)+(VERSION_SUBMINOR)
|
|
||||||
* \endcode
|
|
||||||
* \return the version number.*/
|
|
||||||
extern ogg_uint32_t theora_version_number(void);
|
|
||||||
/**Converts a granule position to an absolute frame number.
|
|
||||||
* The granule position is interpreted in the context of a given
|
|
||||||
* #theora_enc_ctx or #theora_dec_ctx handle (either will suffice).
|
|
||||||
* \param _encdec A previously allocated #theora_enc_ctx or #theora_dec_ctx
|
|
||||||
* handle.
|
|
||||||
* \param _granpos The granule position to convert.
|
|
||||||
* \returns The absolute frame number corresponding to \a _granpos.
|
|
||||||
* \retval -1 The given granule position was invalid (i.e. negative).*/
|
|
||||||
extern ogg_int64_t theora_granule_frame(void *_encdec,ogg_int64_t _granpos);
|
|
||||||
/**Converts a granule position to an absolute time in seconds.
|
|
||||||
* The granule position is interpreted in the context of a given
|
|
||||||
* #theora_enc_ctx or #theora_dec_ctx handle (either will suffice).
|
|
||||||
* \param _encdec A previously allocated #theora_enc_ctx or #theora_dec_ctx
|
|
||||||
* handle.
|
|
||||||
* \param _granpos The granule position to convert.
|
|
||||||
* \return The absolute time in seconds corresponding to \a _granpos.
|
|
||||||
* \retval -1 The given granule position was invalid (i.e. negative).*/
|
|
||||||
extern double theora_granule_time(void *_encdec,ogg_int64_t _granpos);
|
|
||||||
/**Determines whether a Theora packet is a header or not.
|
|
||||||
* This function does no verification beyond checking the packet type bit, so
|
|
||||||
* it should not be used for bitstream identification; use
|
|
||||||
* theora_decode_headerin() for that.
|
|
||||||
* \param _op An <tt>ogg_packet</tt> containing encoded Theora data.
|
|
||||||
* \retval 1 The packet is a header packet
|
|
||||||
* \retval 0 The packet is a video data packet.*/
|
|
||||||
extern int theora_packet_isheader(ogg_packet *_op);
|
|
||||||
/**Determines whether a theora packet is a key frame or not.
|
|
||||||
* This function does no verification beyond checking the packet type and
|
|
||||||
* key frame bits, so it should not be used for bitstream identification; use
|
|
||||||
* theora_decode_headerin() for that.
|
|
||||||
* \param _op An <tt>ogg_packet</tt> containing encoded Theora data.
|
|
||||||
* \retval 1 The packet contains a key frame.
|
|
||||||
* \retval 0 The packet contains a delta frame.
|
|
||||||
* \retval -1 The packet is not a video data packet.*/
|
|
||||||
extern int theora_packet_iskeyframe(ogg_packet *_op);
|
|
||||||
/*@}*/
|
|
||||||
|
|
||||||
|
|
||||||
/**\name Functions for manipulating header data*/
|
|
||||||
/*@{*/
|
|
||||||
/**Initializes a theora_info structure.
|
|
||||||
* This should be called on a freshly allocated #theora_info structure before
|
|
||||||
* attempting to use it.
|
|
||||||
* \param _info The #theora_info struct to initialize.*/
|
|
||||||
extern void theora_info_init(theora_info *_info);
|
|
||||||
/**Clears a #theora_info structure.
|
|
||||||
* This should be called on a #theora_info structure after it is no longer
|
|
||||||
* needed.
|
|
||||||
* \param _info The #theora_info struct to clear.*/
|
|
||||||
extern void theora_info_clear(theora_info *_info);
|
|
||||||
|
|
||||||
/**Initialize a #theora_comment structure.
|
|
||||||
* This should be called on a freshly allocated #theora_comment structure
|
|
||||||
* before attempting to use it.
|
|
||||||
* \param _tc The #theora_comment struct to initialize.*/
|
|
||||||
extern void theora_comment_init(theora_comment *_tc);
|
|
||||||
/**Add a comment to an initialized #theora_comment structure.
|
|
||||||
* \note Neither theora_comment_add() nor theora_comment_add_tag() support
|
|
||||||
* comments containing null values, although the bitstream format does
|
|
||||||
* support them.
|
|
||||||
* To add such comments you will need to manipulate the #theora_comment
|
|
||||||
* structure directly.
|
|
||||||
* \param _tc The #theora_comment struct to add the comment to.
|
|
||||||
* \param _comment Must be a null-terminated UTF-8 string containing the
|
|
||||||
* comment in "TAG=the value" form.*/
|
|
||||||
extern void theora_comment_add(theora_comment *_tc, char *_comment);
|
|
||||||
/**Add a comment to an initialized #theora_comment structure.
|
|
||||||
* \note Neither theora_comment_add() nor theora_comment_add_tag() support
|
|
||||||
* comments containing null values, although the bitstream format does
|
|
||||||
* support them.
|
|
||||||
* To add such comments you will need to manipulate the #theora_comment
|
|
||||||
* structure directly.
|
|
||||||
* \param _tc The #theora_comment struct to add the comment to.
|
|
||||||
* \param _tag A null-terminated string containing the tag associated with
|
|
||||||
* the comment.
|
|
||||||
* \param _val The corresponding value as a null-terminated string.*/
|
|
||||||
extern void theora_comment_add_tag(theora_comment *_tc,char *_tag,char *_val);
|
|
||||||
/**Look up a comment value by its tag.
|
|
||||||
* \param _tc An initialized #theora_comment structure.
|
|
||||||
* \param _tag The tag to look up.
|
|
||||||
* \param _count The instance of the tag.
|
|
||||||
* The same tag can appear multiple times, each with a distinct
|
|
||||||
* value, so an index is required to retrieve them all.
|
|
||||||
* The order these values appear in is significant and should be
|
|
||||||
* preserved.
|
|
||||||
* Use theora_comment_query_count() to get the legal range for
|
|
||||||
* the \a _count parameter.
|
|
||||||
* \return A pointer to the queried tag's value.
|
|
||||||
* \retval NULL If no matching tag is found.*/
|
|
||||||
extern char *theora_comment_query(theora_comment *_tc,char *_tag,int _count);
|
|
||||||
/**Look up the number of instances of a tag.
|
|
||||||
* Call this first when querying for a specific tag and then iterate over the
|
|
||||||
* number of instances with separate calls to theora_comment_query() to
|
|
||||||
* retrieve all instances in order.
|
|
||||||
* \param _tc An initialized #theora_comment structure.
|
|
||||||
* \param _tag The tag to look up.
|
|
||||||
* \return The number on instances of this particular tag.*/
|
|
||||||
extern int theora_comment_query_count(theora_comment *_tc,char *_tag);
|
|
||||||
/**Clears a #theora_comment structure.
|
|
||||||
* This should be called on a #theora_comment structure after it is no longer
|
|
||||||
* needed.
|
|
||||||
* It will free all memory used by the structure members.
|
|
||||||
* \param _tc The #theora_comment struct to clear.*/
|
|
||||||
extern void theora_comment_clear(theora_comment *_tc);
|
|
||||||
/*@}*/
|
|
||||||
/*@}*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Vendored
-534
@@ -1,534 +0,0 @@
|
|||||||
/********************************************************************
|
|
||||||
* *
|
|
||||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
|
||||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
|
||||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
|
||||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
|
||||||
* *
|
|
||||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
|
||||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
|
||||||
* *
|
|
||||||
********************************************************************
|
|
||||||
|
|
||||||
function:
|
|
||||||
last mod: $Id: theora.h 18100 2005-10-20 10:59:59Z gmaynard $
|
|
||||||
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
#ifndef _O_THEORA_H_
|
|
||||||
#define _O_THEORA_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
#ifndef LIBOGG2
|
|
||||||
#include <../extern/vorbis/ogg/ogg.h>
|
|
||||||
#else
|
|
||||||
#include <../extern/vorbis/ogg2/ogg.h>
|
|
||||||
/* This is temporary until libogg2 is more complete */
|
|
||||||
ogg_buffer_state *ogg_buffer_create(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** \mainpage
|
|
||||||
*
|
|
||||||
* \section intro Introduction
|
|
||||||
*
|
|
||||||
* This is the documentation for the libtheora C API.
|
|
||||||
* libtheora is the reference implementation for
|
|
||||||
* <a href="http://www.theora.org/">Theora</a>, a free video codec.
|
|
||||||
* Theora is derived from On2's VP3 codec with improved integration for
|
|
||||||
* Ogg multimedia formats by <a href="http://www.xiph.org/">Xiph.Org</a>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* The libtheora C API.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A YUV buffer for passing uncompressed frames to and from the codec.
|
|
||||||
* This holds a Y'CbCr frame in planar format. The CbCr planes can be
|
|
||||||
* subsampled and have their own separate dimensions and row stride
|
|
||||||
* offsets. Note that the strides may be negative in some
|
|
||||||
* configurations. For theora the width and height of the largest plane
|
|
||||||
* must be a multiple of 16. The actual meaningful picture size and
|
|
||||||
* offset are stored in the theora_info structure; frames returned by
|
|
||||||
* the decoder may need to be cropped for display.
|
|
||||||
* All samples are 8 bits.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
int y_width; /**< Width of the Y' luminance plane */
|
|
||||||
int y_height; /**< Height of the luminance plane */
|
|
||||||
int y_stride; /**< Offset in bytes between successive rows */
|
|
||||||
|
|
||||||
int uv_width; /**< Height of the Cb and Cr chroma planes */
|
|
||||||
int uv_height; /**< Width of the chroma planes */
|
|
||||||
int uv_stride; /**< Offset between successive chroma rows */
|
|
||||||
unsigned char *y; /**< Pointer to start of luminance data */
|
|
||||||
unsigned char *u; /**< Pointer to start of Cb data */
|
|
||||||
unsigned char *v; /**< Pointer to start of Cr data */
|
|
||||||
|
|
||||||
} yuv_buffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Colorspace.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
OC_CS_UNSPECIFIED, /**< The colorspace is unknown or unspecified */
|
|
||||||
OC_CS_ITU_REC_470M, /**< This is the best option for 'NTSC' content */
|
|
||||||
OC_CS_ITU_REC_470BG, /**< This is the best option for 'PAL' content */
|
|
||||||
OC_CS_NSPACES /**< This marks the end of the defined colorspaces */
|
|
||||||
} theora_colorspace;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Chroma subsampling
|
|
||||||
*
|
|
||||||
* These enumerate the available chroma subsampling options supported
|
|
||||||
* by the theora format. See Section 4.4 of the specification for
|
|
||||||
* exact definitions.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
OC_PF_420, /**< Chroma subsampling by 2 in each direction (4:2:0) */
|
|
||||||
OC_PF_RSVD, /**< Reserved value */
|
|
||||||
OC_PF_422, /**< Horizonatal chroma subsampling by 2 (4:2:2) */
|
|
||||||
OC_PF_444, /**< No chroma subsampling at all (4:4:4) */
|
|
||||||
} theora_pixelformat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Theora bitstream info.
|
|
||||||
* Contains the basic playback parameters for a stream,
|
|
||||||
* corresponds to the initial 'info' header packet.
|
|
||||||
*
|
|
||||||
* Encoded theora frames must be a multiple of 16 is size;
|
|
||||||
* this is what the width and height members represent. To
|
|
||||||
* handle other sizes, a crop rectangle is specified in
|
|
||||||
* frame_height and frame_width, offset_x and offset_y. The
|
|
||||||
* offset and size should still be a power of 2 to avoid
|
|
||||||
* chroma sampling shifts.
|
|
||||||
*
|
|
||||||
* Frame rate, in frames per second is stored as a rational
|
|
||||||
* fraction. So is the aspect ratio. Note that this refers
|
|
||||||
* to the aspect ratio of the frame pixels, not of the
|
|
||||||
* overall frame itself.
|
|
||||||
*
|
|
||||||
* see the example code for use of the other parameters and
|
|
||||||
* good default settings for the encoder parameters.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
ogg_uint32_t width;
|
|
||||||
ogg_uint32_t height;
|
|
||||||
ogg_uint32_t frame_width;
|
|
||||||
ogg_uint32_t frame_height;
|
|
||||||
ogg_uint32_t offset_x;
|
|
||||||
ogg_uint32_t offset_y;
|
|
||||||
ogg_uint32_t fps_numerator;
|
|
||||||
ogg_uint32_t fps_denominator;
|
|
||||||
ogg_uint32_t aspect_numerator;
|
|
||||||
ogg_uint32_t aspect_denominator;
|
|
||||||
theora_colorspace colorspace;
|
|
||||||
int target_bitrate;
|
|
||||||
int quality; /**< Nominal quality setting, 0-63 */
|
|
||||||
int quick_p; /**< Quick encode/decode */
|
|
||||||
|
|
||||||
/* decode only */
|
|
||||||
unsigned char version_major;
|
|
||||||
unsigned char version_minor;
|
|
||||||
unsigned char version_subminor;
|
|
||||||
|
|
||||||
void *codec_setup;
|
|
||||||
|
|
||||||
/* encode only */
|
|
||||||
int dropframes_p;
|
|
||||||
int keyframe_auto_p;
|
|
||||||
ogg_uint32_t keyframe_frequency;
|
|
||||||
ogg_uint32_t keyframe_frequency_force; /* also used for decode init to
|
|
||||||
get granpos shift correct */
|
|
||||||
ogg_uint32_t keyframe_data_target_bitrate;
|
|
||||||
ogg_int32_t keyframe_auto_threshold;
|
|
||||||
ogg_uint32_t keyframe_mindistance;
|
|
||||||
ogg_int32_t noise_sensitivity;
|
|
||||||
ogg_int32_t sharpness;
|
|
||||||
|
|
||||||
theora_pixelformat pixelformat;
|
|
||||||
|
|
||||||
} theora_info;
|
|
||||||
|
|
||||||
/** Codec internal state and context.
|
|
||||||
*/
|
|
||||||
typedef struct{
|
|
||||||
theora_info *i;
|
|
||||||
ogg_int64_t granulepos;
|
|
||||||
|
|
||||||
void *internal_encode;
|
|
||||||
void *internal_decode;
|
|
||||||
|
|
||||||
} theora_state;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Comment header metadata.
|
|
||||||
*
|
|
||||||
* This structure holds the in-stream metadata corresponding to
|
|
||||||
* the 'comment' header packet.
|
|
||||||
*
|
|
||||||
* Meta data is stored as a series of (tag, value) pairs, in
|
|
||||||
* length-encoded string vectors. The first occurence of the
|
|
||||||
* '=' character delimits the tag and value. A particular tag
|
|
||||||
* may occur more than once. The character set encoding for
|
|
||||||
* the strings is always utf-8, but the tag names are limited
|
|
||||||
* to case-insensitive ascii. See the spec for details.
|
|
||||||
*
|
|
||||||
* In filling in this structure, theora_decode_header() will
|
|
||||||
* null-terminate the user_comment strings for safety. However,
|
|
||||||
* the bitstream format itself treats them as 8-bit clean,
|
|
||||||
* and so the length array should be treated as authoritative
|
|
||||||
* for their length.
|
|
||||||
*/
|
|
||||||
typedef struct theora_comment{
|
|
||||||
char **user_comments; /**< An array of comment string vectors */
|
|
||||||
int *comment_lengths; /**< An array of corresponding string vector lengths in bytes */
|
|
||||||
int comments; /**< The total number of comment string vectors */
|
|
||||||
char *vendor; /**< The vendor string identifying the encoder, null terminated */
|
|
||||||
|
|
||||||
} theora_comment;
|
|
||||||
|
|
||||||
#define OC_FAULT -1 /**< General failure */
|
|
||||||
#define OC_EINVAL -10 /**< Library encountered invalid internal data */
|
|
||||||
#define OC_DISABLED -11 /**< Requested action is disabled */
|
|
||||||
#define OC_BADHEADER -20 /**< Header packet was corrupt/invalid */
|
|
||||||
#define OC_NOTFORMAT -21 /**< Packet is not a theora packet */
|
|
||||||
#define OC_VERSION -22 /**< Bitstream version is not handled */
|
|
||||||
#define OC_IMPL -23 /**< Feature or action not implemented */
|
|
||||||
#define OC_BADPACKET -24 /**< Packet is corrupt */
|
|
||||||
#define OC_NEWPACKET -25 /**< Packet is an (ignorable) unhandled extension */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a human-readable string to identify the encoder vendor and version.
|
|
||||||
* \returns A version string.
|
|
||||||
*/
|
|
||||||
extern const char *theora_version_string(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a 32-bit version number.
|
|
||||||
* This number is composed of a 16-bit major version, 8-bit minor version
|
|
||||||
* and 8 bit sub-version, composed as follows:
|
|
||||||
<pre>
|
|
||||||
(VERSION_MAJOR<<16) + (VERSION_MINOR<<8) + (VERSION_SUB)
|
|
||||||
</pre>
|
|
||||||
* \returns The version number.
|
|
||||||
*/
|
|
||||||
extern ogg_uint32_t theora_version_number(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the theora encoder.
|
|
||||||
* \param th The theora_state handle to initialize for encoding.
|
|
||||||
* \param ti A theora_info struct filled with the desired encoding parameters.
|
|
||||||
* \retval 0 Success
|
|
||||||
*/
|
|
||||||
extern int theora_encode_init(theora_state *th, theora_info *ti);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submit a YUV buffer to the theora encoder.
|
|
||||||
* \param t A theora_state handle previously initialized for encoding.
|
|
||||||
* \param yuv A buffer of YUV data to encode.
|
|
||||||
* \retval OC_EINVAL Encoder is not ready, or is finished.
|
|
||||||
* \retval -1 The size of the given frame differs from those previously input
|
|
||||||
* \retval 0 Success
|
|
||||||
*/
|
|
||||||
extern int theora_encode_YUVin(theora_state *t, yuv_buffer *yuv);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request the next packet of encoded video.
|
|
||||||
* The encoded data is placed in a user-provided ogg_packet structure.
|
|
||||||
* \param t A theora_state handle previously initialized for encoding.
|
|
||||||
* \param last_p whether this is the last packet the encoder should produce.
|
|
||||||
* \param op An ogg_packet structure to fill. libtheora will set all
|
|
||||||
* elements of this structure, including a pointer to encoded
|
|
||||||
* data. The memory for the encoded data is owned by libtheora.
|
|
||||||
* \retval 0 No internal storage exists OR no packet is ready
|
|
||||||
* \retval -1 The encoding process has completed
|
|
||||||
* \retval 1 Success
|
|
||||||
*/
|
|
||||||
extern int theora_encode_packetout( theora_state *t, int last_p,
|
|
||||||
ogg_packet *op);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request a packet containing the initial header.
|
|
||||||
* A pointer to the header data is placed in a user-provided ogg_packet
|
|
||||||
* structure.
|
|
||||||
* \param t A theora_state handle previously initialized for encoding.
|
|
||||||
* \param op An ogg_packet structure to fill. libtheora will set all
|
|
||||||
* elements of this structure, including a pointer to the header
|
|
||||||
* data. The memory for the header data is owned by libtheora.
|
|
||||||
* \retval 0 Success
|
|
||||||
*/
|
|
||||||
extern int theora_encode_header(theora_state *t, ogg_packet *op);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request a comment header packet from provided metadata.
|
|
||||||
* A pointer to the comment data is placed in a user-provided ogg_packet
|
|
||||||
* structure.
|
|
||||||
* \param tc A theora_comment structure filled with the desired metadata
|
|
||||||
* \param op An ogg_packet structure to fill. libtheora will set all
|
|
||||||
* elements of this structure, including a pointer to the encoded
|
|
||||||
* comment data. The memory for the comment data is owned by
|
|
||||||
* libtheora.
|
|
||||||
* \retval 0 Success
|
|
||||||
*/
|
|
||||||
extern int theora_encode_comment(theora_comment *tc, ogg_packet *op);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request a packet containing the codebook tables for the stream.
|
|
||||||
* A pointer to the codebook data is placed in a user-provided ogg_packet
|
|
||||||
* structure.
|
|
||||||
* \param t A theora_state handle previously initialized for encoding.
|
|
||||||
* \param op An ogg_packet structure to fill. libtheora will set all
|
|
||||||
* elements of this structure, including a pointer to the codebook
|
|
||||||
* data. The memory for the header data is owned by libtheora.
|
|
||||||
* \retval 0 Success
|
|
||||||
*/
|
|
||||||
extern int theora_encode_tables(theora_state *t, ogg_packet *op);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode an Ogg packet, with the expectation that the packet contains
|
|
||||||
* an initial header, comment data or codebook tables.
|
|
||||||
*
|
|
||||||
* \param ci A theora_info structure to fill. This must have been previously
|
|
||||||
* initialized with theora_info_init(). If \a op contains an initial
|
|
||||||
* header, theora_decode_header() will fill \a ci with the
|
|
||||||
* parsed header values. If \a op contains codebook tables,
|
|
||||||
* theora_decode_header() will parse these and attach an internal
|
|
||||||
* representation to \a ci->codec_setup.
|
|
||||||
* \param cc A theora_comment structure to fill. If \a op contains comment
|
|
||||||
* data, theora_decode_header() will fill \a cc with the parsed
|
|
||||||
* comments.
|
|
||||||
* \param op An ogg_packet structure which you expect contains an initial
|
|
||||||
* header, comment data or codebook tables.
|
|
||||||
*
|
|
||||||
* \retval OC_BADHEADER \a op is NULL; OR the first byte of \a op->packet
|
|
||||||
* has the signature of an initial packet, but op is
|
|
||||||
* not a b_o_s packet; OR this packet has the signature
|
|
||||||
* of an initial header packet, but an initial header
|
|
||||||
* packet has already been seen; OR this packet has the
|
|
||||||
* signature of a comment packet, but the initial header
|
|
||||||
* has not yet been seen; OR this packet has the signature
|
|
||||||
* of a comment packet, but contains invalid data; OR
|
|
||||||
* this packet has the signature of codebook tables,
|
|
||||||
* but the initial header or comments have not yet
|
|
||||||
* been seen; OR this packet has the signature of codebook
|
|
||||||
* tables, but contains invalid data;
|
|
||||||
* OR the stream being decoded has a compatible version
|
|
||||||
* but this packet does not have the signature of a
|
|
||||||
* theora initial header, comments, or codebook packet
|
|
||||||
* \retval OC_VERSION The packet data of \a op is an initial header with
|
|
||||||
* a version which is incompatible with this version of
|
|
||||||
* libtheora.
|
|
||||||
* \retval OC_NEWPACKET the stream being decoded has an incompatible (future)
|
|
||||||
* version and contains an unknown signature.
|
|
||||||
* \retval 0 Success
|
|
||||||
*
|
|
||||||
* \note The normal usage is that theora_decode_header() be called on the
|
|
||||||
* first three packets of a theora logical bitstream in succession.
|
|
||||||
*/
|
|
||||||
extern int theora_decode_header(theora_info *ci, theora_comment *cc,
|
|
||||||
ogg_packet *op);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize a theora_state handle for decoding.
|
|
||||||
* \param th The theora_state handle to initialize.
|
|
||||||
* \param c A theora_info struct filled with the desired decoding parameters.
|
|
||||||
* This is of course usually obtained from a previous call to
|
|
||||||
* theora_decode_header().
|
|
||||||
* \retval 0 Success
|
|
||||||
*/
|
|
||||||
extern int theora_decode_init(theora_state *th, theora_info *c);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Input a packet containing encoded data into the theora decoder.
|
|
||||||
* \param th A theora_state handle previously initialized for decoding.
|
|
||||||
* \param op An ogg_packet containing encoded theora data.
|
|
||||||
* \retval 0 Success
|
|
||||||
* \retval OC_BADPACKET \a op does not contain encoded video data
|
|
||||||
*/
|
|
||||||
extern int theora_decode_packetin(theora_state *th,ogg_packet *op);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output the next available frame of decoded YUV data.
|
|
||||||
* \param th A theora_state handle previously initialized for decoding.
|
|
||||||
* \param yuv A yuv_buffer in which libtheora should place the decoded data.
|
|
||||||
* \retval 0 Success
|
|
||||||
*/
|
|
||||||
extern int theora_decode_YUVout(theora_state *th,yuv_buffer *yuv);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Report whether a theora packet is a header or not
|
|
||||||
* This function does no verification beyond checking the header
|
|
||||||
* flag bit so it should not be used for bitstream identification;
|
|
||||||
* use theora_decode_header() for that.
|
|
||||||
*
|
|
||||||
* \param op An ogg_packet containing encoded theora data.
|
|
||||||
* \retval 1 The packet is a header packet
|
|
||||||
* \retval 0 The packet is not a header packet (and so contains frame data)
|
|
||||||
*
|
|
||||||
* Thus function was added in the 1.0alpha4 release.
|
|
||||||
*/
|
|
||||||
extern int theora_packet_isheader(ogg_packet *op);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Report whether a theora packet is a keyframe or not
|
|
||||||
*
|
|
||||||
* \param op An ogg_packet containing encoded theora data.
|
|
||||||
* \retval 1 The packet contains a keyframe image
|
|
||||||
* \retval 0 The packet is contains an interframe delta
|
|
||||||
* \retval -1 The packet is not an image data packet at all
|
|
||||||
*
|
|
||||||
* Thus function was added in the 1.0alpha4 release.
|
|
||||||
*/
|
|
||||||
extern int theora_packet_iskeyframe(ogg_packet *op);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Report the granulepos shift radix
|
|
||||||
*
|
|
||||||
* When embedded in Ogg, Theora uses a two-part granulepos,
|
|
||||||
* splitting the 64-bit field into two pieces. The more-significant
|
|
||||||
* section represents the frame count at the last keyframe,
|
|
||||||
* and the less-significant section represents the count of
|
|
||||||
* frames since the last keyframe. In this way the overall
|
|
||||||
* field is still non-decreasing with time, but usefully encodes
|
|
||||||
* a pointer to the last keyframe, which is necessary for
|
|
||||||
* correctly restarting decode after a seek.
|
|
||||||
*
|
|
||||||
* This function reports the number of bits used to represent
|
|
||||||
* the distance to the last keyframe, and thus how the granulepos
|
|
||||||
* field must be shifted or masked to obtain the two parts.
|
|
||||||
*
|
|
||||||
* Since libtheora returns compressed data in an ogg_packet
|
|
||||||
* structure, this may be generally useful even if the Theora
|
|
||||||
* packets are not being used in an Ogg container.
|
|
||||||
*
|
|
||||||
* \param ti A previously initialized theora_info struct
|
|
||||||
* \returns The bit shift dividing the two granulepos fields
|
|
||||||
*
|
|
||||||
* This function was added in the 1.0alpha5 release.
|
|
||||||
*/
|
|
||||||
int theora_granule_shift(theora_info *ti);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a granulepos to an absolute frame number. The granulepos is
|
|
||||||
* interpreted in the context of a given theora_state handle.
|
|
||||||
*
|
|
||||||
* \param th A previously initialized theora_state handle (encode or decode)
|
|
||||||
* \param granulepos The granulepos to convert.
|
|
||||||
* \returns The frame number corresponding to \a granulepos.
|
|
||||||
* \retval -1 The given granulepos is undefined (i.e. negative)
|
|
||||||
*
|
|
||||||
* Thus function was added in the 1.0alpha4 release.
|
|
||||||
*/
|
|
||||||
extern ogg_int64_t theora_granule_frame(theora_state *th,ogg_int64_t granulepos);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a granulepos to absolute time in seconds. The granulepos is
|
|
||||||
* interpreted in the context of a given theora_state handle.
|
|
||||||
* \param th A previously initialized theora_state handle (encode or decode)
|
|
||||||
* \param granulepos The granulepos to convert.
|
|
||||||
* \returns The absolute time in seconds corresponding to \a granulepos.
|
|
||||||
* \retval -1. The given granulepos is undefined (i.e. negative), or
|
|
||||||
* \retval -1. The function has been disabled because floating
|
|
||||||
* point support is not available.
|
|
||||||
*/
|
|
||||||
extern double theora_granule_time(theora_state *th,ogg_int64_t granulepos);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize a theora_info structure. All values within the given theora_info
|
|
||||||
* structure are initialized, and space is allocated within libtheora for
|
|
||||||
* internal codec setup data.
|
|
||||||
* \param c A theora_info struct to initialize.
|
|
||||||
*/
|
|
||||||
extern void theora_info_init(theora_info *c);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear a theora_info structure. All values within the given theora_info
|
|
||||||
* structure are cleared, and associated internal codec setup data is freed.
|
|
||||||
* \param c A theora_info struct to initialize.
|
|
||||||
*/
|
|
||||||
extern void theora_info_clear(theora_info *c);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free all internal data associated with a theora_state handle.
|
|
||||||
* \param t A theora_state handle.
|
|
||||||
*/
|
|
||||||
extern void theora_clear(theora_state *t);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize an allocated theora_comment structure
|
|
||||||
* \param tc An allocated theora_comment structure
|
|
||||||
**/
|
|
||||||
extern void theora_comment_init(theora_comment *tc);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a comment to an initialized theora_comment structure
|
|
||||||
* \param tc A previously initialized theora comment structure
|
|
||||||
* \param comment A null-terminated string encoding the comment in the form
|
|
||||||
* "TAG=the value"
|
|
||||||
*
|
|
||||||
* Neither theora_comment_add() nor theora_comment_add_tag() support
|
|
||||||
* comments containing null values, although the bitstream format
|
|
||||||
* supports this. To add such comments you will need to manipulate
|
|
||||||
* the theora_comment structure directly.
|
|
||||||
**/
|
|
||||||
|
|
||||||
extern void theora_comment_add(theora_comment *tc, char *comment);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a comment to an initialized theora_comment structure.
|
|
||||||
* \param tc A previously initialized theora comment structure
|
|
||||||
* \param tag A null-terminated string containing the tag
|
|
||||||
* associated with the comment.
|
|
||||||
* \param value The corresponding value as a null-terminated string
|
|
||||||
*
|
|
||||||
* Neither theora_comment_add() nor theora_comment_add_tag() support
|
|
||||||
* comments containing null values, although the bitstream format
|
|
||||||
* supports this. To add such comments you will need to manipulate
|
|
||||||
* the theora_comment structure directly.
|
|
||||||
**/
|
|
||||||
extern void theora_comment_add_tag(theora_comment *tc,
|
|
||||||
char *tag, char *value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Look up a comment value by tag.
|
|
||||||
* \param tc Tn initialized theora_comment structure
|
|
||||||
* \param tag The tag to look up
|
|
||||||
* \param count The instance of the tag. The same tag can appear multiple
|
|
||||||
* times, each with a distinct and ordered value, so an index
|
|
||||||
* is required to retrieve them all.
|
|
||||||
* \returns A pointer to the queried tag's value
|
|
||||||
* \retval NULL No matching tag is found
|
|
||||||
*
|
|
||||||
* \note Use theora_comment_query_count() to get the legal range for the
|
|
||||||
* count parameter.
|
|
||||||
**/
|
|
||||||
|
|
||||||
extern char *theora_comment_query(theora_comment *tc, char *tag, int count);
|
|
||||||
|
|
||||||
/** Look up the number of instances of a tag.
|
|
||||||
* \param tc An initialized theora_comment structure
|
|
||||||
* \param tag The tag to look up
|
|
||||||
* \returns The number on instances of a particular tag.
|
|
||||||
*
|
|
||||||
* Call this first when querying for a specific tag and then interate
|
|
||||||
* over the number of instances with separate calls to
|
|
||||||
* theora_comment_query() to retrieve all instances in order.
|
|
||||||
**/
|
|
||||||
extern int theora_comment_query_count(theora_comment *tc, char *tag);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear an allocated theora_comment struct so that it can be freed.
|
|
||||||
* \param tc An allocated theora_comment structure.
|
|
||||||
**/
|
|
||||||
extern void theora_comment_clear(theora_comment *tc);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
#endif /* _O_THEORA_H_ */
|
|
||||||
Vendored
-280
@@ -1,280 +0,0 @@
|
|||||||
/********************************************************************
|
|
||||||
* *
|
|
||||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
|
||||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
|
||||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
|
||||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
|
||||||
* *
|
|
||||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
|
||||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
|
||||||
* *
|
|
||||||
********************************************************************
|
|
||||||
|
|
||||||
function:
|
|
||||||
last mod: $Id: theoradec.h 26239 2007-05-10 01:53:20Z gmaynard $
|
|
||||||
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
/**\file
|
|
||||||
* The <tt>libtheora</tt> C decoding API.*/
|
|
||||||
|
|
||||||
#if !defined(_O_THEORA_THEORADEC_H_)
|
|
||||||
# define _O_THEORA_THEORADEC_H_ (1)
|
|
||||||
# include <ogg/ogg.h>
|
|
||||||
# include "codec.h"
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**\name theora_decode_ctl() codes
|
|
||||||
* \anchor decctlcodes
|
|
||||||
* These are the available request codes for theora_decode_ctl().
|
|
||||||
* By convention, these are odd, to distinguish them from the
|
|
||||||
* \ref encctlcodes "encoder control codes".
|
|
||||||
* Keep any experimental or vendor-specific values above \c 0x8000.*/
|
|
||||||
/*@{*/
|
|
||||||
/**Gets the maximum post-processing level.
|
|
||||||
*
|
|
||||||
* \param[out] _buf int: The maximum post-processing level.
|
|
||||||
* \retval OC_FAULT \a _dec_ctx or \a _buf is <tt>NULL</tt>.
|
|
||||||
* \retval OC_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>.
|
|
||||||
* \retval OC_IMPL Not supported by this implementation.*/
|
|
||||||
#define OC_DECCTL_GET_PPLEVEL_MAX (1)
|
|
||||||
/**Sets the post-processing level.
|
|
||||||
* By default, post-processing is disabled.
|
|
||||||
*
|
|
||||||
* \param[in] _buf int: The new post-processing level.
|
|
||||||
* 0 to disable; larger values use more CPU.
|
|
||||||
* \retval OC_FAULT \a _dec_ctx or \a _buf is <tt>NULL</tt>.
|
|
||||||
* \retval OC_EINVAL \a _buf_sz is not <tt>sizeof(int)</tt>, or the
|
|
||||||
* post-processing level is out of bounds.
|
|
||||||
* The maximum post-processing level may be
|
|
||||||
* implementation-specific, and can be obtained via
|
|
||||||
* #OC_DECCTL_GET_PPLEVEL_MAX.
|
|
||||||
* \retval OC_IMPL Not supported by this implementation.*/
|
|
||||||
#define OC_DECCTL_SET_PPLEVEL (3)
|
|
||||||
/**Sets the granule position.
|
|
||||||
* Call this after a seek, before decoding the first frame, to ensure that the
|
|
||||||
* proper granule position is returned for all subsequent frames.
|
|
||||||
*
|
|
||||||
* \param[in] _buf <tt>ogg_int64_t</tt>: The granule position of the next
|
|
||||||
* frame.
|
|
||||||
* \retval OC_FAULT \a _dec_ctx or \a _buf is <tt>NULL</tt>.
|
|
||||||
* \retval OC_EINVAL \a _buf_sz is not <tt>sizeof(ogg_int64_t)</tt>, or the
|
|
||||||
* granule position is negative.*/
|
|
||||||
#define OC_DECCTL_SET_GRANPOS (5)
|
|
||||||
/**Sets the striped decode callback function.
|
|
||||||
* If set, this function will be called as each piece of a frame is fully
|
|
||||||
* decoded in theora_decode_packetin().
|
|
||||||
* You can pass in a #theora_stripe_callback with
|
|
||||||
* theora_stripe_callback#stripe_decoded set to <tt>NULL</tt> to disable the
|
|
||||||
* callbacks at any point.
|
|
||||||
*
|
|
||||||
* \param[in] _buf #theora_stripe_callback: The callback parameters.
|
|
||||||
* \retval OC_FAULT \a _dec_ctx or \a _buf is <tt>NULL</tt>.
|
|
||||||
* \retval OC_EINVAL \a _buf_sz is not
|
|
||||||
* <tt>sizeof(theora_stripe_callback)</tt>.*/
|
|
||||||
#define OC_DECCTL_SET_STRIPE_CB (7)
|
|
||||||
/*@}*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**A callback function for striped decode.
|
|
||||||
* This is a function pointer to an application-provided function that will be
|
|
||||||
* called each time a section of the image is fully decoded in
|
|
||||||
* theora_decode_packetin().
|
|
||||||
* This allows the application to process the section immediately, while it is
|
|
||||||
* still in cache.
|
|
||||||
* Note that the frame is decoded bottom to top, so \a _yfrag0 will steadily
|
|
||||||
* decrease with each call until it reaches 0, at which point the full frame
|
|
||||||
* is decoded.
|
|
||||||
* The number of fragment rows made available in each call depends on the pixel
|
|
||||||
* format and the number of post-processing filters enabled, and may not even
|
|
||||||
* be constant for the entire frame.
|
|
||||||
* If a non-<tt>NULL</tt> \a _granpos pointer is passed to
|
|
||||||
* theora_decode_packetin(), the granule position for the frame will be stored
|
|
||||||
* in it before the first callback is made.
|
|
||||||
* If an entire frame is dropped (a 0-byte packet), then no callbacks will be
|
|
||||||
* made at all for that frame.
|
|
||||||
* \param _ctx An application-provided context pointer.
|
|
||||||
* \param _buf The image buffer for the decoded frame.
|
|
||||||
* \param _yfrag0 The Y coordinate of the first row of 8x8 fragments
|
|
||||||
* decoded.
|
|
||||||
* Multiply this by 8 to obtain the pixel row number in the
|
|
||||||
* luma plane.
|
|
||||||
* If the chroma planes are subsampled in the Y direction,
|
|
||||||
* this will always be divisible by two.
|
|
||||||
* \param _yfrag_end The Y coordinate of the first row of 8x8 fragments past
|
|
||||||
* the newly decoded section.
|
|
||||||
* If the chroma planes are subsampled in the Y direction,
|
|
||||||
* this will always be divisible by two.
|
|
||||||
* I.e., this section contains fragment rows
|
|
||||||
* <tt>\a _yfrag0 ...\a _yfrag_end -1</tt>.*/
|
|
||||||
typedef void (*theora_stripe_decoded_func)(void *_ctx,theora_ycbcr_buffer _buf,
|
|
||||||
int _yfrag0,int _yfrag_end);
|
|
||||||
|
|
||||||
/**The striped decode callback data to pass to #OC_DECCTL_SET_STRIPE_CB.*/
|
|
||||||
typedef struct{
|
|
||||||
/**An application-provided context pointer.
|
|
||||||
* This will be passed back verbatim to the application.*/
|
|
||||||
void *ctx;
|
|
||||||
/**The callback function pointer.*/
|
|
||||||
theora_stripe_decoded_func stripe_decoded;
|
|
||||||
}theora_stripe_callback;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**\name Decoder state
|
|
||||||
The following data structures are opaque, and their contents are not
|
|
||||||
publicly defined by this API.
|
|
||||||
Referring to their internals directly is unsupported, and may break without
|
|
||||||
warning.*/
|
|
||||||
/*@{*/
|
|
||||||
/**The decoder context.*/
|
|
||||||
typedef struct theora_dec_ctx theora_dec_ctx;
|
|
||||||
/**Setup information.
|
|
||||||
This contains auxiliary information (Huffman tables and quantization
|
|
||||||
parameters) decoded from the setup header by theora_decode_headerin() to be
|
|
||||||
passed to theora_decode_alloc().
|
|
||||||
It can be re-used to initialize any number of decoders, and can be freed
|
|
||||||
via theora_setup_free() at any time.*/
|
|
||||||
typedef struct theora_setup_info theora_setup_info;
|
|
||||||
/*@}*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**\defgroup decfuncs Functions for Decoding*/
|
|
||||||
/*@{*/
|
|
||||||
/**\name Functions for decoding
|
|
||||||
* You must link to <tt>libtheorabase</tt> and <tt>libtheoradec</tt> if you use
|
|
||||||
* any of the functions in this section.
|
|
||||||
*
|
|
||||||
* The functions are listed in the order they are used in a typical decode.
|
|
||||||
* The basic steps are:
|
|
||||||
* - Parse the header packets by repeatedly calling theora_decode_headerin().
|
|
||||||
* - Allocate a #theora_dec_ctx handle with theora_decode_alloc().
|
|
||||||
* - Call theora_setup_free() to free any memory used for codec setup
|
|
||||||
* information.
|
|
||||||
* - Perform any additional decoder configuration with theora_decode_ctl().
|
|
||||||
* - For each video data packet:
|
|
||||||
* - Submit the packet to the decoder via theora_decode_packetin().
|
|
||||||
* - Retrieve the uncompressed video data via theora_decode_ycbcr_out().
|
|
||||||
* - Call theora_decode_free() to release all decoder memory.*/
|
|
||||||
/*@{*/
|
|
||||||
/**Decodes the header packets of a Theora stream.
|
|
||||||
* This should be called on the initial packets of the stream, in succession,
|
|
||||||
* until it returns <tt>0</tt>, indicating that all headers have been
|
|
||||||
* processed, or an error is encountered.
|
|
||||||
* At least three header packets are required, and additional optional header
|
|
||||||
* packets may follow.
|
|
||||||
* This can be used on the first packet of any logical stream to determine if
|
|
||||||
* that stream is a Theora stream.
|
|
||||||
* \param _info A #theora_info structure to fill in.
|
|
||||||
* This must have been previously initialized with
|
|
||||||
* theora_info_init().
|
|
||||||
* The application may immediately begin using the contents of
|
|
||||||
* this structure after the first header is decoded, though it
|
|
||||||
* must continue to be passed in on all subsequent calls.
|
|
||||||
* \param _tc A #theora_comment structure to fill in.
|
|
||||||
* The application may immediately begin using the contents of
|
|
||||||
* this structure after the second header is decoded, though it
|
|
||||||
* must continue to be passed in on all subsequent calls.
|
|
||||||
* \param _setup Returns a pointer to additional, private setup information
|
|
||||||
* needed by the decoder.
|
|
||||||
* The contents of this pointer must be initialized to
|
|
||||||
* <tt>NULL</tt> on the first call, and the returned value must
|
|
||||||
* continue to be passed in on all subsequent calls.
|
|
||||||
* \param _op An <tt>ogg_packet</tt> structure which contains one of the
|
|
||||||
* initial packets of an Ogg logical stream.
|
|
||||||
* \return A positive value indicates that a Theora header was successfully
|
|
||||||
* processed.
|
|
||||||
* \retval 0 The first video data packet was encountered after all
|
|
||||||
* required header packets were parsed.
|
|
||||||
* The packet just passed in on this call should be saved
|
|
||||||
* and fed to theora_decode_packetin() to begin decoding
|
|
||||||
* video data.
|
|
||||||
* \retval OC_FAULT One of \a _info, \a _tc, or \a _setup was
|
|
||||||
* <tt>NULL</tt>.
|
|
||||||
* \retval OC_BADHEADER \a _op was <tt>NULL</tt>, the packet was not the next
|
|
||||||
* header packet in the expected sequence, or the format
|
|
||||||
* of the header data was invalid.
|
|
||||||
* \retval OC_VERSION The packet data was a Theora info header, but for a
|
|
||||||
* bitstream version not decodable with this version of
|
|
||||||
* <tt>libtheora</tt>.
|
|
||||||
* \retval OC_NOTFORMAT The packet was not a Theora header.
|
|
||||||
*/
|
|
||||||
extern int theora_decode_headerin(theora_info *_info,theora_comment *_tc,
|
|
||||||
theora_setup_info **_setup,ogg_packet *_op);
|
|
||||||
/**Allocates a decoder instance.
|
|
||||||
* \param _info A #theora_info struct filled via theora_decode_headerin().
|
|
||||||
* \param _setup A #theora_setup_info handle returned via
|
|
||||||
* theora_decode_headerin().
|
|
||||||
* \return The initialized #theora_dec_ctx handle.
|
|
||||||
* \retval NULL If the decoding parameters were invalid.*/
|
|
||||||
extern theora_dec_ctx *theora_decode_alloc(const theora_info *_info,
|
|
||||||
const theora_setup_info *_setup);
|
|
||||||
/**Releases all storage used for the decoder setup information.
|
|
||||||
* This should be called after you no longer want to create any decoders for
|
|
||||||
* a stream whose headers you have parsed with theora_decode_headerin().
|
|
||||||
* \param _setup The setup information to free.
|
|
||||||
* This can safely be <tt>NULL</tt>.*/
|
|
||||||
extern void theora_setup_free(theora_setup_info *_setup);
|
|
||||||
/**Encoder control function.
|
|
||||||
* This is used to provide advanced control the decoding process.
|
|
||||||
* \param _dec A #theora_dec_ctx handle.
|
|
||||||
* \param _req The control code to process.
|
|
||||||
* See \ref decctlcodes "the list of available control codes"
|
|
||||||
* for details.
|
|
||||||
* \param _buf The parameters for this control code.
|
|
||||||
* \param _buf_sz The size of the parameter buffer.*/
|
|
||||||
extern int theora_decode_ctl(theora_dec_ctx *_dec,int _req,void *_buf,
|
|
||||||
size_t _buf_sz);
|
|
||||||
/**Submits a packet containing encoded video data to the decoder.
|
|
||||||
* \param _dec A #theora_dec_ctx handle.
|
|
||||||
* \param _op An <tt>ogg_packet</tt> containing encoded video data.
|
|
||||||
* \param _granpos Returns the granule position of the decoded packet.
|
|
||||||
* If non-<tt>NULL</tt>, the granule position for this specific
|
|
||||||
* packet is stored in this location.
|
|
||||||
* This is computed incrementally from previously decoded
|
|
||||||
* packets.
|
|
||||||
* After a seek, the correct granule position must be set via
|
|
||||||
* #OC_DECCTL_SET_GRANPOS for this to work properly.
|
|
||||||
* \retval 0 Success.
|
|
||||||
* \retval OC_FAULT \a _dec or _op was <tt>NULL</tt>.
|
|
||||||
* \retval OC_BADPACKET \a _op does not contain encoded video data.
|
|
||||||
* \retval OC_IMPL The video data uses bitstream features which this
|
|
||||||
* library does not support.*/
|
|
||||||
extern int theora_decode_packetin(theora_dec_ctx *_dec,const ogg_packet *_op,
|
|
||||||
ogg_int64_t *_granpos);
|
|
||||||
/**Outputs the next available frame of decoded Y'CbCr data.
|
|
||||||
* If a striped decode callback has been set with #OC_DECCTL_SET_STRIPE_CB,
|
|
||||||
* then the application does not need to call this function.
|
|
||||||
* \param _dec A #theora_dec_ctx handle.
|
|
||||||
* \param _ycbcr A video buffer structure to fill in.
|
|
||||||
* <tt>libtheora</tt> will fill in all the members of this
|
|
||||||
* structure, including the pointers to the uncompressed video
|
|
||||||
* data.
|
|
||||||
* The memory for this video data is owned by
|
|
||||||
* <tt>libtheora</tt>.
|
|
||||||
* It may be freed or overwritten without notification when
|
|
||||||
* subsequent frames are decoded.
|
|
||||||
* \retval 0 Success
|
|
||||||
*/
|
|
||||||
extern int theora_decode_ycbcr_out(theora_dec_ctx *_dec,
|
|
||||||
theora_ycbcr_buffer _ycbcr);
|
|
||||||
/**Frees an allocated decoder instance.
|
|
||||||
* \param _dec A #theora_dec_ctx handle.*/
|
|
||||||
extern void theora_decode_free(theora_dec_ctx *_dec);
|
|
||||||
/*@}*/
|
|
||||||
/*@}*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
BIN
Binary file not shown.
@@ -246,10 +246,6 @@ MovieTexture = arch/MovieTexture/MovieTexture.cpp arch/MovieTexture/MovieTexture
|
|||||||
arch/MovieTexture/MovieTexture_Generic.cpp arch/MovieTexture/MovieTexture_Generic.h \
|
arch/MovieTexture/MovieTexture_Generic.cpp arch/MovieTexture/MovieTexture_Generic.h \
|
||||||
arch/MovieTexture/MovieTexture_Null.cpp arch/MovieTexture/MovieTexture_Null.h
|
arch/MovieTexture/MovieTexture_Null.cpp arch/MovieTexture/MovieTexture_Null.h
|
||||||
|
|
||||||
if HAVE_THEORA
|
|
||||||
MovieTexture += arch/MovieTexture/MovieTexture_Theora.cpp arch/MovieTexture/MovieTexture_Theora.h
|
|
||||||
endif
|
|
||||||
|
|
||||||
if HAVE_FFMPEG
|
if HAVE_FFMPEG
|
||||||
MovieTexture += arch/MovieTexture/MovieTexture_FFMpeg.cpp arch/MovieTexture/MovieTexture_FFMpeg.h
|
MovieTexture += arch/MovieTexture/MovieTexture_FFMpeg.cpp arch/MovieTexture/MovieTexture_FFMpeg.h
|
||||||
endif
|
endif
|
||||||
|
|||||||
@@ -3456,12 +3456,6 @@ cl /Zl /nologo /c verstub.cpp /Fo"$(IntDir)"\
|
|||||||
<File
|
<File
|
||||||
RelativePath="arch\MovieTexture\MovieTexture_Null.h">
|
RelativePath="arch\MovieTexture\MovieTexture_Null.h">
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="arch\MovieTexture\MovieTexture_Theora.cpp">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="arch\MovieTexture\MovieTexture_Theora.h">
|
|
||||||
</File>
|
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="LowLevelWindow"
|
Name="LowLevelWindow"
|
||||||
|
|||||||
@@ -2055,14 +2055,6 @@
|
|||||||
RelativePath="arch\MovieTexture\MovieTexture_Null.h"
|
RelativePath="arch\MovieTexture\MovieTexture_Null.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="arch\MovieTexture\MovieTexture_Theora.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="arch\MovieTexture\MovieTexture_Theora.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="LowLevelWindow"
|
Name="LowLevelWindow"
|
||||||
|
|||||||
@@ -2318,14 +2318,6 @@
|
|||||||
RelativePath="arch\MovieTexture\MovieTexture_Null.h"
|
RelativePath="arch\MovieTexture\MovieTexture_Null.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="arch\MovieTexture\MovieTexture_Theora.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="arch\MovieTexture\MovieTexture_Theora.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="LowLevelWindow"
|
Name="LowLevelWindow"
|
||||||
|
|||||||
@@ -585,7 +585,6 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)</Command>
|
|||||||
<ClCompile Include="arch\MovieTexture\MovieTexture_FFMpeg.cpp" />
|
<ClCompile Include="arch\MovieTexture\MovieTexture_FFMpeg.cpp" />
|
||||||
<ClCompile Include="arch\MovieTexture\MovieTexture_Generic.cpp" />
|
<ClCompile Include="arch\MovieTexture\MovieTexture_Generic.cpp" />
|
||||||
<ClCompile Include="arch\MovieTexture\MovieTexture_Null.cpp" />
|
<ClCompile Include="arch\MovieTexture\MovieTexture_Null.cpp" />
|
||||||
<ClCompile Include="arch\MovieTexture\MovieTexture_Theora.cpp" />
|
|
||||||
<ClCompile Include="arch\LowLevelWindow\LowLevelWindow.cpp" />
|
<ClCompile Include="arch\LowLevelWindow\LowLevelWindow.cpp" />
|
||||||
<ClCompile Include="arch\LowLevelWindow\LowLevelWindow_Win32.cpp" />
|
<ClCompile Include="arch\LowLevelWindow\LowLevelWindow_Win32.cpp" />
|
||||||
<ClCompile Include="arch\MemoryCard\MemoryCardDriver.cpp" />
|
<ClCompile Include="arch\MemoryCard\MemoryCardDriver.cpp" />
|
||||||
@@ -1899,7 +1898,6 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)</Command>
|
|||||||
<ClInclude Include="arch\MovieTexture\MovieTexture_FFMpeg.h" />
|
<ClInclude Include="arch\MovieTexture\MovieTexture_FFMpeg.h" />
|
||||||
<ClInclude Include="arch\MovieTexture\MovieTexture_Generic.h" />
|
<ClInclude Include="arch\MovieTexture\MovieTexture_Generic.h" />
|
||||||
<ClInclude Include="arch\MovieTexture\MovieTexture_Null.h" />
|
<ClInclude Include="arch\MovieTexture\MovieTexture_Null.h" />
|
||||||
<ClInclude Include="arch\MovieTexture\MovieTexture_Theora.h" />
|
|
||||||
<ClInclude Include="arch\LowLevelWindow\LowLevelWindow.h" />
|
<ClInclude Include="arch\LowLevelWindow\LowLevelWindow.h" />
|
||||||
<ClInclude Include="arch\LowLevelWindow\LowLevelWindow_Win32.h" />
|
<ClInclude Include="arch\LowLevelWindow\LowLevelWindow_Win32.h" />
|
||||||
<ClInclude Include="arch\MemoryCard\MemoryCardDriver.h" />
|
<ClInclude Include="arch\MemoryCard\MemoryCardDriver.h" />
|
||||||
@@ -2387,4 +2385,4 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)</Command>
|
|||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -711,9 +711,6 @@
|
|||||||
<ClCompile Include="arch\MovieTexture\MovieTexture_Null.cpp">
|
<ClCompile Include="arch\MovieTexture\MovieTexture_Null.cpp">
|
||||||
<Filter>StepMania\arch\MovieTexture</Filter>
|
<Filter>StepMania\arch\MovieTexture</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="arch\MovieTexture\MovieTexture_Theora.cpp">
|
|
||||||
<Filter>StepMania\arch\MovieTexture</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="arch\LowLevelWindow\LowLevelWindow.cpp">
|
<ClCompile Include="arch\LowLevelWindow\LowLevelWindow.cpp">
|
||||||
<Filter>StepMania\arch\LowLevelWindow</Filter>
|
<Filter>StepMania\arch\LowLevelWindow</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -2222,9 +2219,6 @@
|
|||||||
<ClInclude Include="arch\MovieTexture\MovieTexture_Null.h">
|
<ClInclude Include="arch\MovieTexture\MovieTexture_Null.h">
|
||||||
<Filter>StepMania\arch\MovieTexture</Filter>
|
<Filter>StepMania\arch\MovieTexture</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="arch\MovieTexture\MovieTexture_Theora.h">
|
|
||||||
<Filter>StepMania\arch\MovieTexture</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="arch\LowLevelWindow\LowLevelWindow.h">
|
<ClInclude Include="arch\LowLevelWindow\LowLevelWindow.h">
|
||||||
<Filter>StepMania\arch\LowLevelWindow</Filter>
|
<Filter>StepMania\arch\LowLevelWindow</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|||||||
@@ -1,816 +0,0 @@
|
|||||||
#include "global.h"
|
|
||||||
#include "MovieTexture_Theora.h"
|
|
||||||
#include "RageDisplay.h"
|
|
||||||
#include "RageFile.h"
|
|
||||||
#include "RageLog.h"
|
|
||||||
#include "RageSurface.h"
|
|
||||||
#include "RageUtil.h"
|
|
||||||
#include "MovieTexture_FFMpeg.h" /* for AVCodecCreateCompatibleSurface */
|
|
||||||
|
|
||||||
namespace avcodec
|
|
||||||
{
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include <libavcodec/avcodec.h> // for avcodec::img_convert
|
|
||||||
#include <libswscale/swscale.h>
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// #define HAVE_THEORAEXP
|
|
||||||
|
|
||||||
#if !defined(HAVE_THEORAEXP)
|
|
||||||
#include <../extern/vorbis/theora/theora.h>
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#pragma comment(lib, OGG_LIB_DIR "ogg_static.lib")
|
|
||||||
#pragma comment(lib, OGG_LIB_DIR "theora_static.lib")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(MACOSX)
|
|
||||||
static const int sws_flags = SWS_BICUBIC; // XXX: Reasonable default?
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class MovieDecoder_Theora: public MovieDecoder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MovieDecoder_Theora();
|
|
||||||
~MovieDecoder_Theora();
|
|
||||||
|
|
||||||
RString Open( RString sFile );
|
|
||||||
void Close();
|
|
||||||
void Rewind() { } // XXX
|
|
||||||
|
|
||||||
int DecodeFrame( float fTargetTime );
|
|
||||||
void GetFrame( RageSurface *pOut );
|
|
||||||
RageSurface *CreateCompatibleSurface( int iTextureWidth, int iTextureHeight, bool bPreferHighColor, MovieDecoderPixelFormatYCbCr &fmtout );
|
|
||||||
|
|
||||||
int GetWidth() const { return m_TheoraInfo.frame_width; }
|
|
||||||
int GetHeight() const { return m_TheoraInfo.frame_height; }
|
|
||||||
float GetSourceAspectRatio() const;
|
|
||||||
|
|
||||||
float GetTimestamp() const;
|
|
||||||
float GetFrameDuration() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void Init();
|
|
||||||
RString ProcessHeaders();
|
|
||||||
int ReadPage( ogg_page *pOggPage, RString &sError, bool bInitializing );
|
|
||||||
void ConvertToSurface( RageSurface *pSurface ) const; // sm4svn
|
|
||||||
|
|
||||||
// sm-ssc with modern ffmpeg:
|
|
||||||
#if !defined(MACOSX)
|
|
||||||
void ConvertToSurface( RageSurface *pSurface );
|
|
||||||
void ConvertImage( avcodec::AVPicture &in, avcodec::AVPicture &out, int height );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RageFile m_File;
|
|
||||||
|
|
||||||
ogg_sync_state m_OggSync;
|
|
||||||
ogg_stream_state m_OggStream;
|
|
||||||
theora_info m_TheoraInfo;
|
|
||||||
theora_comment m_TheoraComment;
|
|
||||||
theora_state m_TheoraState;
|
|
||||||
|
|
||||||
ogg_int64_t m_iGranulepos;
|
|
||||||
|
|
||||||
avcodec::PixelFormat m_InputPixFmt; /* PixelFormat of YUV input surface */
|
|
||||||
avcodec::PixelFormat m_OutputPixFmt; /* PixelFormat of RGB output surface */
|
|
||||||
#if !defined(MACOSX)
|
|
||||||
avcodec::SwsContext *m_swsctx;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
MovieDecoder_Theora::MovieDecoder_Theora()
|
|
||||||
{
|
|
||||||
avcodec::avcodec_init();
|
|
||||||
|
|
||||||
memset( &m_TheoraInfo, 0, sizeof(m_TheoraInfo) );
|
|
||||||
memset( &m_TheoraComment, 0, sizeof(m_TheoraComment) );
|
|
||||||
memset( &m_OggStream, 0, sizeof(m_OggStream) );
|
|
||||||
memset( &m_TheoraState, 0, sizeof(m_TheoraState) );
|
|
||||||
#if !defined(MACOSX)
|
|
||||||
m_swsctx = NULL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
MovieDecoder_Theora::~MovieDecoder_Theora()
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
#if !defined(MACOSX)
|
|
||||||
if (m_swsctx)
|
|
||||||
{
|
|
||||||
avcodec::sws_freeContext(m_swsctx);
|
|
||||||
m_swsctx = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovieDecoder_Theora::Init()
|
|
||||||
{
|
|
||||||
theora_info_init( &m_TheoraInfo );
|
|
||||||
theora_comment_init( &m_TheoraComment );
|
|
||||||
ogg_sync_init( &m_OggSync );
|
|
||||||
}
|
|
||||||
|
|
||||||
int MovieDecoder_Theora::ReadPage( ogg_page *pOggPage, RString &sError, bool bInitializing )
|
|
||||||
{
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
int iRet = ogg_sync_pageout( &m_OggSync, pOggPage );
|
|
||||||
if( iRet > 0 )
|
|
||||||
return iRet;
|
|
||||||
if( iRet < 0 )
|
|
||||||
{
|
|
||||||
if( bInitializing )
|
|
||||||
{
|
|
||||||
sError = "not an Ogg file";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG->Trace( "%s: hole in stream", m_File.GetPath().c_str() );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( iRet == 0 )
|
|
||||||
{
|
|
||||||
char *pBuffer = ogg_sync_buffer( &m_OggSync, 4096 );
|
|
||||||
int iBytes = m_File.Read( pBuffer, 4096 );
|
|
||||||
if( iBytes == 0 )
|
|
||||||
return 0;
|
|
||||||
if( iBytes == -1 )
|
|
||||||
{
|
|
||||||
sError = ssprintf( "error reading: %s", m_File.GetError().c_str() );
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ogg_sync_wrote( &m_OggSync, iBytes );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RString MovieDecoder_Theora::ProcessHeaders()
|
|
||||||
{
|
|
||||||
int iTheoraPacketsProcessed = 0;
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
ogg_page OggPage;
|
|
||||||
RString sError;
|
|
||||||
int ret = ReadPage( &OggPage, sError, true );
|
|
||||||
if( ret == 0 )
|
|
||||||
return ssprintf( "error opening %s: EOF while searching for codec headers", m_File.GetPath().c_str() );
|
|
||||||
if( ret<0 )
|
|
||||||
return ssprintf( "error reading %s: %s", m_File.GetPath().c_str(), sError.c_str() );
|
|
||||||
|
|
||||||
if( m_OggStream.body_data == NULL )
|
|
||||||
{
|
|
||||||
/* We don't have a stream yet. If this packet doesn't start a stream,
|
|
||||||
* then there aren't any Theora streams. */
|
|
||||||
if( !ogg_page_bos(&OggPage) )
|
|
||||||
return ssprintf( "error opening %s: no Theora streams found", m_File.GetPath().c_str() );
|
|
||||||
|
|
||||||
ogg_stream_init( &m_OggStream, ogg_page_serialno(&OggPage) );
|
|
||||||
ogg_stream_pagein( &m_OggStream, &OggPage );
|
|
||||||
ogg_packet op;
|
|
||||||
ogg_stream_packetout( &m_OggStream, &op );
|
|
||||||
|
|
||||||
if( theora_decode_header(&m_TheoraInfo, &m_TheoraComment, &op) < 0 )
|
|
||||||
{
|
|
||||||
ogg_stream_clear( &m_OggStream );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We've found the Theora stream. */
|
|
||||||
iTheoraPacketsProcessed++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ogg_stream_pagein( &m_OggStream, &OggPage );
|
|
||||||
|
|
||||||
/* Look for more headers in this page. */
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
ogg_packet op;
|
|
||||||
int ret2 = ogg_stream_packetpeek( &m_OggStream, &op );
|
|
||||||
if( ret2 == 0 )
|
|
||||||
break;
|
|
||||||
if( ret2 < 0 )
|
|
||||||
return ssprintf( "error opening %s: error parsing Theora stream headers", m_File.GetPath().c_str() );
|
|
||||||
|
|
||||||
if( !theora_packet_isheader(&op) )
|
|
||||||
{
|
|
||||||
/* This is a body packet, not a header packet, so we're done processing
|
|
||||||
* headers. We must have at least three header packets. */
|
|
||||||
if( iTheoraPacketsProcessed < 3 )
|
|
||||||
return ssprintf( "error opening %s: error parsing Theora stream headers", m_File.GetPath().c_str() );
|
|
||||||
return RString();
|
|
||||||
}
|
|
||||||
|
|
||||||
ret2 = theora_decode_header( &m_TheoraInfo, &m_TheoraComment, &op);
|
|
||||||
if( ret2 < 0 && ret2 != OC_NEWPACKET )
|
|
||||||
return ssprintf( "error opening %s: error parsing Theora stream headers", m_File.GetPath().c_str() );
|
|
||||||
|
|
||||||
ogg_stream_packetout( &m_OggStream, NULL );
|
|
||||||
iTheoraPacketsProcessed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RString MovieDecoder_Theora::Open( RString sFile )
|
|
||||||
{
|
|
||||||
if( !m_File.Open(sFile) )
|
|
||||||
return ssprintf( "error opening %s: %s", sFile.c_str(), m_File.GetError().c_str() );
|
|
||||||
|
|
||||||
Init();
|
|
||||||
|
|
||||||
RString sError = ProcessHeaders();
|
|
||||||
if( !sError.empty() )
|
|
||||||
return sError;
|
|
||||||
|
|
||||||
theora_decode_init( &m_TheoraState, &m_TheoraInfo );
|
|
||||||
|
|
||||||
RString sOutput = ssprintf( "MovieDecoder_Theora: Opened \"%s\". Serial: 0x%08lx, FPS: %.02f",
|
|
||||||
m_File.GetPath().c_str(), m_OggStream.serialno, 1/GetFrameDuration() );
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
m_InputPixFmt = avcodec::PIX_FMT_YUV420P;
|
|
||||||
#else
|
|
||||||
switch( m_TheoraInfo.pixelformat )
|
|
||||||
{
|
|
||||||
case OC_PF_420:
|
|
||||||
m_InputPixFmt = avcodec::PIX_FMT_YUV420P;
|
|
||||||
sOutput += ", Format: YUV420";
|
|
||||||
break;
|
|
||||||
case OC_PF_422:
|
|
||||||
m_InputPixFmt = avcodec::PIX_FMT_YUV422P;
|
|
||||||
sOutput += ", Format: YUV422";
|
|
||||||
break;
|
|
||||||
case OC_PF_444:
|
|
||||||
m_InputPixFmt = avcodec::PIX_FMT_YUV444P;
|
|
||||||
sOutput += ", Format: YUV444";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return ssprintf( "error opening %s: unsupported pixel format %i", m_File.GetPath().c_str(), m_TheoraInfo.pixelformat );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
LOG->Trace( "%s", sOutput.c_str() );
|
|
||||||
|
|
||||||
return RString();
|
|
||||||
}
|
|
||||||
|
|
||||||
int MovieDecoder_Theora::DecodeFrame( float fTargetTime )
|
|
||||||
{
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
ogg_packet op;
|
|
||||||
if( ogg_stream_packetout(&m_OggStream, &op) != 0 )
|
|
||||||
{
|
|
||||||
theora_decode_packetin( &m_TheoraState, &op );
|
|
||||||
|
|
||||||
if( fTargetTime != -1 &&
|
|
||||||
GetTimestamp() + GetFrameDuration() <= fTargetTime )
|
|
||||||
{
|
|
||||||
ogg_int64_t iFrame = theora_granule_frame( (theora_state *) &m_TheoraState, m_iGranulepos );
|
|
||||||
if( (iFrame % 2) == 0 )
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_iGranulepos = m_TheoraState.granulepos;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read more data. */
|
|
||||||
ogg_page OggPage;
|
|
||||||
RString sError;
|
|
||||||
int ret = ReadPage( &OggPage, sError, false );
|
|
||||||
if( ret == 0 )
|
|
||||||
return 0;
|
|
||||||
if( ret == -1 )
|
|
||||||
{
|
|
||||||
LOG->Warn( "error reading %s: %s", m_File.GetPath().c_str(), sError.c_str() );
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if( ret > 0 )
|
|
||||||
ogg_stream_pagein( &m_OggStream, &OggPage );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovieDecoder_Theora::GetFrame( RageSurface *pOut )
|
|
||||||
{
|
|
||||||
ConvertToSurface( pOut );
|
|
||||||
}
|
|
||||||
|
|
||||||
RageSurface *MovieDecoder_Theora::CreateCompatibleSurface( int iTextureWidth, int iTextureHeight, bool bPreferHighColor, MovieDecoderPixelFormatYCbCr &fmtout )
|
|
||||||
{
|
|
||||||
return RageMovieTextureDriver_FFMpeg::AVCodecCreateCompatibleSurface( iTextureWidth, iTextureHeight, bPreferHighColor, *ConvertValue<int>(&m_OutputPixFmt), fmtout );
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(MACOSX)
|
|
||||||
void MovieDecoder_Theora::ConvertImage( avcodec::AVPicture &in, avcodec::AVPicture &out, int height )
|
|
||||||
{
|
|
||||||
// XXX: Do we need separate contexts for different heights?
|
|
||||||
// XXX: Do this in one of the Open() methods instead?
|
|
||||||
// XXX: The problem of doing this in Open() is that m_OutputPixFmt is not already initialized with its correct value.
|
|
||||||
if( m_swsctx == NULL )
|
|
||||||
{
|
|
||||||
m_swsctx = avcodec::sws_getCachedContext( m_swsctx,
|
|
||||||
GetWidth(), GetHeight(), m_InputPixFmt,
|
|
||||||
GetWidth(), GetHeight(), m_OutputPixFmt,
|
|
||||||
sws_flags, NULL, NULL, NULL );
|
|
||||||
if( m_swsctx == NULL )
|
|
||||||
{
|
|
||||||
LOG->Warn("Cannot initialize sws conversion context for (%d,%d) %d->%d", GetWidth(), GetHeight(), m_InputPixFmt, m_OutputPixFmt);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
avcodec::sws_scale( m_swsctx,
|
|
||||||
in.data, in.linesize, 0, height,
|
|
||||||
out.data, out.linesize );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// const in sm4svn:
|
|
||||||
void MovieDecoder_Theora::ConvertToSurface( RageSurface *pSurface )
|
|
||||||
#if defined(MACOSX)
|
|
||||||
const
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
yuv_buffer yuv;
|
|
||||||
theora_decode_YUVout( (theora_state *) &m_TheoraState, &yuv );
|
|
||||||
|
|
||||||
/* XXX: non-zero offset untested */
|
|
||||||
int iUVOffsetX = m_TheoraInfo.offset_x;
|
|
||||||
int iUVOffsetY = m_TheoraInfo.offset_y;
|
|
||||||
if( m_InputPixFmt == avcodec::PIX_FMT_YUV420P || avcodec::PIX_FMT_YUV422P )
|
|
||||||
iUVOffsetX /= 2;
|
|
||||||
if( m_InputPixFmt == avcodec::PIX_FMT_YUV420P )
|
|
||||||
iUVOffsetY /= 2;
|
|
||||||
|
|
||||||
avcodec::AVPicture YUVIn;
|
|
||||||
YUVIn.data[0] = yuv.y + m_TheoraInfo.offset_x + yuv.y_stride*m_TheoraInfo.offset_y;
|
|
||||||
YUVIn.data[1] = yuv.u + iUVOffsetX + yuv.uv_stride*iUVOffsetY;
|
|
||||||
YUVIn.data[2] = yuv.v + iUVOffsetX + yuv.uv_stride*iUVOffsetY;
|
|
||||||
YUVIn.data[3] = NULL;
|
|
||||||
YUVIn.linesize[0] = yuv.y_stride;
|
|
||||||
YUVIn.linesize[1] = yuv.uv_stride;
|
|
||||||
YUVIn.linesize[2] = yuv.uv_stride;
|
|
||||||
YUVIn.linesize[3] = 0;
|
|
||||||
|
|
||||||
avcodec::AVPicture RGBOut;
|
|
||||||
RGBOut.data[0] = (unsigned char *) pSurface->pixels;
|
|
||||||
RGBOut.linesize[0] = pSurface->pitch;
|
|
||||||
|
|
||||||
// sm4svn code:
|
|
||||||
#if defined(MACOSX)
|
|
||||||
avcodec::img_convert( &RGBOut, m_OutputPixFmt,
|
|
||||||
&YUVIn, m_InputPixFmt,
|
|
||||||
m_TheoraInfo.frame_width, m_TheoraInfo.frame_height );
|
|
||||||
#else
|
|
||||||
ConvertImage( YUVIn, RGBOut, m_TheoraInfo.frame_height );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
float MovieDecoder_Theora::GetSourceAspectRatio() const
|
|
||||||
{
|
|
||||||
return (float) m_TheoraInfo.aspect_numerator / m_TheoraInfo.aspect_denominator;
|
|
||||||
}
|
|
||||||
|
|
||||||
float MovieDecoder_Theora::GetTimestamp() const
|
|
||||||
{
|
|
||||||
return (float) theora_granule_time( (theora_state *) &m_TheoraState, m_iGranulepos );
|
|
||||||
}
|
|
||||||
|
|
||||||
float MovieDecoder_Theora::GetFrameDuration() const
|
|
||||||
{
|
|
||||||
return (float) m_TheoraInfo.fps_denominator / m_TheoraInfo.fps_numerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovieDecoder_Theora::Close()
|
|
||||||
{
|
|
||||||
ogg_stream_clear( &m_OggStream );
|
|
||||||
theora_clear( &m_TheoraState );
|
|
||||||
theora_comment_clear( &m_TheoraComment );
|
|
||||||
theora_info_clear( &m_TheoraInfo );
|
|
||||||
ogg_sync_clear( &m_OggSync );
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <theora/codec.h>
|
|
||||||
#include <theora/theoradec.h>
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#pragma comment(lib, OGG_LIB_DIR "ogg_static.lib")
|
|
||||||
#pragma comment(lib, OGG_LIB_DIR "theorabase_static.lib")
|
|
||||||
#pragma comment(lib, OGG_LIB_DIR "theoradec_static.lib")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class MovieDecoder_Theora: public MovieDecoder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MovieDecoder_Theora();
|
|
||||||
~MovieDecoder_Theora();
|
|
||||||
|
|
||||||
RString Open( RString sFile );
|
|
||||||
void Close();
|
|
||||||
|
|
||||||
int GetFrame( RageSurface *pOut, float fTargetTime );
|
|
||||||
RageSurface *CreateCompatibleSurface( int iTextureWidth, int iTextureHeight, bool bPreferHighColor, MovieDecoderPixelFormatYCbCr &fmtout );
|
|
||||||
|
|
||||||
int GetWidth() const { return m_TheoraInfo.frame_width; }
|
|
||||||
int GetHeight() const { return m_TheoraInfo.frame_height; }
|
|
||||||
float GetSourceAspectRatio() const;
|
|
||||||
|
|
||||||
float GetTimestamp() const;
|
|
||||||
float GetFrameDuration() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void Init();
|
|
||||||
RString ProcessHeaders( theora_setup_info **pTheoraSetupInfo );
|
|
||||||
int ReadPage( ogg_page *pOggPage, RString &sError, bool bInitializing );
|
|
||||||
static void DecodeStripeStub( void *pCtx, theora_ycbcr_buffer yuv, int yfrag0, int yfrag_end );
|
|
||||||
void DecodeStripe( theora_ycbcr_buffer yuv, int yfrag0, int yfrag_end );
|
|
||||||
|
|
||||||
RageFile m_File;
|
|
||||||
|
|
||||||
ogg_sync_state m_OggSync;
|
|
||||||
ogg_stream_state m_OggStream;
|
|
||||||
theora_info m_TheoraInfo;
|
|
||||||
theora_comment m_TheoraComment;
|
|
||||||
theora_dec_ctx *m_TheoraState;
|
|
||||||
|
|
||||||
ogg_int64_t m_iGranulepos;
|
|
||||||
|
|
||||||
avcodec::PixelFormat m_InputPixFmt; /* PixelFormat of YUV input surface */
|
|
||||||
avcodec::PixelFormat m_OutputPixFmt; /* PixelFormat of RGB output surface */
|
|
||||||
|
|
||||||
/* This is only set during GetFrame, for DecodeStripe. */
|
|
||||||
RageSurface *m_pSurface;
|
|
||||||
};
|
|
||||||
|
|
||||||
MovieDecoder_Theora::MovieDecoder_Theora()
|
|
||||||
{
|
|
||||||
avcodec::avcodec_init();
|
|
||||||
|
|
||||||
memset( &m_TheoraInfo, 0, sizeof(m_TheoraInfo) );
|
|
||||||
memset( &m_TheoraComment, 0, sizeof(m_TheoraComment) );
|
|
||||||
memset( &m_OggStream, 0, sizeof(m_OggStream) );
|
|
||||||
m_TheoraState = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
MovieDecoder_Theora::~MovieDecoder_Theora()
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovieDecoder_Theora::Init()
|
|
||||||
{
|
|
||||||
theora_info_init( &m_TheoraInfo );
|
|
||||||
theora_comment_init( &m_TheoraComment );
|
|
||||||
ogg_sync_init( &m_OggSync );
|
|
||||||
}
|
|
||||||
|
|
||||||
int MovieDecoder_Theora::ReadPage( ogg_page *pOggPage, RString &sError, bool bInitializing )
|
|
||||||
{
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
int iRet = ogg_sync_pageout( &m_OggSync, pOggPage );
|
|
||||||
if( iRet > 0 )
|
|
||||||
return iRet;
|
|
||||||
if( iRet < 0 )
|
|
||||||
{
|
|
||||||
if( bInitializing )
|
|
||||||
{
|
|
||||||
sError = "not an Ogg file";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG->Trace( "%s: hole in stream", m_File.GetPath().c_str() );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( iRet == 0 )
|
|
||||||
{
|
|
||||||
char *pBuffer = ogg_sync_buffer( &m_OggSync, 4096 );
|
|
||||||
int iBytes = m_File.Read( pBuffer, 4096 );
|
|
||||||
if( iBytes == 0 )
|
|
||||||
return 0;
|
|
||||||
if( iBytes == -1 )
|
|
||||||
{
|
|
||||||
sError = ssprintf( "error reading: %s", m_File.GetError().c_str() );
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ogg_sync_wrote( &m_OggSync, iBytes );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RString MovieDecoder_Theora::ProcessHeaders( theora_setup_info **pTheoraSetupInfo )
|
|
||||||
{
|
|
||||||
int iTheoraPacketsProcessed = 0;
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
ogg_page OggPage;
|
|
||||||
RString sError;
|
|
||||||
int ret = ReadPage( &OggPage, sError, true );
|
|
||||||
if( ret == 0 )
|
|
||||||
return ssprintf( "error opening %s: EOF while searching for codec headers", m_File.GetPath().c_str() );
|
|
||||||
if( ret<0 )
|
|
||||||
return ssprintf( "error reading %s: %s", m_File.GetPath().c_str(), sError.c_str() );
|
|
||||||
|
|
||||||
if( m_OggStream.body_data == NULL )
|
|
||||||
{
|
|
||||||
/* We don't have a stream yet. If this packet doesn't start a stream,
|
|
||||||
* then there aren't any Theora streams. */
|
|
||||||
if( !ogg_page_bos(&OggPage) )
|
|
||||||
return ssprintf( "error opening %s: no Theora streams found", m_File.GetPath().c_str() );
|
|
||||||
|
|
||||||
ogg_stream_init( &m_OggStream, ogg_page_serialno(&OggPage) );
|
|
||||||
ogg_stream_pagein( &m_OggStream, &OggPage );
|
|
||||||
ogg_packet op;
|
|
||||||
ogg_stream_packetout( &m_OggStream, &op );
|
|
||||||
|
|
||||||
if( theora_decode_headerin(&m_TheoraInfo, &m_TheoraComment, pTheoraSetupInfo, &op) < 0 )
|
|
||||||
{
|
|
||||||
ogg_stream_clear( &m_OggStream );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We've found the Theora stream. */
|
|
||||||
iTheoraPacketsProcessed++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ogg_stream_pagein( &m_OggStream, &OggPage );
|
|
||||||
|
|
||||||
/* Look for more headers in this page. */
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
ogg_packet op;
|
|
||||||
int ret = ogg_stream_packetpeek( &m_OggStream, &op );
|
|
||||||
if( ret == 0 )
|
|
||||||
break;
|
|
||||||
if( ret < 0 )
|
|
||||||
return ssprintf( "error opening %s: error parsing Theora stream headers", m_File.GetPath().c_str() );
|
|
||||||
|
|
||||||
if( !theora_packet_isheader(&op) )
|
|
||||||
{
|
|
||||||
/* This is a body packet, not a header packet, so we're done processing
|
|
||||||
* headers. We must have at least three header packets. */
|
|
||||||
if( iTheoraPacketsProcessed < 3 )
|
|
||||||
return ssprintf( "error opening %s: error parsing Theora stream headers", m_File.GetPath().c_str() );
|
|
||||||
return RString();
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = theora_decode_headerin( &m_TheoraInfo, &m_TheoraComment, pTheoraSetupInfo, &op );
|
|
||||||
if( ret < 0 )
|
|
||||||
return ssprintf( "error opening %s: error parsing Theora stream headers", m_File.GetPath().c_str() );
|
|
||||||
|
|
||||||
ogg_stream_packetout( &m_OggStream, NULL );
|
|
||||||
iTheoraPacketsProcessed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RString MovieDecoder_Theora::Open( RString sFile )
|
|
||||||
{
|
|
||||||
if( !m_File.Open(sFile) )
|
|
||||||
return ssprintf( "error opening %s: %s", sFile.c_str(), m_File.GetError().c_str() );
|
|
||||||
|
|
||||||
Init();
|
|
||||||
|
|
||||||
theora_setup_info *pTheoraSetupInfo = NULL;
|
|
||||||
RString sError = ProcessHeaders( &pTheoraSetupInfo );
|
|
||||||
if( !sError.empty() )
|
|
||||||
{
|
|
||||||
theora_setup_free( pTheoraSetupInfo );
|
|
||||||
return sError;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_TheoraState = theora_decode_alloc( &m_TheoraInfo, pTheoraSetupInfo );
|
|
||||||
theora_setup_free( pTheoraSetupInfo );
|
|
||||||
|
|
||||||
RString sOutput = ssprintf( "MovieDecoder_Theora: Opened \"%s\". Serial: 0x%08lx, FPS: %.02f",
|
|
||||||
m_File.GetPath().c_str(), m_OggStream.serialno, 1/GetFrameDuration() );
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
m_InputPixFmt = avcodec::PIX_FMT_YUV420P;
|
|
||||||
#else
|
|
||||||
switch( m_TheoraInfo.pixelformat )
|
|
||||||
{
|
|
||||||
case OC_PF_420:
|
|
||||||
m_InputPixFmt = avcodec::PIX_FMT_YUV420P;
|
|
||||||
sOutput += ", Format: YUV420";
|
|
||||||
break;
|
|
||||||
case OC_PF_422:
|
|
||||||
m_InputPixFmt = avcodec::PIX_FMT_YUV422P;
|
|
||||||
sOutput += ", Format: YUV422";
|
|
||||||
break;
|
|
||||||
case OC_PF_444:
|
|
||||||
m_InputPixFmt = avcodec::PIX_FMT_YUV444P;
|
|
||||||
sOutput += ", Format: YUV444";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return ssprintf( "error opening %s: unsupported pixel format %i", m_File.GetPath().c_str(), m_TheoraInfo.pixelformat );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
LOG->Trace( "%s", sOutput.c_str() );
|
|
||||||
|
|
||||||
{
|
|
||||||
theora_stripe_callback cb;
|
|
||||||
cb.ctx = this;
|
|
||||||
cb.stripe_decoded = DecodeStripeStub;
|
|
||||||
theora_decode_ctl( m_TheoraState, OC_DECCTL_SET_STRIPE_CB, &cb, sizeof(cb) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return RString();
|
|
||||||
}
|
|
||||||
|
|
||||||
int MovieDecoder_Theora::GetFrame( RageSurface *pOut, float fTargetTime )
|
|
||||||
{
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
ogg_packet op;
|
|
||||||
if( ogg_stream_packetout(&m_OggStream, &op) != 0 )
|
|
||||||
{
|
|
||||||
bool bSkipThisFrame = false;
|
|
||||||
if( fTargetTime != -1 &&
|
|
||||||
GetTimestamp() + GetFrameDuration() <= fTargetTime )
|
|
||||||
{
|
|
||||||
ogg_int64_t iFrame = theora_granule_frame( m_TheoraState, op.granulepos );
|
|
||||||
if( (iFrame % 2) == 0 )
|
|
||||||
bSkipThisFrame = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( bSkipThisFrame )
|
|
||||||
m_pSurface = NULL;
|
|
||||||
else
|
|
||||||
m_pSurface = pOut;
|
|
||||||
|
|
||||||
theora_decode_packetin( m_TheoraState, &op, &m_iGranulepos );
|
|
||||||
|
|
||||||
m_pSurface = NULL;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read more data. */
|
|
||||||
ogg_page OggPage;
|
|
||||||
RString sError;
|
|
||||||
int ret = ReadPage( &OggPage, sError, false );
|
|
||||||
if( ret == 0 )
|
|
||||||
return 0;
|
|
||||||
if( ret == -1 )
|
|
||||||
{
|
|
||||||
LOG->Warn( "error reading %s: %s", m_File.GetPath().c_str(), sError.c_str() );
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if( ret > 0 )
|
|
||||||
ogg_stream_pagein( &m_OggStream, &OggPage );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RageSurface *MovieDecoder_Theora::CreateCompatibleSurface( int iTextureWidth, int iTextureHeight, bool bPreferHighColor, MovieDecoderPixelFormatYCbCr &fmtout )
|
|
||||||
{
|
|
||||||
return MovieTexture_FFMpeg::AVCodecCreateCompatibleSurface( iTextureWidth, iTextureHeight, bPreferHighColor, *ConvertValue<int>(&m_OutputPixFmt) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovieDecoder_Theora::DecodeStripeStub( void *pCtx, theora_ycbcr_buffer yuv, int yfrag0, int yfrag_end )
|
|
||||||
{
|
|
||||||
((MovieDecoder_Theora *) pCtx)->DecodeStripe( yuv, yfrag0, yfrag_end );
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovieDecoder_Theora::DecodeStripe( theora_ycbcr_buffer yuv, int yfrag0, int yfrag_end )
|
|
||||||
{
|
|
||||||
yfrag0 *= 8;
|
|
||||||
yfrag_end *= 8;
|
|
||||||
|
|
||||||
/* If m_pSurface is NULL, we're skipping this frame. */
|
|
||||||
if( m_pSurface != NULL )
|
|
||||||
{
|
|
||||||
/* XXX: non-zero offset untested */
|
|
||||||
int iYOffsetY = m_TheoraInfo.pic_y;
|
|
||||||
int iUVOffsetX = m_TheoraInfo.pic_x;
|
|
||||||
int iUVOffsetY = m_TheoraInfo.pic_y;
|
|
||||||
|
|
||||||
iYOffsetY += yfrag0;
|
|
||||||
iUVOffsetY += yfrag0;
|
|
||||||
|
|
||||||
if( m_InputPixFmt == avcodec::PIX_FMT_YUV420P || avcodec::PIX_FMT_YUV422P )
|
|
||||||
iUVOffsetX /= 2;
|
|
||||||
if( m_InputPixFmt == avcodec::PIX_FMT_YUV420P )
|
|
||||||
iUVOffsetY /= 2;
|
|
||||||
|
|
||||||
avcodec::AVPicture YUVIn;
|
|
||||||
YUVIn.data[0] = yuv[0].data + m_TheoraInfo.pic_x + yuv[0].ystride*iYOffsetY;
|
|
||||||
YUVIn.data[1] = yuv[1].data + iUVOffsetX + yuv[1].ystride*iUVOffsetY;
|
|
||||||
YUVIn.data[2] = yuv[2].data + iUVOffsetX + yuv[2].ystride*iUVOffsetY;
|
|
||||||
YUVIn.data[3] = NULL;
|
|
||||||
YUVIn.linesize[0] = yuv[0].ystride;
|
|
||||||
YUVIn.linesize[1] = yuv[1].ystride;
|
|
||||||
YUVIn.linesize[2] = yuv[2].ystride;
|
|
||||||
YUVIn.linesize[3] = 0;
|
|
||||||
|
|
||||||
avcodec::AVPicture RGBOut;
|
|
||||||
RGBOut.data[0] = (unsigned char *) m_pSurface->pixels;
|
|
||||||
RGBOut.linesize[0] = m_pSurface->pitch;
|
|
||||||
RGBOut.data[0] += RGBOut.linesize[0] * yfrag0;
|
|
||||||
|
|
||||||
int iRows = (yfrag_end-yfrag0) + 1;
|
|
||||||
// sm4svn code:
|
|
||||||
#if defined(MACOSX)
|
|
||||||
avcodec::img_convert( &RGBOut, m_OutputPixFmt,
|
|
||||||
&YUVIn, m_InputPixFmt,
|
|
||||||
m_TheoraInfo.frame_width, iRows );
|
|
||||||
#else
|
|
||||||
ConvertImage( YUVIn, RGBOut, iRows );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
/* yfrag0 = 0 ... frame_height-1 */
|
|
||||||
int iHalf = m_TheoraInfo.frame_height / 2;
|
|
||||||
if( yfrag0 < iHalf && yfrag_end+1 >= iHalf )
|
|
||||||
{
|
|
||||||
float fFPS = (float)m_TheoraInfo.fps_numerator / m_TheoraInfo.fps_denominator;
|
|
||||||
if( fFPS <= 30.0001f )
|
|
||||||
{
|
|
||||||
// LOG->Trace( "..." );
|
|
||||||
float fSecondsPerFrame = 1/fFPS;
|
|
||||||
int iUsecPerFrame = int(fSecondsPerFrame * 1000000);
|
|
||||||
// usleep( iUsecPerFrame/2 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float MovieDecoder_Theora::GetSourceAspectRatio() const
|
|
||||||
{
|
|
||||||
return (float) m_TheoraInfo.aspect_numerator / m_TheoraInfo.aspect_denominator;
|
|
||||||
}
|
|
||||||
|
|
||||||
float MovieDecoder_Theora::GetTimestamp() const
|
|
||||||
{
|
|
||||||
return (float) theora_granule_time( const_cast<theora_dec_ctx *>(m_TheoraState), m_iGranulepos );
|
|
||||||
}
|
|
||||||
|
|
||||||
float MovieDecoder_Theora::GetFrameDuration() const
|
|
||||||
{
|
|
||||||
return (float) m_TheoraInfo.fps_denominator / m_TheoraInfo.fps_numerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovieDecoder_Theora::Close()
|
|
||||||
{
|
|
||||||
ogg_stream_clear( &m_OggStream );
|
|
||||||
theora_decode_free( m_TheoraState );
|
|
||||||
m_TheoraState = NULL;
|
|
||||||
theora_comment_clear( &m_TheoraComment );
|
|
||||||
theora_info_clear( &m_TheoraInfo );
|
|
||||||
ogg_sync_clear( &m_OggSync );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class MovieTexture_Theora: public MovieTexture_Generic
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MovieTexture_Theora( RageTextureID ID );
|
|
||||||
};
|
|
||||||
|
|
||||||
MovieTexture_Theora::MovieTexture_Theora( RageTextureID ID ):
|
|
||||||
MovieTexture_Generic( ID, new MovieDecoder_Theora )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RageMovieTexture *RageMovieTextureDriver_Theora::Create( RageTextureID ID, RString &sError )
|
|
||||||
{
|
|
||||||
MovieTexture_Theora *pRet = new MovieTexture_Theora( ID );
|
|
||||||
sError = pRet->Init();
|
|
||||||
if( !sError.empty() )
|
|
||||||
SAFE_DELETE( pRet );
|
|
||||||
return pRet;
|
|
||||||
}
|
|
||||||
|
|
||||||
REGISTER_MOVIE_TEXTURE_CLASS( Theora );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (c) 2005 Glenn Maynard
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the
|
|
||||||
* "Software"), to deal in the Software without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
|
||||||
* whom the Software is furnished to do so, provided that the above
|
|
||||||
* copyright notice(s) and this permission notice appear in all copies of
|
|
||||||
* the Software and that both the above copyright notice(s) and this
|
|
||||||
* permission notice appear in supporting documentation.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
|
||||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
|
||||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
|
|
||||||
*/
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
/* MovieTexture_Theora - Ogg Theora movie renderer. */
|
|
||||||
|
|
||||||
#ifndef RAGE_MOVIE_TEXTURE_THEORA_H
|
|
||||||
#define RAGE_MOVIE_TEXTURE_THEORA_H
|
|
||||||
|
|
||||||
#include "MovieTexture_Generic.h"
|
|
||||||
|
|
||||||
class RageMovieTextureDriver_Theora: public RageMovieTextureDriver
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual RageMovieTexture *Create( RageTextureID ID, RString &sError );
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (c) 2005 Glenn Maynard
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the
|
|
||||||
* "Software"), to deal in the Software without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
|
||||||
* whom the Software is furnished to do so, provided that the above
|
|
||||||
* copyright notice(s) and this permission notice appear in all copies of
|
|
||||||
* the Software and that both the above copyright notice(s) and this
|
|
||||||
* permission notice appear in supporting documentation.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
|
||||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
|
||||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
|
|
||||||
*/
|
|
||||||
@@ -195,9 +195,6 @@ RageMovieTexture *MakeRageMovieTexture( RageTextureID ID )
|
|||||||
{
|
{
|
||||||
Driver = DriversToTry[i];
|
Driver = DriversToTry[i];
|
||||||
LOG->Trace( "Initializing driver: %s", Driver.c_str() );
|
LOG->Trace( "Initializing driver: %s", Driver.c_str() );
|
||||||
#ifdef USE_MOVIE_TEXTURE_THEORA
|
|
||||||
if( !Driver.CompareNoCase("Theora") ) ret = new MovieTexture_Theora(ID);
|
|
||||||
#endif
|
|
||||||
#ifdef USE_MOVIE_TEXTURE_DSHOW
|
#ifdef USE_MOVIE_TEXTURE_DSHOW
|
||||||
if( !Driver.CompareNoCase("DShow") ) ret = new MovieTexture_DShow(ID);
|
if( !Driver.CompareNoCase("DShow") ) ret = new MovieTexture_DShow(ID);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "LowLevelWindow/LowLevelWindow_Win32.h"
|
#include "LowLevelWindow/LowLevelWindow_Win32.h"
|
||||||
#include "MemoryCard/MemoryCardDriverThreaded_Windows.h"
|
#include "MemoryCard/MemoryCardDriverThreaded_Windows.h"
|
||||||
#define DEFAULT_INPUT_DRIVER_LIST "DirectInput,Pump,Para"
|
#define DEFAULT_INPUT_DRIVER_LIST "DirectInput,Pump,Para"
|
||||||
#define DEFAULT_MOVIE_DRIVER_LIST "Theora,FFMpeg,DShow,Null"
|
#define DEFAULT_MOVIE_DRIVER_LIST "FFMpeg,DShow,Null"
|
||||||
#define DEFAULT_SOUND_DRIVER_LIST "DirectSound-sw,WDMKS,WaveOut,Null"
|
#define DEFAULT_SOUND_DRIVER_LIST "DirectSound-sw,WDMKS,WaveOut,Null"
|
||||||
|
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
#include "LowLevelWindow/LowLevelWindow_MacOSX.h"
|
#include "LowLevelWindow/LowLevelWindow_MacOSX.h"
|
||||||
#include "MemoryCard/MemoryCardDriverThreaded_MacOSX.h"
|
#include "MemoryCard/MemoryCardDriverThreaded_MacOSX.h"
|
||||||
#define DEFAULT_INPUT_DRIVER_LIST "HID"
|
#define DEFAULT_INPUT_DRIVER_LIST "HID"
|
||||||
#define DEFAULT_MOVIE_DRIVER_LIST "Theora,FFMpeg,Null"
|
#define DEFAULT_MOVIE_DRIVER_LIST "FFMpeg,Null"
|
||||||
#define DEFAULT_SOUND_DRIVER_LIST "AudioUnit,Null"
|
#define DEFAULT_SOUND_DRIVER_LIST "AudioUnit,Null"
|
||||||
|
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
#else
|
#else
|
||||||
#define DEFAULT_INPUT_DRIVER_LIST "X11"
|
#define DEFAULT_INPUT_DRIVER_LIST "X11"
|
||||||
#endif
|
#endif
|
||||||
#define DEFAULT_MOVIE_DRIVER_LIST "Theora,FFMpeg,Null"
|
#define DEFAULT_MOVIE_DRIVER_LIST "FFMpeg,Null"
|
||||||
#define DEFAULT_SOUND_DRIVER_LIST "ALSA-sw,pulse,OSS,Null"
|
#define DEFAULT_SOUND_DRIVER_LIST "ALSA-sw,pulse,OSS,Null"
|
||||||
#else
|
#else
|
||||||
#error Which arch?
|
#error Which arch?
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ extern "C" int SM_main( int argc, char *argv[] );
|
|||||||
|
|
||||||
#define HAVE_VERSION_INFO
|
#define HAVE_VERSION_INFO
|
||||||
#define HAVE_CXA_DEMANGLE
|
#define HAVE_CXA_DEMANGLE
|
||||||
#define HAVE_THEORA
|
|
||||||
#define HAVE_FFMPEG
|
#define HAVE_FFMPEG
|
||||||
#define HAVE_PTHREAD_COND_TIMEDWAIT
|
#define HAVE_PTHREAD_COND_TIMEDWAIT
|
||||||
/* This must be defined to 1 because autoconf's AC_CHECK_DECLS macro decides to define
|
/* This must be defined to 1 because autoconf's AC_CHECK_DECLS macro decides to define
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#define ARCH_SETUP_WINDOWS_H
|
#define ARCH_SETUP_WINDOWS_H
|
||||||
|
|
||||||
#define HAVE_FFMPEG
|
#define HAVE_FFMPEG
|
||||||
#define HAVE_THEORA
|
|
||||||
|
|
||||||
#define SUPPORT_OPENGL
|
#define SUPPORT_OPENGL
|
||||||
#define SUPPORT_D3D
|
#define SUPPORT_D3D
|
||||||
|
|||||||
Reference in New Issue
Block a user