[xiph-commits] r16478 - branches/theora-monty-post-1-1/examples
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Wed Aug 12 23:13:10 PDT 2009
Author: xiphmont
Date: 2009-08-12 23:13:10 -0700 (Wed, 12 Aug 2009)
New Revision: 16478
Added:
branches/theora-monty-post-1-1/examples/y4o.c
Log:
How these got missed I cannot fathom
Added: branches/theora-monty-post-1-1/examples/y4o.c
===================================================================
--- branches/theora-monty-post-1-1/examples/y4o.c (rev 0)
+++ branches/theora-monty-post-1-1/examples/y4o.c 2009-08-13 06:13:10 UTC (rev 16478)
@@ -0,0 +1,614 @@
+/********************************************************************
+ * *
+ * 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-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function: yuv4ogg code to be used by example encoder application
+ last mod: $Id: y4o.c 16421 2009-08-05 17:28:35Z gmaxwell $
+
+ ********************************************************************/
+
+#if !defined(_REENTRANT)
+#define _REENTRANT
+#endif
+#if !defined(_GNU_SOURCE)
+#define _GNU_SOURCE
+#endif
+#if !defined(_LARGEFILE_SOURCE)
+#define _LARGEFILE_SOURCE
+#endif
+#if !defined(_LARGEFILE64_SOURCE)
+#define _LARGEFILE64_SOURCE
+#endif
+#if !defined(_FILE_OFFSET_BITS)
+#define _FILE_OFFSET_BITS 64
+#endif
+
+#include <stdio.h>
+#if !defined(_WIN32)
+#include <getopt.h>
+#include <unistd.h>
+#else
+#include "getopt.h"
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+#include "theora/theoraenc.h"
+#include "vorbis/codec.h"
+#include "vorbis/vorbisenc.h"
+#include "y4o.h"
+
+#define EPSILON 1e-6
+
+#ifdef _WIN32
+/*supply missing headers and functions to Win32. going to hell, I know*/
+#include <fcntl.h>
+#include <io.h>
+
+static double rint(double x)
+{
+ if (x < 0.0)
+ return (double)(int)(x - 0.5);
+ else
+ return (double)(int)(x + 0.5);
+}
+#endif
+
+static char *chromaformat[]={
+ "mono", //0
+ "411ntscdv", //1
+ "420jpeg", //2 chroma sample is centered vertically and horizontally between luma samples
+ "420mpeg2", //3 chroma sample is centered vertically between lines, cosited horizontally */
+ "420paldv", //4 chroma sample is cosited vertically and horizontally */
+ "420unknown",//5
+ "422jpeg", //6 chroma sample is horizontally centered between luma samples */
+ "422smpte", //7 chroma sample is cosited horizontally */
+ "422unknown",//8
+ "444", //9
+ "444alpha", //10
+ NULL
+};
+
+static unsigned char chromabits[]={
+ 8,
+ 12,
+ 12,
+ 12,
+ 12,
+ 12,
+ 16,
+ 16,
+ 16,
+ 24,
+ 32
+};
+
+static int y4o_read_container_header(FILE *f, char *first, int *sync){
+ char line[80];
+ char *p;
+ int n;
+ size_t ret,len;
+
+ len=sizeof("YUV4OGG");
+ if(first){
+ strncpy(line,first,len);
+ line[len]='\0';
+ first+=len;
+ ret=strlen(line);
+ }else{
+ ret = fread(line, 1, len,f);
+ }
+
+ if (ret<len){
+ if(feof(f))
+ fprintf(stderr, "ERROR: EOF reading y4o file header\n");
+ return 1;
+ }
+
+ if (strncmp(line, "YUV4OGG ", sizeof("YUV4OGG ")-1)){
+ fprintf(stderr, "ERROR: cannot parse y4o file header\n");
+ return 1;
+ }
+
+ /* proceed to get the tags... (overwrite the magic) */
+ if(!first){
+ for (n = 0, p = line; n < 80; n++, p++) {
+ if ((ret=fread(p,1,1,f))<1){
+ if(feof(f))
+ fprintf(stderr,"ERROR: EOF reading y4o file header\n");
+ return 1;
+ }
+ if (*p == '\n') {
+ *p = '\0';
+ break;
+ }
+ }
+ if (n >= 80) {
+ fprintf(stderr,"ERROR: line too long reading y4o file header\n");
+ return 1;
+ }
+ }else{
+ strncpy(line,first,80);
+ }
+
+ /* read tags */
+ /* S%c = sync */
+
+ {
+ char *token, *value;
+ char tag;
+
+ *sync=-1;
+
+ /* parse fields */
+ for (token = strtok(line, " ");
+ token != NULL;
+ token = strtok(NULL, " ")) {
+ if (token[0] == '\0') continue; /* skip empty strings */
+ tag = token[0];
+ value = token + 1;
+ switch (tag) {
+ case 'S':
+ switch(token[1]){
+ case 'y':
+ case 'Y':
+ *sync = 1;
+ break;
+ case 'n':
+ case 'N':
+ *sync=0;
+ break;
+ default:
+ fprintf(stderr,"ERROR: unknown sync tag setting in y4o header\n");
+ return 1;
+ }
+ break;
+ default:
+ fprintf(stderr,"ERROR: unknown file tag in y4o header\n");
+ return 1;
+ }
+ }
+ }
+
+ if(*sync==-1)return 1;
+
+ return 0;
+}
+
+static y4o_stream_t *y4o_read_stream_header(FILE *f){
+ char line[80];
+ char *p;
+ int n;
+ size_t ret;
+ int af=0,vf=0;
+ y4o_stream_t *s;
+
+ /* Check for past the stream headers and at first frame */
+ line[0]=getc(f);
+ ungetc(line[0],f);
+ if(line[0]=='F'){
+ return NULL;
+ }
+
+ s=calloc(1,sizeof(*s));
+
+ ret = fread(line, 1, sizeof("AUDIO"), f);
+ if (ret<sizeof("AUDIO")){
+ if(feof(f))
+ fprintf(stderr,"ERROR: EOF reading y4o stream header\n");
+ goto err;
+ }
+
+ if (!strncmp(line, "VIDEO ", sizeof("VIDEO ")-1)) vf=1;
+ else if (!strncmp(line, "AUDIO ", sizeof("AUDIO ")-1)) af=1;
+
+ if(!(af||vf)){
+ fprintf(stderr,"ERROR: unknown y4o stream header type\n");
+ goto err;
+ }
+
+ if(vf){
+ /* video stream! */
+ /* proceed to get the tags... (overwrite the magic) */
+ for (n = 0, p = line; n < 80; n++, p++) {
+ if ((ret=fread(p, 1, 1, f))<1){
+ if(feof(f))
+ fprintf(stderr,"ERROR: EOF reading y4o video stream header\n");
+ goto err;
+ }
+ if (*p == '\n') {
+ *p = '\0';
+ break;
+ }
+ }
+ if (n >= 80) {
+ fprintf(stderr,"ERROR: line too long reading y4o video stream header\n");
+ goto err;
+ }
+
+ /* read tags */
+ /* W%d = width
+ H%d = height
+ F%d:%d = fps
+ I%c = interlace
+ A%d:%d = pixel aspect
+ C%s = chroma format
+ */
+
+ {
+ char *token, *value;
+ char tag;
+ int i;
+ s->m.video.format=-1;
+ s->m.video.i=-1;
+
+ /* parse fields */
+ for (token = strtok(line, " ");
+ token != NULL;
+ token = strtok(NULL, " ")) {
+ if (token[0] == '\0') continue; /* skip empty strings */
+ tag = token[0];
+ value = token + 1;
+ switch (tag) {
+ case 'W':
+ s->m.video.w = atoi(token+1);
+ break;
+ case 'H':
+ s->m.video.h = atoi(token+1);
+ break;
+ case 'F':
+ {
+ char *pos=strchr(token+1,':');
+ if(pos){
+ *pos='\0';
+ s->m.video.fps_n = atoi(token+1);
+ s->m.video.fps_d = atoi(pos+1);
+ *pos=':';
+ }else{
+ s->m.video.fps_n = atoi(token+1);
+ s->m.video.fps_d = 1;
+ }
+ }
+ break;
+ case 'I':
+ switch(token[1]){
+ case 'p':
+ case 'P':
+ s->m.video.i=Y4O_I_PROGRESSIVE;
+ break;
+ case 't':
+ case 'T':
+ s->m.video.i=Y4O_I_TOP_FIRST;
+ break;
+ case 'b':
+ case 'B':
+ s->m.video.i=Y4O_I_BOTTOM_FIRST;
+ break;
+ default:
+ fprintf(stderr,"ERROR: unknown y4o video interlace setting\n");
+ goto err;
+ }
+ case 'A':
+ {
+ char *pos=strchr(token+1,':');
+ if(pos){
+ *pos='\0';
+ s->m.video.pa_n = atoi(token+1);
+ s->m.video.pa_d = atoi(pos+1);
+ *pos=':';
+ }else{
+ s->m.video.pa_n = atoi(token+1);
+ s->m.video.pa_d = 1;
+ }
+ }
+ break;
+ case 'C':
+ for(i=0;chromaformat[i];i++)
+ if(!strcasecmp(chromaformat[i],token+1))break;
+ if(!chromaformat[i]){
+ fprintf(stderr,"ERROR: unknown y4o video chroma format\n");
+ goto err;
+ }
+ s->m.video.format=i;
+ break;
+ default:
+ fprintf(stderr,"ERROR: unknown y4o video stream tag\n");
+ goto err;
+ }
+ }
+ }
+
+ if(s->m.video.fps_n>0 &&
+ s->m.video.fps_d>0 &&
+ s->m.video.pa_n>0 &&
+ s->m.video.pa_d>0 &&
+ s->m.video.format>=0 &&
+ s->m.video.w>0 &&
+ s->m.video.h>0 &&
+ s->m.video.i>=0)
+ s->type=Y4O_STREAM_VIDEO;
+ else{
+ fprintf(stderr,"ERROR: missing flags in y4o video stream header\n");
+ goto err;
+ }
+
+ {
+ int dw = s->m.video.w*s->m.video.pa_n;
+ int dh = s->m.video.h*s->m.video.pa_d;
+ int d;
+ for(d=1;d<10000;d++)
+ if(fabs(rint(dw/(double)dh*d) - dw/(double)dh*d)<EPSILON)
+ break;
+ s->m.video.frame_n=rint(dw/(double)dh*d);
+ s->m.video.frame_d=d;
+ }
+
+ return s;
+
+ }
+
+ if(af){
+ /* audio stream! */
+ /* proceed to get the tags... (overwrite the magic) */
+ for (n = 0, p = line; n < 80; n++, p++) {
+ if ((ret=fread(p, 1, 1, f))<1){
+ if(feof(f))
+ fprintf(stderr,"ERROR: EOF reading y4o audio stream header\n");
+ goto err;
+ }
+ if (*p == '\n') {
+ *p = '\0';
+ break;
+ }
+ }
+ if (n >= 80) {
+ fprintf(stderr,"ERROR: line too long reading y4o audio stream header\n");
+ goto err;
+ }
+
+ /* read tags */
+ /* R%d = rate
+ C%d = channels
+ all interchange audio is 24 bit signed LE
+ */
+
+ {
+ char *token, *value;
+ char tag;
+
+ /* parse fields */
+ for (token = strtok(line, " ");
+ token != NULL;
+ token = strtok(NULL, " ")) {
+ if (token[0] == '\0') continue; /* skip empty strings */
+ tag = token[0];
+ value = token + 1;
+ switch (tag) {
+ case 'R':
+ s->m.audio.rate = atoi(token+1);
+ break;
+ case 'C':
+ s->m.audio.ch = atoi(token+1);
+ break;
+ default:
+ fprintf(stderr,"ERROR: unknown y4o audio stream tag\n");
+ goto err;
+ }
+ }
+ }
+
+ if(s->m.audio.rate>0 &&
+ s->m.audio.ch>0)
+ s->type=Y4O_STREAM_AUDIO;
+ else{
+ fprintf(stderr,"ERROR: missing flags in y4o stream header\n");
+ goto err;
+ }
+
+ return s;
+ }
+
+ err:
+ s->type = Y4O_STREAM_INVALID;
+ return s;
+}
+
+y4o_in_t *y4o_init(FILE *f, char *first){
+ int i;
+ y4o_in_t *y;
+
+ if(y4o_read_container_header(f,first,&i))
+ return NULL;
+
+ y=calloc(1,sizeof(*y));
+ y->synced=i;
+
+ // read stream headers
+ while(1){
+ y4o_stream_t *s=y4o_read_stream_header(f);
+ if(!s)
+ break;
+ if(s->type == Y4O_STREAM_INVALID)
+ fprintf(stderr,"ERROR: Stream #%d unreadable; trying to continue\n",y->num_streams);
+ s->stream_num=y->num_streams++;
+
+ if(y->streams){
+ y->streams=realloc(y->streams,y->num_streams*sizeof(*y->streams));
+ }else{
+ y->streams=calloc(1,sizeof(*y->streams));
+ }
+ y->streams[s->stream_num]=s;
+ }
+
+ y->f = f;
+
+ return y;
+}
+
+void y4o_free(y4o_in_t *y){
+ int i;
+ if(y){
+ if(y->streams){
+ for(i=0;i<y->num_streams;i++){
+ y4o_stream_t *s=y->streams[i];
+ free(s);
+ }
+ free(y->streams);
+ }
+ free(y);
+ }
+}
+
+y4o_frame_t *y4o_read_frame_header(y4o_in_t *y){
+ FILE *f=y->f;
+ int streamno;
+ int length;
+ double pts;
+ char line[80];
+ char *p;
+ int n;
+ size_t ret;
+
+ ret = fread(line, 1, sizeof("FRAME"),f);
+ if (ret<sizeof("FRAME"))
+ {
+ /* A clean EOF should end exactly at a frame-boundary */
+ if( ret != 0 && feof(f) )
+ fprintf(stderr,"ERROR: EOF reading y4o frame\n");
+ y->eof=1;
+ return NULL;
+ }
+
+ if (strncmp(line, "FRAME ", sizeof("FRAME ")-1)){
+ fprintf(stderr,"ERROR: loss of y4o framing\n");
+ exit(1);
+ }
+
+ /* proceed to get the tags... (overwrite the magic) */
+ for (n = 0, p = line; n < 80; n++, p++) {
+ if ((ret=fread(p, 1, 1, f))<1){
+ if(feof(f))
+ fprintf(stderr,"ERROR: EOF reading y4o frame\n");
+ return NULL;
+ }
+ if (*p == '\n') {
+ *p = '\0'; /* Replace linefeed by end of string */
+ break;
+ }
+ }
+ if (n >= 80) {
+ fprintf(stderr,"ERROR: line too long reading y4o frame header\n");
+ return NULL;
+ }
+
+ /* read tags */
+ /* S%d = streamno
+ L%d = length
+ P%g = pts */
+
+ {
+ char *token, *value;
+ char tag;
+
+ streamno=-1;
+ length=-1;
+ pts=-1;
+
+ /* parse fields */
+ for (token = strtok(line, " ");
+ token != NULL;
+ token = strtok(NULL, " ")) {
+ if (token[0] == '\0') continue; /* skip empty strings */
+ tag = token[0];
+ value = token + 1;
+ switch (tag) {
+ case 'S':
+ streamno = atoi(token+1);
+ break;
+ case 'L':
+ length = atoi(token+1);
+ break;
+ case 'P':
+ pts = atof(token+1);
+ break;
+ default:
+ fprintf(stderr,"ERROR: unknown y4o frame tag\n");
+ return NULL;
+ }
+ }
+ }
+
+ if(streamno>=y->num_streams){
+ fprintf(stderr,"ERROR: error reading frame; streamno out of range\n");
+ return NULL;
+ }
+
+ if(streamno==-1 || length==-1 || pts==-1){
+ fprintf(stderr,"ERROR: missing y4o frame tags; frame unreadable\n");
+ return NULL;
+ }
+
+ {
+ y4o_frame_t *p=calloc(1,sizeof(*p));
+
+ if(!p){
+ fprintf(stderr,"ERROR: unable to allocate memory for frame\n");
+ return NULL;
+ }
+
+ p->pts=pts;
+ p->len=length;
+ p->streamno=streamno;
+
+ return p;
+ }
+}
+
+int y4o_read_frame_data(y4o_in_t *y, y4o_frame_t *p){
+ int ret;
+ char *data=malloc(p->len);
+
+ if(!data){
+ fprintf(stderr,"ERROR: unable to allocate memory for frame\n");
+ return -1;
+ }
+ p->data=data;
+ ret=fread(data,1,p->len,y->f);
+ if(ret<p->len){
+ free(data);
+ p->len=0;
+ p->data=NULL;
+ if(feof(y->f)){
+ fprintf(stderr,"ERROR: unable to read frame; EOF\n");
+ }else{
+ fprintf(stderr,"ERROR: IO error reading frame\n");
+ }
+ return -1;
+ }
+ return 0;
+}
+
+y4o_frame_t *y4o_read_frame(y4o_in_t *y){
+ y4o_frame_t *p = y4o_read_frame_header(y);
+ if(!p)return NULL;
+ if(y4o_read_frame_data(y,p)){
+ y4o_free_frame(p);
+ return NULL;
+ }
+ return p;
+}
+
+void y4o_free_frame(y4o_frame_t *p){
+ if(p->data)free(p->data);
+ memset(p,0,sizeof(*p));
+ free(p);
+}
More information about the commits
mailing list