⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transcoder_example.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************** *                                                                  * * 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-2004                * * by the Xiph.Org Foundation http://www.xiph.org/                  * *                                                                  * ********************************************************************  function: example encoder application; makes an Ogg Theora/Vorbis            file from YUV4MPEG2 and WAV input  last mod: $Id: transcoder_example.c,v 1.4 2004/03/20 00:14:04 tterribe Exp $ ********************************************************************/#define _GNU_SOURCE#define _REENTRANT#define _LARGEFILE_SOURCE#define _LARGEFILE64_SOURCE#define _FILE_OFFSET_BITS 64#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <getopt.h>#include <time.h>#include <math.h>#include "theora/theora.h"#include "vorbis/codec.h"#include "vorbis/vorbisenc.h"#ifdef _WIN32/*supply missing headers and functions to Win32. going to hell, I know*/#include <io.h>#include <fcntl.h>static double rint(double x){  if (x < 0.0)    return (double)(int)(x - 0.5);  else    return (double)(int)(x + 0.5);}#endif/*Copied from vorbis/sharedbook.c*/static int _ilog(unsigned int v){  int ret=0;  while(v){    ret++;    v>>=1;  }  return(ret);}const char *optstring = "o:a:A:v:V:";struct option options [] = {  {"output",required_argument,NULL,'o'},  {"audio-rate-target",required_argument,NULL,'A'},  {"video-rate-target",required_argument,NULL,'V'},  {"audio-quality",required_argument,NULL,'a'},  {"video-quality",required_argument,NULL,'v'},  {NULL,0,NULL,0}};typedef struct TC_INSTANCE {  ogg_uint32_t     LastKeyFrame ;  ogg_int64_t      KeyFrameCount;  int              ThisIsFirstFrame;  int              ThisIsKeyFrame;  ogg_uint32_t     CurrentFrame;  ogg_int64_t      granulepos;  int              keyframe_granule_shift;  char *           in_bytes;  long             in_bytecount;  ogg_uint32_t     fps_denominator;  ogg_uint32_t     fps_numerator;  oggpack_buffer   opb_in;  oggpack_buffer   opb_out;} TC_INSTANCE;/* You'll go to Hell for using globals. */FILE *audio=NULL;FILE *video=NULL;int audio_ch=0;int audio_hz=0;float audio_q=.1;int audio_r=-1;int video_x=0;int video_y=0;int frame_x=0;int frame_y=0;int frame_x_offset=0;int frame_y_offset=0;int video_hzn=0;int video_hzd=0;int video_an=0;int video_ad=0;int video_r=-1;int video_q=16;  char *vp3frame[2];  int framebytecount[2];  int frameiskey[2];    ogg_page audiopage;    ogg_page videopage;static void usage(void){  fprintf(stderr,          "Usage: encoder_example [options] [audio_file] video_file\n\n"          "Options: \n\n"          "  -o --output <filename.ogg>  file name for encoded output;\n"          "                              If this option is not given, the\n"          "                              compressed data is sent to stdout.\n\n"          "  -A --audio-rate-target <n>  bitrate target for Vorbis audio;\n"          "                              use -a and not -A if at all possible,\n"          "                              as -a gives higher quality for a given\n"          "                              bitrate.\n\n"          "  -V --video-rate-target <n>  bitrate target for Theora video\n\n"          "  -a --audio-quality <n>      Vorbis quality selector from -1 to 10\n"          "                              (-1 yields smallest files but lowest\n"          "                              fidelity; 10 yields highest fidelity\n"          "                              but large files. '2' is a reasonable\n"          "                              default).\n\n"          "   -v --video-quality <n>     Theora quality selector fro 0 to 10\n"          "                              (0 yields smallest files but lowest\n"          "                              video quality. 10 yields highest\n"          "                              fidelity but large files).\n\n"          "encoder_example accepts only uncompressed RIFF WAV format audio and\n"          "YUV4MPEG2 uncompressed video.\n\n");  exit(1);}static void id_file(char *f){  FILE *test;  unsigned char buffer[80];  int ret;  /* open it, look for magic */  if(!strcmp(f,"-")){    /* stdin */    test=stdin;  }else{    test=fopen(f,"rb");    if(!test){      fprintf(stderr,"Unable to open file %s.\n",f);      exit(1);    }  }  ret=fread(buffer,1,4,test);  if(ret<4){    fprintf(stderr,"EOF determining file type of file %s.\n",f);    exit(1);  }  if(!memcmp(buffer,"RIFF",4)){    /* possible WAV file */    if(audio){      /* umm, we already have one */      fprintf(stderr,"Multiple RIFF WAVE files specified on command line.\n");      exit(1);    }    /* Parse the rest of the header */    ret=fread(buffer,1,4,test);    ret=fread(buffer,1,4,test);    if(ret<4)goto riff_err;    if(!memcmp(buffer,"WAVE",4)){      while(!feof(test)){        ret=fread(buffer,1,4,test);        if(ret<4)goto riff_err;        if(!memcmp("fmt",buffer,3)){          /* OK, this is our audio specs chunk.  Slurp it up. */          ret=fread(buffer,1,20,test);          if(ret<20)goto riff_err;          if(memcmp(buffer+4,"\001\000",2)){            fprintf(stderr,"The WAV file %s is in a compressed format; "                    "can't read it.\n",f);            exit(1);          }          audio=test;          audio_ch=buffer[6]+(buffer[7]<<8);          audio_hz=buffer[8]+(buffer[9]<<8)+            (buffer[10]<<16)+(buffer[11]<<24);          if(buffer[18]+(buffer[19]<<8)!=16){            fprintf(stderr,"Can only read 16 bit WAV files for now.\n");            exit(1);          }          /* Now, align things to the beginning of the data */          /* Look for 'dataxxxx' */          while(!feof(test)){            ret=fread(buffer,1,4,test);            if(ret<4)goto riff_err;            if(!memcmp("data",buffer,4)){              /* We're there.  Ignore the declared size for now. */              ret=fread(buffer,1,4,test);              if(ret<4)goto riff_err;              fprintf(stderr,"File %s is 16 bit %d channel %d Hz RIFF WAV audio.\n",                      f,audio_ch,audio_hz);              return;            }          }        }      }    }    fprintf(stderr,"Couldn't find WAVE data in RIFF file %s.\n",f);    exit(1);  }  if(!memcmp(buffer,"AVI2",4)){    /* possible AVI2VP31 format file */    /* read until newline, or 80 cols, whichever happens first */    int i;    for(i=0;i<79;i++){      ret=fread(buffer+i,1,1,test);      if(ret<1)goto yuv_err;      if(buffer[i]=='\n')break;    }    if(i==79){      fprintf(stderr,"Error parsing %s header; not a VP31 raw frames file?\n",f);    }    buffer[i]='\0';    if(!memcmp(buffer,"VP31",4)){      char interlace;      if(video){        /* umm, we already have one */        fprintf(stderr,"Multiple video files specified on command line.\n");        exit(1);      }      if(buffer[4]!='R'){        fprintf(stderr,"Incorrect file ; VP31 raw frames required.\n");      }      ret=sscanf(buffer,"VP31R W%d H%d F%d:%d I%c A%d:%d",                 &frame_x,&frame_y,&video_hzn,&video_hzd,&interlace,                 &video_an,&video_ad);      if(ret<7){        fprintf(stderr,"Error parsing AVI2VP31R header in file %s.\n",f);        exit(1);      }      if(interlace!='p'){        fprintf(stderr,"Input video is interlaced; Theora handles only progressive scan\n");        exit(1);      }      video=test;      fprintf(stderr,"File %s is %dx%d %.02f fps VP31 video.\n",              f,frame_x,frame_y,(double)video_hzn/video_hzd);      return;    }  }  fprintf(stderr,"Input file %s is neither a WAV nor VP31 file.\n",f);  exit(1); riff_err:  fprintf(stderr,"EOF parsing RIFF file %s.\n",f);  exit(1); yuv_err:  fprintf(stderr,"EOF parsing VP31 file %s.\n",f);  exit(1);}int spinner=0;char *spinascii="|/-\\";void spinnit(void){  spinner++;  if(spinner==4)spinner=0;  fprintf(stderr,"\r%c",spinascii[spinner]);}int fetch_and_process_audio(FILE *audio,ogg_page *audiopage,                            ogg_stream_state *vo,                            vorbis_dsp_state *vd,                            vorbis_block *vb,                            int audioflag){  ogg_packet op;  int i,j;  while(audio && !audioflag){    /* process any audio already buffered */    spinnit();    if(ogg_stream_pageout(vo,audiopage)>0) return 1;    if(ogg_stream_eos(vo))return 0;    {      /* read and process more audio */      signed char readbuffer[4096];      int toread=4096/2/audio_ch;      int bytesread=fread(readbuffer,1,toread*2*audio_ch,audio);      int sampread=bytesread/2/audio_ch;      float **vorbis_buffer;      int count=0;      if(bytesread<=0){        /* end of file.  this can be done implicitly, but it's           easier to see here in non-clever fashion.  Tell the           library we're at end of stream so that it can handle the           last frame and mark end of stream in the output properly */        vorbis_analysis_wrote(vd,0);      }else{        vorbis_buffer=vorbis_analysis_buffer(vd,sampread);        /* uninterleave samples */        for(i=0;i<sampread;i++){          for(j=0;j<audio_ch;j++){            vorbis_buffer[j][i]=((readbuffer[count+1]<<8)|                                 (0x00ff&(int)readbuffer[count]))/32768.f;            count+=2;          }        }                vorbis_analysis_wrote(vd,sampread);              }      while(vorbis_analysis_blockout(vd,vb)==1){                /* analysis, assume we want to use bitrate management */        vorbis_analysis(vb,NULL);        vorbis_bitrate_addblock(vb);                /* weld packets into the bitstream */        while(vorbis_bitrate_flushpacket(vd,&op))          ogg_stream_packetin(vo,&op);              }    }  }  return audioflag;}int theora_transcode_packetout( TC_INSTANCE *ttc, int last_p, ogg_packet *op){  long bytes=ttc->in_bytecount;  if(!bytes)return(0);  op->packet=ttc->in_bytes;  op->bytes=bytes;  op->b_o_s=0;  op->e_o_s=last_p;  op->packetno=ttc->CurrentFrame;  op->granulepos=ttc->granulepos;  return 1;}void TranscodeKeyFrame(TC_INSTANCE *ttc){    /* Keep track of the total number of Key Frames Coded */    ttc->KeyFrameCount += 1;    ttc->LastKeyFrame = 1;}void TranscodeFrame(TC_INSTANCE *ttc){    ttc->LastKeyFrame++;}void TranscodeFirstFrame(TC_INSTANCE *ttc){  /* Keep track of the total number of Key Frames Coded. */  ttc->KeyFrameCount = 1;  ttc->LastKeyFrame = 1;}int theora_transcode_bufferin( TC_INSTANCE *ttc, int isKeyFrame, char * bytes, int bytecount){  /*transcode: record keyframe flag*/  ttc->ThisIsKeyFrame = isKeyFrame;  /* Special case for first frame */  if ( ttc->ThisIsFirstFrame ){    ttc->ThisIsFirstFrame = 0;    ttc->ThisIsKeyFrame = 0;  } else if ( ttc->ThisIsKeyFrame ) {    TranscodeKeyFrame(ttc);    ttc->ThisIsKeyFrame = 0;  } else  {    /* Compress the frame. */    TranscodeFrame( ttc );  }  /*need to pack info here*/  {    int            frame_type;    long           total_bits;    long           total_words;    int            frac_bits;    oggpackB_readinit(&ttc->opb_in,bytes,bytecount);    oggpackB_reset(&ttc->opb_out);    /*Mark as video frame.*/    oggpackB_write(&ttc->opb_out,0,1);    /*Copy frame type.*/    frame_type=oggpackB_read1(&ttc->opb_in);    oggpackB_write(&ttc->opb_out,frame_type,1);    /*Skip an unused bit in the VP32 header.*/    oggpackB_adv1(&ttc->opb_in);    /*Copy Q multiplier.*/    oggpackB_write(&ttc->opb_out,oggpackB_read(&ttc->opb_in,6),6);    /*VP3 has no per-block Q multipliers*/    oggpackB_write(&ttc->opb_out,0,1);    /*If the frame is a base/key/golden frame, copy a few extra bits.*/    if(frame_type==0){      /*These 13 bits are not included in a Theora frame header.        They were 0's and VP3 version info in VP32.*/      oggpackB_adv(&ttc->opb_in,13);      /*Copy the key frame type and the spare configuration bits.*/      oggpackB_write(&ttc->opb_out,oggpackB_read(&ttc->opb_in,3),3);    }    /*Copy the rest of the bits over.*/    total_bits=bytecount*8-oggpack_bits(&ttc->opb_in);    frac_bits=(int)(total_bits&31);    if(frac_bits){      oggpackB_write(&ttc->opb_out,oggpackB_read(&ttc->opb_in,frac_bits),       frac_bits);    }    total_words=total_bits>>5;    while(total_words-->0){      oggpackB_write(&ttc->opb_out,oggpackB_read(&ttc->opb_in,32),32);    }    ttc->in_bytecount = oggpackB_bytes(&ttc->opb_out);    ttc->in_bytes = oggpackB_get_buffer(&ttc->opb_out);  }  /* Update stats variables. */  ttc->CurrentFrame++;  ttc->granulepos=    ((ttc->CurrentFrame-ttc->LastKeyFrame-1)<<ttc->keyframe_granule_shift)+

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -