summaryrefslogtreecommitdiff
path: root/vpxenc.c
diff options
context:
space:
mode:
authorTom Finegan <tomfinegan@google.com>2013-11-05 10:02:18 -0800
committerTom Finegan <tomfinegan@google.com>2013-11-06 06:49:55 -0800
commit03848f5ca744e10238d5bc3f62491ae5934a2371 (patch)
tree476720ae72d32036e0b102cec5c44641993e0500 /vpxenc.c
parentdde8069e5731a49ea520ce7f796d046f28912a86 (diff)
downloadlibvpx-03848f5ca744e10238d5bc3f62491ae5934a2371.tar
libvpx-03848f5ca744e10238d5bc3f62491ae5934a2371.tar.gz
libvpx-03848f5ca744e10238d5bc3f62491ae5934a2371.tar.bz2
libvpx-03848f5ca744e10238d5bc3f62491ae5934a2371.zip
Move WebM writing support out of vpxenc.c.
This is mainly a clean up patchset. It moves the WebM writing support out of vpxenc and into its own source file. Changes to tools_common and vpxdec result from relocation of shared bits of code. Change-Id: Iee55d3285f56e0a548f791094fb14c5ac5346a26
Diffstat (limited to 'vpxenc.c')
-rw-r--r--vpxenc.c423
1 files changed, 6 insertions, 417 deletions
diff --git a/vpxenc.c b/vpxenc.c
index aa99c6b7c..df75b853a 100644
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -34,6 +34,8 @@
#include <unistd.h>
#endif
+#include "third_party/libyuv/include/libyuv/scale.h"
+
#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
#include "vpx/vp8cx.h"
#endif
@@ -44,10 +46,9 @@
#include "vpx_ports/mem_ops.h"
#include "vpx_ports/vpx_timer.h"
#include "tools_common.h"
+#include "webmenc.h"
#include "y4minput.h"
-#include "third_party/libmkv/EbmlWriter.h"
-#include "third_party/libmkv/EbmlIDs.h"
-#include "third_party/libyuv/include/libyuv/scale.h"
+
/* Need special handling of these functions on Windows */
#if defined(_MSC_VER)
@@ -89,8 +90,6 @@ static size_t wrap_fwrite(const void *ptr, size_t size, size_t nmemb,
static const char *exec_name;
-#define VP8_FOURCC (0x30385056)
-#define VP9_FOURCC (0x30395056)
static const struct codec_item {
char const *name;
const vpx_codec_iface_t *(*iface)(void);
@@ -109,37 +108,6 @@ static const struct codec_item {
#endif
};
-static void usage_exit();
-
-#define LOG_ERROR(label) do \
- {\
- const char *l=label;\
- va_list ap;\
- va_start(ap, fmt);\
- if(l)\
- fprintf(stderr, "%s: ", l);\
- vfprintf(stderr, fmt, ap);\
- fprintf(stderr, "\n");\
- va_end(ap);\
- } while(0)
-
-void die(const char *fmt, ...) {
- LOG_ERROR(NULL);
- usage_exit();
-}
-
-
-void fatal(const char *fmt, ...) {
- LOG_ERROR("Fatal");
- exit(EXIT_FAILURE);
-}
-
-
-void warn(const char *fmt, ...) {
- LOG_ERROR("Warning");
-}
-
-
static void warn_or_exit_on_errorv(vpx_codec_ctx_t *ctx, int fatal,
const char *s, va_list ap) {
if (ctx->err) {
@@ -293,15 +261,6 @@ vpx_fixed_buf_t stats_get(stats_io_t *stats) {
return stats->buf;
}
-/* Stereo 3D packed frame format */
-typedef enum stereo_format {
- STEREO_FORMAT_MONO = 0,
- STEREO_FORMAT_LEFT_RIGHT = 1,
- STEREO_FORMAT_BOTTOM_TOP = 2,
- STEREO_FORMAT_TOP_BOTTOM = 3,
- STEREO_FORMAT_RIGHT_LEFT = 11
-} stereo_format_t;
-
enum video_file_type {
FILE_TYPE_RAW,
FILE_TYPE_IVF,
@@ -496,376 +455,6 @@ static void write_ivf_frame_size(FILE *outfile, size_t size) {
}
-typedef off_t EbmlLoc;
-
-
-struct cue_entry {
- unsigned int time;
- uint64_t loc;
-};
-
-
-struct EbmlGlobal {
- int debug;
-
- FILE *stream;
- int64_t last_pts_ms;
- vpx_rational_t framerate;
-
- /* These pointers are to the start of an element */
- off_t position_reference;
- off_t seek_info_pos;
- off_t segment_info_pos;
- off_t track_pos;
- off_t cue_pos;
- off_t cluster_pos;
-
- /* This pointer is to a specific element to be serialized */
- off_t track_id_pos;
-
- /* These pointers are to the size field of the element */
- EbmlLoc startSegment;
- EbmlLoc startCluster;
-
- uint32_t cluster_timecode;
- int cluster_open;
-
- struct cue_entry *cue_list;
- unsigned int cues;
-
-};
-
-
-void Ebml_Write(EbmlGlobal *glob, const void *buffer_in, unsigned long len) {
- (void) fwrite(buffer_in, 1, len, glob->stream);
-}
-
-#define WRITE_BUFFER(s) \
- for(i = len-1; i>=0; i--)\
- { \
- x = (char)(*(const s *)buffer_in >> (i * CHAR_BIT)); \
- Ebml_Write(glob, &x, 1); \
- }
-void Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in, int buffer_size, unsigned long len) {
- char x;
- int i;
-
- /* buffer_size:
- * 1 - int8_t;
- * 2 - int16_t;
- * 3 - int32_t;
- * 4 - int64_t;
- */
- switch (buffer_size) {
- case 1:
- WRITE_BUFFER(int8_t)
- break;
- case 2:
- WRITE_BUFFER(int16_t)
- break;
- case 4:
- WRITE_BUFFER(int32_t)
- break;
- case 8:
- WRITE_BUFFER(int64_t)
- break;
- default:
- break;
- }
-}
-#undef WRITE_BUFFER
-
-/* Need a fixed size serializer for the track ID. libmkv provides a 64 bit
- * one, but not a 32 bit one.
- */
-static void Ebml_SerializeUnsigned32(EbmlGlobal *glob, unsigned long class_id, uint64_t ui) {
- unsigned char sizeSerialized = 4 | 0x80;
- Ebml_WriteID(glob, class_id);
- Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
- Ebml_Serialize(glob, &ui, sizeof(ui), 4);
-}
-
-
-static void
-Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc,
- unsigned long class_id) {
- /* todo this is always taking 8 bytes, this may need later optimization */
- /* this is a key that says length unknown */
- uint64_t unknownLen = LITERALU64(0x01FFFFFF, 0xFFFFFFFF);
-
- Ebml_WriteID(glob, class_id);
- *ebmlLoc = ftello(glob->stream);
- Ebml_Serialize(glob, &unknownLen, sizeof(unknownLen), 8);
-}
-
-static void
-Ebml_EndSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc) {
- off_t pos;
- uint64_t size;
-
- /* Save the current stream pointer */
- pos = ftello(glob->stream);
-
- /* Calculate the size of this element */
- size = pos - *ebmlLoc - 8;
- size |= LITERALU64(0x01000000, 0x00000000);
-
- /* Seek back to the beginning of the element and write the new size */
- fseeko(glob->stream, *ebmlLoc, SEEK_SET);
- Ebml_Serialize(glob, &size, sizeof(size), 8);
-
- /* Reset the stream pointer */
- fseeko(glob->stream, pos, SEEK_SET);
-}
-
-
-static void
-write_webm_seek_element(EbmlGlobal *ebml, unsigned long id, off_t pos) {
- uint64_t offset = pos - ebml->position_reference;
- EbmlLoc start;
- Ebml_StartSubElement(ebml, &start, Seek);
- Ebml_SerializeBinary(ebml, SeekID, id);
- Ebml_SerializeUnsigned64(ebml, SeekPosition, offset);
- Ebml_EndSubElement(ebml, &start);
-}
-
-
-static void
-write_webm_seek_info(EbmlGlobal *ebml) {
-
- off_t pos;
-
- /* Save the current stream pointer */
- pos = ftello(ebml->stream);
-
- if (ebml->seek_info_pos)
- fseeko(ebml->stream, ebml->seek_info_pos, SEEK_SET);
- else
- ebml->seek_info_pos = pos;
-
- {
- EbmlLoc start;
-
- Ebml_StartSubElement(ebml, &start, SeekHead);
- write_webm_seek_element(ebml, Tracks, ebml->track_pos);
- write_webm_seek_element(ebml, Cues, ebml->cue_pos);
- write_webm_seek_element(ebml, Info, ebml->segment_info_pos);
- Ebml_EndSubElement(ebml, &start);
- }
- {
- /* segment info */
- EbmlLoc startInfo;
- uint64_t frame_time;
- char version_string[64];
-
- /* Assemble version string */
- if (ebml->debug)
- strcpy(version_string, "vpxenc");
- else {
- strcpy(version_string, "vpxenc ");
- strncat(version_string,
- vpx_codec_version_str(),
- sizeof(version_string) - 1 - strlen(version_string));
- }
-
- frame_time = (uint64_t)1000 * ebml->framerate.den
- / ebml->framerate.num;
- ebml->segment_info_pos = ftello(ebml->stream);
- Ebml_StartSubElement(ebml, &startInfo, Info);
- Ebml_SerializeUnsigned(ebml, TimecodeScale, 1000000);
- Ebml_SerializeFloat(ebml, Segment_Duration,
- (double)(ebml->last_pts_ms + frame_time));
- Ebml_SerializeString(ebml, 0x4D80, version_string);
- Ebml_SerializeString(ebml, 0x5741, version_string);
- Ebml_EndSubElement(ebml, &startInfo);
- }
-}
-
-
-static void
-write_webm_file_header(EbmlGlobal *glob,
- const vpx_codec_enc_cfg_t *cfg,
- const struct vpx_rational *fps,
- stereo_format_t stereo_fmt,
- unsigned int fourcc) {
- {
- EbmlLoc start;
- Ebml_StartSubElement(glob, &start, EBML);
- Ebml_SerializeUnsigned(glob, EBMLVersion, 1);
- Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1);
- Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4);
- Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8);
- Ebml_SerializeString(glob, DocType, "webm");
- Ebml_SerializeUnsigned(glob, DocTypeVersion, 2);
- Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2);
- Ebml_EndSubElement(glob, &start);
- }
- {
- Ebml_StartSubElement(glob, &glob->startSegment, Segment);
- glob->position_reference = ftello(glob->stream);
- glob->framerate = *fps;
- write_webm_seek_info(glob);
-
- {
- EbmlLoc trackStart;
- glob->track_pos = ftello(glob->stream);
- Ebml_StartSubElement(glob, &trackStart, Tracks);
- {
- unsigned int trackNumber = 1;
- uint64_t trackID = 0;
-
- EbmlLoc start;
- Ebml_StartSubElement(glob, &start, TrackEntry);
- Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
- glob->track_id_pos = ftello(glob->stream);
- Ebml_SerializeUnsigned32(glob, TrackUID, trackID);
- Ebml_SerializeUnsigned(glob, TrackType, 1);
- Ebml_SerializeString(glob, CodecID,
- fourcc == VP8_FOURCC ? "V_VP8" : "V_VP9");
- {
- unsigned int pixelWidth = cfg->g_w;
- unsigned int pixelHeight = cfg->g_h;
-
- EbmlLoc videoStart;
- Ebml_StartSubElement(glob, &videoStart, Video);
- Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
- Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
- Ebml_SerializeUnsigned(glob, StereoMode, stereo_fmt);
- Ebml_EndSubElement(glob, &videoStart);
- }
- Ebml_EndSubElement(glob, &start); /* Track Entry */
- }
- Ebml_EndSubElement(glob, &trackStart);
- }
- /* segment element is open */
- }
-}
-
-
-static void
-write_webm_block(EbmlGlobal *glob,
- const vpx_codec_enc_cfg_t *cfg,
- const vpx_codec_cx_pkt_t *pkt) {
- unsigned long block_length;
- unsigned char track_number;
- unsigned short block_timecode = 0;
- unsigned char flags;
- int64_t pts_ms;
- int start_cluster = 0, is_keyframe;
-
- /* Calculate the PTS of this frame in milliseconds */
- pts_ms = pkt->data.frame.pts * 1000
- * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den;
- if (pts_ms <= glob->last_pts_ms)
- pts_ms = glob->last_pts_ms + 1;
- glob->last_pts_ms = pts_ms;
-
- /* Calculate the relative time of this block */
- if (pts_ms - glob->cluster_timecode > SHRT_MAX)
- start_cluster = 1;
- else
- block_timecode = (unsigned short)pts_ms - glob->cluster_timecode;
-
- is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY);
- if (start_cluster || is_keyframe) {
- if (glob->cluster_open)
- Ebml_EndSubElement(glob, &glob->startCluster);
-
- /* Open the new cluster */
- block_timecode = 0;
- glob->cluster_open = 1;
- glob->cluster_timecode = (uint32_t)pts_ms;
- glob->cluster_pos = ftello(glob->stream);
- Ebml_StartSubElement(glob, &glob->startCluster, Cluster); /* cluster */
- Ebml_SerializeUnsigned(glob, Timecode, glob->cluster_timecode);
-
- /* Save a cue point if this is a keyframe. */
- if (is_keyframe) {
- struct cue_entry *cue, *new_cue_list;
-
- new_cue_list = realloc(glob->cue_list,
- (glob->cues + 1) * sizeof(struct cue_entry));
- if (new_cue_list)
- glob->cue_list = new_cue_list;
- else
- fatal("Failed to realloc cue list.");
-
- cue = &glob->cue_list[glob->cues];
- cue->time = glob->cluster_timecode;
- cue->loc = glob->cluster_pos;
- glob->cues++;
- }
- }
-
- /* Write the Simple Block */
- Ebml_WriteID(glob, SimpleBlock);
-
- block_length = (unsigned long)pkt->data.frame.sz + 4;
- block_length |= 0x10000000;
- Ebml_Serialize(glob, &block_length, sizeof(block_length), 4);
-
- track_number = 1;
- track_number |= 0x80;
- Ebml_Write(glob, &track_number, 1);
-
- Ebml_Serialize(glob, &block_timecode, sizeof(block_timecode), 2);
-
- flags = 0;
- if (is_keyframe)
- flags |= 0x80;
- if (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE)
- flags |= 0x08;
- Ebml_Write(glob, &flags, 1);
-
- Ebml_Write(glob, pkt->data.frame.buf, (unsigned long)pkt->data.frame.sz);
-}
-
-
-static void
-write_webm_file_footer(EbmlGlobal *glob, long hash) {
-
- if (glob->cluster_open)
- Ebml_EndSubElement(glob, &glob->startCluster);
-
- {
- EbmlLoc start;
- unsigned int i;
-
- glob->cue_pos = ftello(glob->stream);
- Ebml_StartSubElement(glob, &start, Cues);
- for (i = 0; i < glob->cues; i++) {
- struct cue_entry *cue = &glob->cue_list[i];
- EbmlLoc start;
-
- Ebml_StartSubElement(glob, &start, CuePoint);
- {
- EbmlLoc start;
-
- Ebml_SerializeUnsigned(glob, CueTime, cue->time);
-
- Ebml_StartSubElement(glob, &start, CueTrackPositions);
- Ebml_SerializeUnsigned(glob, CueTrack, 1);
- Ebml_SerializeUnsigned64(glob, CueClusterPosition,
- cue->loc - glob->position_reference);
- Ebml_EndSubElement(glob, &start);
- }
- Ebml_EndSubElement(glob, &start);
- }
- Ebml_EndSubElement(glob, &start);
- }
-
- Ebml_EndSubElement(glob, &glob->startSegment);
-
- /* Patch up the seek info block */
- write_webm_seek_info(glob);
-
- /* Patch up the track id */
- fseeko(glob->stream, glob->track_id_pos, SEEK_SET);
- Ebml_SerializeUnsigned32(glob, TrackUID, glob->debug ? 0xDEADBEEF : hash);
-
- fseeko(glob->stream, 0, SEEK_END);
-}
-
/* Murmur hash derived from public domain reference implementation at
* http:// sites.google.com/site/murmurhash/
@@ -1172,7 +761,7 @@ static const int vp9_arg_ctrl_map[] = {
static const arg_def_t *no_args[] = { NULL };
-static void usage_exit() {
+void usage_exit() {
int i;
fprintf(stderr, "Usage: %s <options> -o dst_filename src_filename \n",
@@ -1647,7 +1236,7 @@ struct stream_state {
struct stream_config config;
FILE *file;
struct rate_hist rate_hist;
- EbmlGlobal ebml;
+ struct EbmlGlobal ebml;
uint32_t hash;
uint64_t psnr_sse_total;
uint64_t psnr_samples_total;