コード例 #1
0
ファイル: common.c プロジェクト: Distrotech/libkate
int get_packet(ogg_sync_state *oy,ogg_stream_state *os,int *init,ogg_packet *op)
{
  char *buffer;
  size_t bytes;
  ogg_page og;

  /* try to get a packet from the stream */
  if (*init && ogg_stream_packetout(os,op)) return 0;

  /* read data and feed the pages to ogg */
  buffer=ogg_sync_buffer(oy,4096);
  bytes=fread(buffer,1,4096,stdin);
  if (bytes==0) return 1; /* we're done */
  ogg_sync_wrote(oy,bytes);
  while (ogg_sync_pageout(oy,&og)>0) {
    if (!*init && ogg_page_bos(&og)) {
      ogg_stream_init(os,ogg_page_serialno(&og));
    }
    ogg_stream_pagein(os,&og);
    if (!*init && ogg_page_bos(&og)) {
      ogg_packet op;
      ogg_stream_packetpeek(os,&op);
      if (op.bytes>=8 && !memcmp(op.packet,"\200kate\0\0\0",8)) {
        *init=1;
      }
      else {
        ogg_stream_clear(os);
      }
    }
  }

  /* try again with the new data */
  return get_packet(oy,os,init,op);
}
コード例 #2
0
ファイル: oggmux.c プロジェクト: ChinnaSuhas/ossbuild
static ChainCodec
get_page_codec (ogg_page * page)
{
  ChainCodec codec = CODEC_UNKNOWN;
  ogg_stream_state state;
  ogg_packet packet;

  ogg_stream_init (&state, ogg_page_serialno (page));
  if (ogg_stream_pagein (&state, page) == 0) {
    if (ogg_stream_packetpeek (&state, &packet) > 0) {
      if (strncmp ((char *) &packet.packet[1], "vorbis",
              strlen ("vorbis")) == 0)
        codec = CODEC_VORBIS;
      else if (strncmp ((char *) &packet.packet[1], "theora",
              strlen ("theora")) == 0)
        codec = CODEC_THEORA;
      else if (strncmp ((char *) &packet.packet[0], "Speex   ",
              strlen ("Speex   ")) == 0)
        codec = CODEC_SPEEX;
    }
  }
  ogg_stream_clear (&state);

  return codec;
}
コード例 #3
0
ファイル: pyEx_ogg.c プロジェクト: vigith/ogg-theora-vorbis
static PyObject * py_ogg_ogg_stream_packetpeek(PyObject *self, PyObject *args) {
  int c_out;
  int size1, size2;
  ogg_stream_state * os;
  ogg_packet * op;
  PyArg_ParseTuple(args, "s#s#", &os, &size1, &op, &size2);
  c_out = ogg_stream_packetpeek(os, op);
  return Py_BuildValue("i", c_out);
};
コード例 #4
0
bool OggReader::compact_eval_state(ogg_stream_state* os)
{
    bool readFarFromEnding = (os->body_storage - os->body_returned >= 2 * 1024 * 1024);	// try to minimize compact operation, but...
    bool hasAudio = (ogg_stream_packetpeek(&movie->v_osstate, NULL) > 0);			// ... if we run out of audio, don't risk audio glitches!
    bool pastMinimumReturn = (os->body_returned > 3 * 1024 * 1024);

    return !readFarFromEnding || (!hasAudio && movie->vorbis_p /*&& !::cfeof(this->file) && !buffering **/ &&
                                  pastMinimumReturn);
}
コード例 #5
0
/*
 * Class:     org_tritonus_lowlevel_ogg_StreamState
 * Method:    packetPeek
 * Signature: (Lorg/tritonus/lowlevel/ogg/Packet;)I
 */
JNIEXPORT jint JNICALL
Java_org_tritonus_lowlevel_ogg_StreamState_packetPeek
(JNIEnv* env, jobject obj, jobject packet)
{
	ogg_stream_state*	handle;
	ogg_packet*		packetHandle;
	int			nReturn;

	if (debug_flag) { fprintf(debug_file, "Java_org_tritonus_lowlevel_ogg_StreamState_packetPeek(): begin\n"); }
	handle = getHandle(env, obj);
	packetHandle = getPacketNativeHandle(env, packet);
	nReturn = ogg_stream_packetpeek(handle, packetHandle);
	if (debug_flag) { fprintf(debug_file, "Java_org_tritonus_lowlevel_ogg_StreamState_packetPeek(): end\n"); }
	return nReturn;
}
コード例 #6
0
ファイル: framing.c プロジェクト: andreipaga/audacity
void test_pack(const int *pl, const int **headers){
  unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
  long inptr=0;
  long outptr=0;
  long deptr=0;
  long depacket=0;
  long granule_pos=7,pageno=0;
  int i,j,packets,pageout=0;
  int eosflag=0;
  int bosflag=0;

  ogg_stream_reset(&os_en);
  ogg_stream_reset(&os_de);
  ogg_sync_reset(&oy);

  for(packets=0;;packets++)if(pl[packets]==-1)break;

  for(i=0;i<packets;i++){
    /* construct a test packet */
    ogg_packet op;
    int len=pl[i];
    
    op.packet=data+inptr;
    op.bytes=len;
    op.e_o_s=(pl[i+1]<0?1:0);
    op.granulepos=granule_pos;

    granule_pos+=1024;

    for(j=0;j<len;j++)data[inptr++]=i+j;

    /* submit the test packet */
    ogg_stream_packetin(&os_en,&op);

    /* retrieve any finished pages */
    {
      ogg_page og;
      
      while(ogg_stream_pageout(&os_en,&og)){
	/* We have a page.  Check it carefully */

	fprintf(stderr,"%ld, ",pageno);

	if(headers[pageno]==NULL){
	  fprintf(stderr,"coded too many pages!\n");
	  exit(1);
	}

	check_page(data+outptr,headers[pageno],&og);

	outptr+=og.body_len;
	pageno++;

	/* have a complete page; submit it to sync/decode */

	{
	  ogg_page og_de;
	  ogg_packet op_de,op_de2;
	  char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
	  memcpy(buf,og.header,og.header_len);
	  memcpy(buf+og.header_len,og.body,og.body_len);
	  ogg_sync_wrote(&oy,og.header_len+og.body_len);

	  while(ogg_sync_pageout(&oy,&og_de)>0){
	    /* got a page.  Happy happy.  Verify that it's good. */
	    
	    check_page(data+deptr,headers[pageout],&og_de);
	    deptr+=og_de.body_len;
	    pageout++;

	    /* submit it to deconstitution */
	    ogg_stream_pagein(&os_de,&og_de);

	    /* packets out? */
	    while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
	      ogg_stream_packetpeek(&os_de,NULL);
	      ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
	      
	      /* verify peek and out match */
	      if(memcmp(&op_de,&op_de2,sizeof(op_de))){
		fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
			depacket);
		exit(1);
	      }

	      /* verify the packet! */
	      /* check data */
	      if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
		fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
			depacket);
		exit(1);
	      }
	      /* check bos flag */
	      if(bosflag==0 && op_de.b_o_s==0){
		fprintf(stderr,"b_o_s flag not set on packet!\n");
		exit(1);
	      }
	      if(bosflag && op_de.b_o_s){
		fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
		exit(1);
	      }
	      bosflag=1;
	      depacket+=op_de.bytes;
	      
	      /* check eos flag */
	      if(eosflag){
		fprintf(stderr,"Multiple decoded packets with eos flag!\n");
		exit(1);
	      }

	      if(op_de.e_o_s)eosflag=1;

	      /* check granulepos flag */
	      if(op_de.granulepos!=-1){
		fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
	      }
	    }
	  }
	}
      }
    }
  }
  _ogg_free(data);
  if(headers[pageno]!=NULL){
    fprintf(stderr,"did not write last page!\n");
    exit(1);
  }
  if(headers[pageout]!=NULL){
    fprintf(stderr,"did not decode last page!\n");
    exit(1);
  }
  if(inptr!=outptr){
    fprintf(stderr,"encoded page data incomplete!\n");
    exit(1);
  }
  if(inptr!=deptr){
    fprintf(stderr,"decoded page data incomplete!\n");
    exit(1);
  }
  if(inptr!=depacket){
    fprintf(stderr,"decoded packet data incomplete!\n");
    exit(1);
  }
  if(!eosflag){
    fprintf(stderr,"Never got a packet with EOS set!\n");
    exit(1);
  }
  fprintf(stderr,"ok.\n");
}
コード例 #7
0
ファイル: opus.c プロジェクト: ifroz/rockbox
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    int error = CODEC_ERROR;
    intptr_t param;
    ogg_sync_state oy;
    ogg_page og;
    ogg_packet op;
    ogg_stream_state os;
    int64_t page_granule = 0;
    int stream_init = 0;
    int sample_rate = 48000;
    OpusDecoder *st = NULL;
    OpusHeader header;
    int ret;
    unsigned long strtoffset = ci->id3->offset;
    int skip = 0;
    int64_t seek_target;
    uint64_t granule_pos;

    ogg_malloc_init();

    global_stack = 0;

#if defined(CPU_COLDFIRE)
    /* EMAC rounding is disabled because of MULT16_32_Q15, which will be
       inaccurate with rounding in its current incarnation */
    coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
#endif

    /* pre-init the ogg_sync_state buffer, so it won't need many reallocs */
    ogg_sync_init(&oy);
    oy.storage = 64*1024;
    oy.data = _ogg_malloc(oy.storage);

    /* allocate output buffer */
    uint16_t *output = (uint16_t*) _ogg_malloc(MAX_FRAME_SIZE*sizeof(uint16_t));

    ci->seek_buffer(0);
    ci->set_elapsed(0);

    while (1) {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        if (action == CODEC_ACTION_SEEK_TIME) {
            if (st != NULL) {
                /* calculate granule to seek to (including seek rewind) */
                seek_target = (48LL * param) + header.preskip;
                skip = MIN(seek_target, SEEK_REWIND);
                seek_target -= skip;

                LOGF("Opus seek page:%lld,%lld,%ld\n",
		            seek_target, page_granule, (long)param);
                speex_seek_page_granule(seek_target, page_granule, &oy, &os);
            }

            ci->set_elapsed(param);
            ci->seek_complete();
        }

        /*Get the ogg buffer for writing*/
        if (get_more_data(&oy) < 1) {
            goto done;
        }

        /* Loop for all complete pages we got (most likely only one) */
        while (ogg_sync_pageout(&oy, &og) == 1) {
            if (stream_init == 0) {
                ogg_stream_init(&os, ogg_page_serialno(&og));
                stream_init = 1;
            }

            /* Add page to the bitstream */
            ogg_stream_pagein(&os, &og);

            page_granule = ogg_page_granulepos(&og);
            granule_pos = page_granule;

            /* Do this to avoid allocating space for huge comment packets
               (embedded Album Art) */
            if(os.packetno == 1 && ogg_stream_packetpeek(&os, &op) != 1){
              ogg_sync_reset(&oy);
            }

            while ((ogg_stream_packetout(&os, &op) == 1) && !op.e_o_s) {
                if (op.packetno == 0){
                    /* identification header */
                
                    if (opus_header_parse(op.packet, op.bytes, &header) == 0) {
                        LOGF("Could not parse header");
                        goto done;
                    }
                    skip = header.preskip;

                    st = opus_decoder_create(sample_rate, header.channels, &ret);
                    if (ret != OPUS_OK) {
                        LOGF("opus_decoder_create failed %d", ret);
                        goto done;
                    }
                    LOGF("Decoder inited");

                    codec_set_replaygain(ci->id3);

                    opus_decoder_ctl(st, OPUS_SET_GAIN(header.gain));

                    ci->configure(DSP_SET_FREQUENCY, sample_rate);
                    ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
                    ci->configure(DSP_SET_STEREO_MODE, (header.channels == 2) ?
                        STEREO_INTERLEAVED : STEREO_MONO);

                } else if (op.packetno == 1) {
                    /* Comment header */
                } else {
                    if (strtoffset) {
                        ci->seek_buffer(strtoffset);
                        ogg_sync_reset(&oy);
                        strtoffset = 0;
                        break;//next page
                    }

                    /* report progress */
                    ci->set_elapsed((granule_pos - header.preskip) / 48);

                    /* Decode audio packets */
                    ret = opus_decode(st, op.packet, op.bytes, output, MAX_FRAME_SIZE, 0);

                    if (ret > 0) {
                        if (skip > 0) {
                            if (ret <= skip) {
                                /* entire output buffer is skipped */
                                skip -= ret;
                                ret = 0;
                            } else {
                                /* part of output buffer is played */
                                ret -= skip;
                                ci->pcmbuf_insert(&output[skip * header.channels], NULL, ret);
                                skip = 0;
                            }
                        } else {
                            /* entire buffer is played */
                            ci->pcmbuf_insert(output, NULL, ret);
                        }
                        granule_pos += ret;
                    } else {
                        if (ret < 0) {
                            LOGF("opus_decode failed %d", ret);
                            goto done;
                        }
                        break;
                    }
                }
            }
        }
    }
    LOGF("Returned OK");
    error = CODEC_OK;
done:
    ogg_malloc_destroy();
    return error;
}
コード例 #8
0
static void theora_process(stream_processor *stream, ogg_page *page)
{
    ogg_packet packet;
    misc_theora_info *inf = stream->data;
    int i, header=0;
    int res;

    ogg_stream_pagein(&stream->os, page);
    if(inf->doneheaders < 3)
        header = 1;

    while(1) {
        res = ogg_stream_packetout(&stream->os, &packet);
        if(res < 0) {
           warn(_("WARNING: discontinuity in stream (%d)\n"), stream->num);
           continue;
        }
        else if (res == 0)
            break;

        if(inf->doneheaders < 3) {
            if(theora_decode_header(&inf->ti, &inf->tc, &packet) < 0) {
                warn(_("WARNING: Could not decode Theora header "
                       "packet - invalid Theora stream (%d)\n"), stream->num);
                continue;
            }
            inf->doneheaders++;
            if(inf->doneheaders == 3) {
                if(ogg_page_granulepos(page) != 0 || ogg_stream_packetpeek(&stream->os, NULL) == 1)
                    warn(_("WARNING: Theora stream %d does not have headers "
                           "correctly framed. Terminal header page contains "
                           "additional packets or has non-zero granulepos\n"),
                            stream->num);
                info(_("Theora headers parsed for stream %d, "
                       "information follows...\n"), stream->num);

                info(_("Version: %d.%d.%d\n"), inf->ti.version_major, inf->ti.version_minor, inf->ti.version_subminor);

                info(_("Vendor: %s\n"), inf->tc.vendor);
                info(_("Width: %d\n"), inf->ti.frame_width);
                info(_("Height: %d\n"), inf->ti.frame_height);
		info(_("Total image: %d by %d, crop offset (%d, %d)\n"),
		    inf->ti.width, inf->ti.height, inf->ti.offset_x, inf->ti.offset_y);
		if(inf->ti.offset_x + inf->ti.frame_width > inf->ti.width)
		    warn(_("Frame offset/size invalid: width incorrect\n"));
		if(inf->ti.offset_y + inf->ti.frame_height > inf->ti.height)
		    warn(_("Frame offset/size invalid: height incorrect\n"));

		if(inf->ti.fps_numerator == 0 || inf->ti.fps_denominator == 0) 
		   warn(_("Invalid zero framerate\n"));
		else
		   info(_("Framerate %d/%d (%.02f fps)\n"), inf->ti.fps_numerator, inf->ti.fps_denominator, (float)inf->ti.fps_numerator/(float)inf->ti.fps_denominator);
		
		if(inf->ti.aspect_numerator == 0 || inf->ti.aspect_denominator == 0) 
		{
		    info(_("Aspect ratio undefined\n"));
		}	
		else
		{
		    float frameaspect = (float)inf->ti.frame_width/(float)inf->ti.frame_height * (float)inf->ti.aspect_numerator/(float)inf->ti.aspect_denominator; 
		    info(_("Pixel aspect ratio %d:%d (%f:1)\n"), inf->ti.aspect_numerator, inf->ti.aspect_denominator, (float)inf->ti.aspect_numerator/(float)inf->ti.aspect_denominator);
                    if(fabs(frameaspect - 4.0/3.0) < 0.02)
			info(_("Frame aspect 4:3\n"));
                    else if(fabs(frameaspect - 16.0/9.0) < 0.02)
			info(_("Frame aspect 16:9\n"));
		    else
			info(_("Frame aspect %f:1\n"), frameaspect);
		}

		if(inf->ti.colorspace == OC_CS_ITU_REC_470M)
		    info(_("Colourspace: Rec. ITU-R BT.470-6 System M (NTSC)\n")); 
		else if(inf->ti.colorspace == OC_CS_ITU_REC_470BG)
		    info(_("Colourspace: Rec. ITU-R BT.470-6 Systems B and G (PAL)\n")); 
		else
		    info(_("Colourspace unspecified\n"));

		if(inf->ti.pixelformat == OC_PF_420)
		    info(_("Pixel format 4:2:0\n"));
		else if(inf->ti.pixelformat == OC_PF_422)
		    info(_("Pixel format 4:2:2\n"));
		else if(inf->ti.pixelformat == OC_PF_444)
		    info(_("Pixel format 4:4:4\n"));
		else
		    warn(_("Pixel format invalid\n"));

		info(_("Target bitrate: %d kbps\n"), inf->ti.target_bitrate/1000);
		info(_("Nominal quality setting (0-63): %d\n"), inf->ti.quality);

                if(inf->tc.comments > 0)
                    info(_("User comments section follows...\n"));

                for(i=0; i < inf->tc.comments; i++) {
                    char *comment = inf->tc.user_comments[i];
		    check_xiph_comment(stream, i, comment, 
		            inf->tc.comment_lengths[i]);
		}
	    }
	}
        else {
            ogg_int64_t framenum;
            ogg_int64_t iframe,pframe;
            ogg_int64_t gp = packet.granulepos;

            if(gp > 0) {
                iframe=gp>>inf->ti.granule_shift;
                pframe=gp-(iframe<<inf->ti.granule_shift);
                framenum = iframe+pframe;
                if(inf->framenum_expected >= 0 && 
                    inf->framenum_expected != framenum)
                {
                    warn(_("WARNING: Expected frame %" I64FORMAT 
                           ", got %" I64FORMAT "\n"), 
                           inf->framenum_expected, framenum);
                }
                inf->framenum_expected = framenum + 1;
            }
            else if (inf->framenum_expected >= 0) {
                inf->framenum_expected++;
            }
        }
コード例 #9
0
ファイル: mmfile.cpp プロジェクト: BlastarIndia/raceintospace
static int
init_vorbis(mm_file *mf, ogg_page *pg)
{
    int pkts = 0;
    int res = 0;
    int rval = 0;
    vorbis_block *vo_blk = NULL;
    vorbis_info *vo_info = NULL;
    vorbis_comment vo_comm;
    ogg_packet pkt;
    ogg_stream_state stream;

    assert(mf);
    vo_info = (vorbis_info *)xmalloc(sizeof(*vo_info));
    vorbis_info_init(vo_info);
    vorbis_comment_init(&vo_comm);
    ogg_stream_init(&stream, ogg_page_serialno(pg));

    if (ogg_page_packets(pg) != 1 || ogg_page_granulepos(pg) != 0) {
        goto end;
    }

    if (ogg_stream_pagein(&stream, pg) < 0)
        /* should not happen */
    {
        goto end;
    }

    /*
     * Three first packets must go successfully through the loop.
     */
    for (pkts = 0; pkts < 3; ++pkts) {
        while ((res = ogg_stream_packetpeek(&stream, &pkt)) != 1) {
            if (res < 0
                || get_page(mf, pg) <= 0
                || ogg_stream_pagein(&stream, pg) < 0) {
                rval = -1;
                goto end;
            }
        }

        switch (vorbis_synthesis_headerin(vo_info, &vo_comm, &pkt)) {
        case 0:
            break;

        case OV_EBADHEADER:
            INFO1("bad vorbis header");

        case OV_ENOTVORBIS:
        default:
            goto end;
        }

        /* decode successful so grab packet */
        ogg_stream_packetout(&stream, &pkt);
    }

    /* maybe print something about comment or etc? */

    mf->audio_ctx = (vorbis_dsp_state *)xmalloc(sizeof(*mf->audio_ctx));
    mf->audio = (ogg_stream_state *)xmalloc(sizeof(*mf->audio));
    vo_blk = (vorbis_block *)xmalloc(sizeof(*vo_blk));
    memcpy(mf->audio, &stream, sizeof(stream));
    vorbis_synthesis_init(mf->audio_ctx, vo_info);
    vorbis_block_init(mf->audio_ctx, vo_blk);
    mf->audio_info = vo_info;
    mf->audio_blk = vo_blk;
    rval = 1;
end:
    vorbis_comment_clear(&vo_comm);

    if (rval <= 0) {
        ogg_stream_clear(&stream);
        vorbis_info_clear(vo_info);
        free(vo_info);
    }

    return rval;
}
コード例 #10
0
ファイル: mmfile.cpp プロジェクト: BlastarIndia/raceintospace
static int
init_theora(mm_file *mf, ogg_page *pg)
{
    int pkts = 0;
    int res = 0;
    int rval = 0;
    theora_info *th_info = NULL;
    theora_comment th_comm;
    ogg_packet pkt;
    ogg_stream_state stream;

    assert(mf);
    th_info = (theora_info *)xmalloc(sizeof(*mf->video_info));
    theora_info_init(th_info);
    theora_comment_init(&th_comm);
    ogg_stream_init(&stream, ogg_page_serialno(pg));

    if (ogg_page_packets(pg) != 1 || ogg_page_granulepos(pg) != 0) {
        goto end;
    }

    if (ogg_stream_pagein(&stream, pg))
        /* should not happen */
    {
        goto end;
    }

    /* Three first packets must go successfully through the loop. */
    for (pkts = 0; pkts < 3; ++pkts) {
        while ((res = ogg_stream_packetpeek(&stream, &pkt)) != 1) {
            if (res < 0
                || get_page(mf, pg) <= 0
                || ogg_stream_pagein(&stream, pg) < 0) {
                rval = -1;
                goto end;
            }
        }

        switch (theora_decode_header(th_info, &th_comm, &pkt)) {
        case 0:
            break;

        case OC_VERSION:
        case OC_NEWPACKET:
            INFO1("incompatible theora file");

            /* fall through */
        case OC_BADHEADER:
        default:
            goto end;
        }

        /* decode successful so grab packet */
        ogg_stream_packetout(&stream, &pkt);
    }

    mf->video_ctx = (theora_state *)xmalloc(sizeof(*mf->video_ctx));
    mf->video = (ogg_stream_state *)xmalloc(sizeof(*mf->video));
    memcpy(mf->video, &stream, sizeof(stream));
    theora_decode_init(mf->video_ctx, th_info);
    mf->video_info = th_info;
    rval = 1;
end:
    theora_comment_clear(&th_comm);

    if (rval <= 0) {
        ogg_stream_clear(&stream);
        theora_info_clear(th_info);
        free(th_info);
        mf->video_info = NULL;
    }

    return rval;
}
コード例 #11
0
ファイル: ogg.c プロジェクト: jameshilliard/WECB-BH-GPL
static void vorbis_process(stream_processor *stream, ogg_page *page,
			   MP3FILE *pmp3)
{
    ogg_packet packet;
    misc_vorbis_info *inf = stream->data;
    int i, header=0;
    int k;

    ogg_stream_pagein(&stream->os, page);
    if(inf->doneheaders < 3)
        header = 1;

    while(ogg_stream_packetout(&stream->os, &packet) > 0) {
        if(inf->doneheaders < 3) {
            if(vorbis_synthesis_headerin(&inf->vi, &inf->vc, &packet) < 0) {
	        DPRINTF(E_WARN, L_SCAN, "Could not decode vorbis header "
                       "packet - invalid vorbis stream (%d)\n", stream->num);
                continue;
            }
            inf->doneheaders++;
            if(inf->doneheaders == 3) {
                if(ogg_page_granulepos(page) != 0 || ogg_stream_packetpeek(&stream->os, NULL) == 1)
		    DPRINTF(E_WARN, L_SCAN, "Vorbis stream %d does not have headers "
                           "correctly framed. Terminal header page contains "
                           "additional packets or has non-zero granulepos\n",
                            stream->num);
		DPRINTF(E_DBG, L_SCAN, "Vorbis headers parsed for stream %d, "
			"information follows...\n", stream->num);
                /*
                DPRINTF(E_INF, L_SCAN, "Version: %d\n", inf->vi.version);
                k = 0;
                while(releases[k].vendor_string) {
                    if(!strcmp(inf->vc.vendor, releases[k].vendor_string)) {
		      //PENDING:
		      DPRINTF(E_INF, L_SCAN, "Vendor: %s (%s)\n",
			      inf->vc.vendor, releases[k].desc);
                        break;
                    }
                    k++;
                    }

                if(!releases[k].vendor_string)
                DPRINTF(E_INF, L_SCAN, "Vendor: %s\n", inf->vc.vendor);*/

                DPRINTF(E_DBG, L_SCAN, "Channels: %d\n", inf->vi.channels);
                DPRINTF(E_DBG, L_SCAN, "Rate: %ld\n\n", inf->vi.rate);

		pmp3->samplerate = inf->vi.rate;

                if(inf->vi.bitrate_nominal > 0) {
                  DPRINTF(E_DBG, L_SCAN, "Nominal bitrate: %f kb/s\n",
                          (double)inf->vi.bitrate_nominal / 1000.0);
		    pmp3->bitrate = inf->vi.bitrate_nominal / 1000;
		}
                else {
                    int         upper_rate, lower_rate;

                    DPRINTF(E_DBG, L_SCAN, "Nominal bitrate not set\n");

                    /* Average the lower and upper bitrates if set */
                    
                    upper_rate = 0;
                    lower_rate = 0;

                    if(inf->vi.bitrate_upper > 0) {
                        DPRINTF(E_DBG, L_SCAN, "Upper bitrate: %f kb/s\n",
                                (double)inf->vi.bitrate_upper / 1000.0);
                        upper_rate = inf->vi.bitrate_upper;
                    } else {
                        DPRINTF(E_DBG, L_SCAN, "Upper bitrate not set\n");
                    }

                    if(inf->vi.bitrate_lower > 0) {
                        DPRINTF(E_DBG, L_SCAN,"Lower bitrate: %f kb/s\n",
                                (double)inf->vi.bitrate_lower / 1000.0);
                        lower_rate = inf->vi.bitrate_lower;;
                    } else {
                        DPRINTF(E_DBG, L_SCAN, "Lower bitrate not set\n");
                    }

                    if (upper_rate && lower_rate) {
                        pmp3->bitrate = (upper_rate + lower_rate) / 2;
                    } else {
                        pmp3->bitrate = upper_rate + lower_rate;
                    }
                }

                if(inf->vc.comments > 0)
                    DPRINTF(E_DBG, L_SCAN,
                            "User comments section follows...\n");

                for(i=0; i < inf->vc.comments; i++) {
                    char *sep = strchr(inf->vc.user_comments[i], '=');
                    char *decoded;
                    int j;
                    int broken = 0;
                    unsigned char *val;
                    int bytes;
                    int remaining;

                    if(sep == NULL) {
		        DPRINTF(E_WARN, L_SCAN,
				"Comment %d in stream %d is invalidly "
                               "formatted, does not contain '=': \"%s\"\n",
                               i, stream->num, inf->vc.user_comments[i]);
                        continue;
                    }

                    for(j=0; j < sep-inf->vc.user_comments[i]; j++) {
                        if(inf->vc.user_comments[i][j] < 0x20 ||
                           inf->vc.user_comments[i][j] > 0x7D) {
			    DPRINTF(E_WARN, L_SCAN,
				    "Warning: Invalid comment fieldname in "
                                   "comment %d (stream %d): \"%s\"\n",
                                    i, stream->num, inf->vc.user_comments[i]);
                            broken = 1;
                            break;
                        }
                    }

                    if(broken)
                        continue;

                    val = inf->vc.user_comments[i];

                    j = sep-inf->vc.user_comments[i]+1;
                    while(j < inf->vc.comment_lengths[i])
                    {
                        remaining = inf->vc.comment_lengths[i] - j;
                        if((val[j] & 0x80) == 0)
                            bytes = 1;
                        else if((val[j] & 0x40) == 0x40) {
                            if((val[j] & 0x20) == 0)
                                bytes = 2;
                            else if((val[j] & 0x10) == 0)
                                bytes = 3;
                            else if((val[j] & 0x08) == 0)
                                bytes = 4;
                            else if((val[j] & 0x04) == 0)
                                bytes = 5;
                            else if((val[j] & 0x02) == 0)
                                bytes = 6;
                            else {
                                DPRINTF(E_WARN, L_SCAN,
					"Illegal UTF-8 sequence in "
                                       "comment %d (stream %d): length "
                                       "marker wrong\n",
                                        i, stream->num);
                                broken = 1;
                                break;
                            }
                        }
                        else {
                            DPRINTF(E_WARN, L_SCAN,
				    "Illegal UTF-8 sequence in comment "
                                    "%d (stream %d): length marker wrong\n",
                                    i, stream->num);
                            broken = 1;
                            break;
                        }

                        if(bytes > remaining) {
                            DPRINTF(E_WARN, L_SCAN,
				    "Illegal UTF-8 sequence in comment "
				    "%d (stream %d): too few bytes\n",
				    i, stream->num);
                            broken = 1;
                            break;
                        }

                        switch(bytes) {
                            case 1:
                                /* No more checks needed */
                                break;
                            case 2:
                                if((val[j+1] & 0xC0) != 0x80)
                                    broken = 1;
                                if((val[j] & 0xFE) == 0xC0)
                                    broken = 1;
                                break;
                            case 3:
                                if(!((val[j] == 0xE0 && val[j+1] >= 0xA0 && 
                                        val[j+1] <= 0xBF && 
                                        (val[j+2] & 0xC0) == 0x80) ||
                                   (val[j] >= 0xE1 && val[j] <= 0xEC &&
                                        (val[j+1] & 0xC0) == 0x80 &&
                                        (val[j+2] & 0xC0) == 0x80) ||
                                   (val[j] == 0xED && val[j+1] >= 0x80 &&
                                        val[j+1] <= 0x9F &&
                                        (val[j+2] & 0xC0) == 0x80) ||
                                   (val[j] >= 0xEE && val[j] <= 0xEF &&
                                        (val[j+1] & 0xC0) == 0x80 &&
                                        (val[j+2] & 0xC0) == 0x80)))
                                    broken = 1;
                                if(val[j] == 0xE0 && (val[j+1] & 0xE0) == 0x80)
                                    broken = 1;
                                break;
                            case 4:
                                if(!((val[j] == 0xF0 && val[j+1] >= 0x90 &&
                                        val[j+1] <= 0xBF &&
                                        (val[j+2] & 0xC0) == 0x80 &&
                                        (val[j+3] & 0xC0) == 0x80) ||
                                     (val[j] >= 0xF1 && val[j] <= 0xF3 &&
                                        (val[j+1] & 0xC0) == 0x80 &&
                                        (val[j+2] & 0xC0) == 0x80 &&
                                        (val[j+3] & 0xC0) == 0x80) ||
                                     (val[j] == 0xF4 && val[j+1] >= 0x80 &&
                                        val[j+1] <= 0x8F &&
                                        (val[j+2] & 0xC0) == 0x80 &&
                                        (val[j+3] & 0xC0) == 0x80)))
                                    broken = 1;
                                if(val[j] == 0xF0 && (val[j+1] & 0xF0) == 0x80)
                                    broken = 1;
                                break;
                            /* 5 and 6 aren't actually allowed at this point*/  
                            case 5:
                                broken = 1;
                                break;
                            case 6:
                                broken = 1;
                                break;
                        }

                        if(broken) {
			    DPRINTF(E_WARN, L_SCAN,
				    "Illegal UTF-8 sequence in comment "
				    "%d (stream %d): invalid sequence\n",
                                    i, stream->num);
                            broken = 1;
                            break;
                        }

                        j += bytes;
                    }

                    if(!broken) {
		      /*                        if(utf8_decode(sep+1, &decoded) < 0) {
			    DPRINTF(E_WARN, L_SCAN,
				    "Failure in utf8 decoder. This "
				    "should be impossible\n");
                            continue;
			    }*/
                      
                      DPRINTF(E_DBG, L_SCAN,
                              "\t%s\n", inf->vc.user_comments[i]);

                        if (!strncasecmp(inf->vc.user_comments[i],"TITLE",5)) {
                            pmp3->title = strdup(sep + 1);
                            DPRINTF(E_DBG, L_SCAN, "Mapping %s to title.\n",
                                    sep + 1);
			} else if (!strncasecmp(inf->vc.user_comments[i], "ARTIST", 6)) {
                            pmp3->artist = strdup(sep + 1);
                            DPRINTF(E_DBG, L_SCAN, "Mapping %s to artist.\n",
                                    sep + 1);
			} else if (!strncasecmp(inf->vc.user_comments[i], "ALBUM", 5)) {
                            pmp3->album = strdup(sep + 1);
                            DPRINTF(E_DBG, L_SCAN, "Mapping %s to album.\n",
                                    sep + 1);
			} else if (!strncasecmp(inf->vc.user_comments[i],
					   "TRACKNUMBER", 11)) {
                            pmp3->track = atoi(sep + 1);
                            DPRINTF(E_INF, L_SCAN, "Mapping %s to track.\n",
                                    sep + 1);
			} else if (!strncasecmp(inf->vc.user_comments[i], "GENRE", 5)) {
                            pmp3->genre = strdup(sep + 1);
                            DPRINTF(E_INF, L_SCAN, "Mapping %s to genre.\n",
                                    sep + 1);
			} else if (!strncasecmp(inf->vc.user_comments[i], "DATE", 4)) {
			  //PENDING: Should only parse first 4 characters
                            pmp3->year = atoi(sep + 1);
                            DPRINTF(E_INF, L_SCAN, "Mapping %s to year.\n",
                                    sep + 1);
			} else if (!strncasecmp(inf->vc.user_comments[i], "COMMENT", 7)) {
                            pmp3->comment = strdup(sep + 1);
                            DPRINTF(E_INF, L_SCAN, "Mapping %s to comment.\n",
                                    sep + 1);
			}

                        *sep = 0;
			/*                        free(decoded);*/
                    }
                }
            }
        }
    }

    if(!header) {
        ogg_int64_t gp = ogg_page_granulepos(page);
        if(gp > 0) {
            if(gp < inf->lastgranulepos)
#ifdef _WIN32
                DPRINTF(E_WARN, L_SCAN, "granulepos in stream %d decreases from %I64d to %I64d",
                        stream->num, inf->lastgranulepos, gp);
#else
                DPRINTF(E_WARN, L_SCAN, "granulepos in stream %d decreases from %lld to %lld",
                        stream->num, inf->lastgranulepos, gp);
#endif
            inf->lastgranulepos = gp;
        }
        else {
            DPRINTF(E_WARN, L_SCAN, "Negative granulepos on vorbis stream outside of headers. This file was created by a buggy encoder\n");
        }
        if(inf->firstgranulepos < 0) { /* Not set yet */
        }
        inf->bytes += page->header_len + page->body_len;
    }
}
コード例 #12
0
int main(int argc,char *argv[]){

  ogg_packet op;

  int long_option_index;
  int c;

  struct timeb start;
  struct timeb after;
  struct timeb last;
  int fps_only=0;
  int frames = 0;

  FILE *infile = stdin;
  outfile = stdout;

#ifdef _WIN32 /* We need to set stdin/stdout to binary mode on windows. */
  /* Beware the evil ifdef. We avoid these where we can, but this one we
     cannot. Don't add any more, you'll probably go to hell if you do. */
  _setmode( _fileno( stdin ), _O_BINARY );
  _setmode( _fileno( stdout ), _O_BINARY );
#endif

  /* Process option arguments. */
  while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){
    switch(c){
    case 'o':
      if(strcmp(optarg,"-")!=0){
        outfile=fopen(optarg,"wb");
        if(outfile==NULL){
          fprintf(stderr,"Unable to open output file '%s'\n", optarg);
          exit(1);
        }
      }else{
        outfile=stdout;
      }
      break;

    case 'c':
      crop=1;
      break;

    case 'r':
      raw=1;
      break;

    case 'f':
      fps_only = 1;
      outfile = NULL;
      break;

    default:
      usage();
    }
  }
  if(optind<argc){
    infile=fopen(argv[optind],"rb");
    if(infile==NULL){
      fprintf(stderr,"Unable to open '%s' for extraction.\n", argv[optind]);
      exit(1);
    }
    if(++optind<argc){
      usage();
      exit(1);
    }
  }
  /*Ok, Ogg parsing.
    The idea here is we have a bitstream that is made up of Ogg pages.
    The libogg sync layer will find them for us.
    There may be pages from several logical streams interleaved; we find the
     first theora stream and ignore any others.
    Then we pass the pages for our stream to the libogg stream layer which
     assembles our original set of packets out of them.
    It's the packets that libtheora actually knows how to handle.*/

  /* start up Ogg stream synchronization layer */
  ogg_sync_init(&oy);

  /* init supporting Theora structures needed in header parsing */
  th_comment_init(&tc);
  th_info_init(&ti);

  /*Ogg file open; parse the headers.
    Theora (like Vorbis) depends on some initial header packets for decoder
     setup and initialization.
    We retrieve these first before entering the main decode loop.*/

  /* Only interested in Theora streams */
  while(!stateflag){
    int ret=buffer_data(infile,&oy);
    if(ret==0)break;
    while(ogg_sync_pageout(&oy,&og)>0){
      int got_packet;
      ogg_stream_state test;

      /* is this a mandated initial header? If not, stop parsing */
      if(!ogg_page_bos(&og)){
        /* don't leak the page; get it into the appropriate stream */
        queue_page(&og);
        stateflag=1;
        break;
      }

      ogg_stream_init(&test,ogg_page_serialno(&og));
      ogg_stream_pagein(&test,&og);
      got_packet = ogg_stream_packetpeek(&test,&op);

      /* identify the codec: try theora */
      if((got_packet==1) && !theora_p && (theora_processing_headers=
       th_decode_headerin(&ti,&tc,&ts,&op))>=0){
        /* it is theora -- save this stream state */
        memcpy(&to,&test,sizeof(test));
        theora_p=1;
        /*Advance past the successfully processed header.*/
        if(theora_processing_headers)ogg_stream_packetout(&to,NULL);
      }else{
        /* whatever it is, we don't care about it */
        ogg_stream_clear(&test);
      }
    }
    /* fall through to non-bos page parsing */
  }

  /* we're expecting more header packets. */
  while(theora_p && theora_processing_headers){
    int ret;

    /* look for further theora headers */
    while(theora_processing_headers&&(ret=ogg_stream_packetpeek(&to,&op))){
      if(ret<0)continue;
      theora_processing_headers=th_decode_headerin(&ti,&tc,&ts,&op);
      if(theora_processing_headers<0){
        fprintf(stderr,"Error parsing Theora stream headers; "
         "corrupt stream?\n");
        exit(1);
      }
      else if(theora_processing_headers>0){
        /*Advance past the successfully processed header.*/
        ogg_stream_packetout(&to,NULL);
      }
      theora_p++;
    }

    /*Stop now so we don't fail if there aren't enough pages in a short
       stream.*/
    if(!(theora_p && theora_processing_headers))break;

    /* The header pages/packets will arrive before anything else we
       care about, or the stream is not obeying spec */

    if(ogg_sync_pageout(&oy,&og)>0){
      queue_page(&og); /* demux into the appropriate stream */
    }else{
      int ret=buffer_data(infile,&oy); /* someone needs more data */
      if(ret==0){
        fprintf(stderr,"End of file while searching for codec headers.\n");
        exit(1);
      }
    }
  }

  /* and now we have it all.  initialize decoders */
  if(theora_p){
    dump_comments(&tc);
    td=th_decode_alloc(&ti,ts);
    fprintf(stderr,"Ogg logical stream %lx is Theora %dx%d %.02f fps video\n"
     "Encoded frame content is %dx%d with %dx%d offset\n",
     to.serialno,ti.frame_width,ti.frame_height,
     (double)ti.fps_numerator/ti.fps_denominator,
     ti.pic_width,ti.pic_height,ti.pic_x,ti.pic_y);

    /*{
      int arg = 0xffff;
      th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_MBMODE,&arg,sizeof(arg));
      th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_MV,&arg,sizeof(arg));
      th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_QI,&arg,sizeof(arg));
      arg=10;
      th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_BITS,&arg,sizeof(arg));
    }*/
  }else{
    /* tear down the partial theora setup */
    th_info_clear(&ti);
    th_comment_clear(&tc);
  }
  /*Either way, we're done with the codec setup data.*/
  th_setup_free(ts);

  /* open video */
  if(theora_p)open_video();

  if(!raw && outfile){
    static const char *CHROMA_TYPES[4]={"420jpeg",NULL,"422jpeg","444"};
    int width;
    int height;
    if(ti.pixel_fmt>=4||ti.pixel_fmt==TH_PF_RSVD){
      fprintf(stderr,"Unknown pixel format: %i\n",ti.pixel_fmt);
      exit(1);
    }
    if(crop){
      int hdec;
      int vdec;
      hdec=!(ti.pixel_fmt&1);
      vdec=!(ti.pixel_fmt&2);
      if((ti.pic_x&hdec)||(ti.pic_width&hdec)
       ||(ti.pic_y&vdec)||(ti.pic_height&vdec)){
        fprintf(stderr,
         "Error: Cropped images with odd offsets/sizes and chroma subsampling\n"
         "cannot be output to YUV4MPEG2. Remove the --crop flag or add the\n"
         "--raw flag.\n");
        exit(1);
      }
      width=ti.pic_width;
      height=ti.pic_height;
    }
    else{
      width=ti.frame_width;
      height=ti.frame_height;
    }
    fprintf(outfile,"YUV4MPEG2 C%s W%d H%d F%d:%d I%c A%d:%d\n",
     CHROMA_TYPES[ti.pixel_fmt],width,height,
     ti.fps_numerator,ti.fps_denominator,'p',
     ti.aspect_numerator,ti.aspect_denominator);
  }

  /* install signal handler */
  signal (SIGINT, sigint_handler);

  /*Finally the main decode loop.

    It's one Theora packet per frame, so this is pretty straightforward if
     we're not trying to maintain sync with other multiplexed streams.

    The videobuf_ready flag is used to maintain the input buffer in the libogg
     stream state.
    If there's no output frame available at the end of the decode step, we must
     need more input data.
    We could simplify this by just using the return code on
     ogg_page_packetout(), but the flag system extends easily to the case where
     you care about more than one multiplexed stream (like with audio
     playback).
    In that case, just maintain a flag for each decoder you care about, and
     pull data when any one of them stalls.

    videobuf_time holds the presentation time of the currently buffered video
     frame.
    We ignore this value.*/

  stateflag=0; /* playback has not begun */
  /* queue any remaining pages from data we buffered but that did not
      contain headers */
  while(ogg_sync_pageout(&oy,&og)>0){
    queue_page(&og);
  }

  if(fps_only){
    ftime(&start);
    ftime(&last);
  }

  while(!got_sigint){

    while(theora_p && !videobuf_ready){
      /* theora is one in, one out... */
      if(ogg_stream_packetout(&to,&op)>0){

        if(th_decode_packetin(td,&op,&videobuf_granulepos)>=0){
          videobuf_time=th_granule_time(td,videobuf_granulepos);
          videobuf_ready=1;
          frames++;
          if(fps_only)
            ftime(&after);
        }

      }else
        break;
    }

    if(fps_only && (videobuf_ready || fps_only==2)){
      long ms =
        after.time*1000.+after.millitm-
        (last.time*1000.+last.millitm);

      if(ms>500 || fps_only==1 ||
         (feof(infile) && !videobuf_ready)){
        float file_fps = (float)ti.fps_numerator/ti.fps_denominator;
        fps_only=2;

        ms = after.time*1000.+after.millitm-
          (start.time*1000.+start.millitm);

        fprintf(stderr,"\rframe:%d rate:%.2fx           ",
                frames,
                frames*1000./(ms*file_fps));
        memcpy(&last,&after,sizeof(last));
      }
    }

    if(!videobuf_ready && feof(infile))break;

    if(!videobuf_ready){
      /* no data yet for somebody.  Grab another page */
      buffer_data(infile,&oy);
      while(ogg_sync_pageout(&oy,&og)>0){
        queue_page(&og);
      }
    }
    /* dumpvideo frame, and get new one */
    else if(outfile)video_write();

    videobuf_ready=0;
  }

  /* end of decoder loop -- close everything */

  if(theora_p){
    ogg_stream_clear(&to);
    th_decode_free(td);
    th_comment_clear(&tc);
    th_info_clear(&ti);
  }
  ogg_sync_clear(&oy);

  if(infile && infile!=stdin)fclose(infile);
  if(outfile && outfile!=stdout)fclose(outfile);

  fprintf(stderr, "\n\n%d frames\n", frames);
  fprintf(stderr, "\nDone.\n");

  return(0);

}
コード例 #13
0
ファイル: ogginfo2.c プロジェクト: zdementor/my-deps
static void vorbis_process(stream_processor *stream, ogg_page *page )
{
    ogg_packet packet;
    misc_vorbis_info *inf = stream->data;
    int i, header=0;
    int k;

    ogg_stream_pagein(&stream->os, page);
    if(inf->doneheaders < 3)
        header = 1;

    while(ogg_stream_packetout(&stream->os, &packet) > 0) {
        if(inf->doneheaders < 3) {
            if(vorbis_synthesis_headerin(&inf->vi, &inf->vc, &packet) < 0) {
                warn(_("Warning: Could not decode vorbis header "
                       "packet - invalid vorbis stream (%d)\n"), stream->num);
                continue;
            }
            inf->doneheaders++;
            if(inf->doneheaders == 3) {
                if(ogg_page_granulepos(page) != 0 || ogg_stream_packetpeek(&stream->os, NULL) == 1)
                    warn(_("Warning: Vorbis stream %d does not have headers "
                           "correctly framed. Terminal header page contains "
                           "additional packets or has non-zero granulepos\n"),
                            stream->num);
                info(_("Vorbis headers parsed for stream %d, "
                       "information follows...\n"), stream->num);

                info(_("Version: %d\n"), inf->vi.version);
                k = 0;
                while(releases[k].vendor_string) {
                    if(!strcmp(inf->vc.vendor, releases[k].vendor_string)) {
                        info(_("Vendor: %s (%s)\n"), inf->vc.vendor, 
                                    releases[k].desc);
                        break;
                    }
                    k++;
                }
                if(!releases[k].vendor_string)
                    info(_("Vendor: %s\n"), inf->vc.vendor);
                info(_("Channels: %d\n"), inf->vi.channels);
                info(_("Rate: %ld\n\n"), inf->vi.rate);

                if(inf->vi.bitrate_nominal > 0)
                    info(_("Nominal bitrate: %f kb/s\n"), 
                            (double)inf->vi.bitrate_nominal / 1000.0);
                else
                    info(_("Nominal bitrate not set\n"));

                if(inf->vi.bitrate_upper > 0)
                    info(_("Upper bitrate: %f kb/s\n"), 
                            (double)inf->vi.bitrate_upper / 1000.0);
                else
                    info(_("Upper bitrate not set\n"));

                if(inf->vi.bitrate_lower > 0)
                    info(_("Lower bitrate: %f kb/s\n"), 
                            (double)inf->vi.bitrate_lower / 1000.0);
                else
                    info(_("Lower bitrate not set\n"));

                if(inf->vc.comments > 0)
                    info(_("User comments section follows...\n"));

                for(i=0; i < inf->vc.comments; i++) {
                    char *comment = inf->vc.user_comments[i];
		    check_xiph_comment(stream, i, comment, 
		            inf->vc.comment_lengths[i]);
		}
            }
        }
    }

    if(!header) {
        ogg_int64_t gp = ogg_page_granulepos(page);
        if(gp > 0) {
            if(gp < inf->lastgranulepos)
#ifdef _WIN32
                warn(_("Warning: granulepos in stream %d decreases from %I64d to %I64d" ),
                        stream->num, inf->lastgranulepos, gp);
#else
                warn(_("Warning: granulepos in stream %d decreases from %lld to %lld" ),
                        stream->num, inf->lastgranulepos, gp);
#endif
            inf->lastgranulepos = gp;
        }
        else {
            warn(_("Negative granulepos on vorbis stream outside of headers. This file was created by a buggy encoder\n"));
        }
        if(inf->firstgranulepos < 0) { /* Not set yet */
        }
        inf->bytes += page->header_len + page->body_len;
    }
}
コード例 #14
0
ファイル: ogginfo2.c プロジェクト: zdementor/my-deps
static void theora_process(stream_processor *stream, ogg_page *page)
{
    ogg_packet packet;
    misc_theora_info *inf = stream->data;
    int i, header=0;

    ogg_stream_pagein(&stream->os, page);
    if(inf->doneheaders < 3)
        header = 1;

    while(ogg_stream_packetout(&stream->os, &packet) > 0) {
        if(inf->doneheaders < 3) {
            if(theora_decode_header(&inf->ti, &inf->tc, &packet) < 0) {
                warn(_("Warning: Could not decode theora header "
                       "packet - invalid theora stream (%d)\n"), stream->num);
                continue;
            }
            inf->doneheaders++;
            if(inf->doneheaders == 3) {
                if(ogg_page_granulepos(page) != 0 || ogg_stream_packetpeek(&stream->os, NULL) == 1)
                    warn(_("Warning: Theora stream %d does not have headers "
                           "correctly framed. Terminal header page contains "
                           "additional packets or has non-zero granulepos\n"),
                            stream->num);
                info(_("Theora headers parsed for stream %d, "
                       "information follows...\n"), stream->num);

                info(_("Version: %d.%d.%d\n"), inf->ti.version_major, inf->ti.version_minor, inf->ti.version_subminor);
   
                info(_("Vendor: %s\n"), inf->tc.vendor);
                info(_("Width: %d\n"), inf->ti.frame_width);
                info(_("Height: %d\n"), inf->ti.frame_height);
		info(_("Total image: %d by %d, crop offset (%d, %d)\n"),
		    inf->ti.width, inf->ti.height, inf->ti.offset_x, inf->ti.offset_y);
		if(inf->ti.offset_x + inf->ti.frame_width > inf->ti.width)
		    warn(_("Frame offset/size invalid: width incorrect\n"));
		if(inf->ti.offset_y + inf->ti.frame_height > inf->ti.height)
		    warn(_("Frame offset/size invalid: height incorrect\n"));

		if(inf->ti.fps_numerator == 0 || inf->ti.fps_denominator == 0) 
		   warn(_("Invalid zero framerate\n"));
		else
		   info(_("Framerate %d/%d (%.02f fps)\n"), inf->ti.fps_numerator, inf->ti.fps_denominator, (float)inf->ti.fps_numerator/(float)inf->ti.fps_denominator);
		
		if(inf->ti.aspect_numerator == 0 || inf->ti.aspect_denominator == 0) 
		{
		    info(_("Aspect ratio undefined\n"));
		}	
		else
		{
		    float frameaspect = (float)inf->ti.frame_width/(float)inf->ti.frame_height * (float)inf->ti.aspect_numerator/(float)inf->ti.aspect_denominator; 
		    info(_("Pixel aspect ratio %d:%d (1:%f)\n"), inf->ti.aspect_numerator, inf->ti.aspect_denominator, (float)inf->ti.aspect_numerator/(float)inf->ti.aspect_denominator);
                    if(abs(frameaspect - 4.0/3.0) < 0.02)
			info(_("Frame aspect 4:3\n"));
                    else if(abs(frameaspect - 16.0/9.0) < 0.02)
			info(_("Frame aspect 16:9\n"));
		    else
			info(_("Frame aspect 1:%d\n"), frameaspect);
		}

		if(inf->ti.colorspace == OC_CS_ITU_REC_470M)
		    info(_("Colourspace: Rec. ITU-R BT.470-6 System M (NTSC)\n")); 
		else if(inf->ti.colorspace == OC_CS_ITU_REC_470BG)
		    info(_("Colourspace: Rec. ITU-R BT.470-6 Systems B and G (PAL)\n")); 
		else
		    info(_("Colourspace unspecified\n"));

		if(inf->ti.pixelformat == OC_PF_420)
		    info(_("Pixel format 4:2:0\n"));
		else if(inf->ti.pixelformat == OC_PF_422)
		    info(_("Pixel format 4:2:2\n"));
		else if(inf->ti.pixelformat == OC_PF_444)
		    info(_("Pixel format 4:4:4\n"));
		else
		    warn(_("Pixel format invalid\n"));

		info(_("Target bitrate: %d kbps\n"), inf->ti.target_bitrate/1000);
		info(_("Nominal quality setting (0-63): %d\n"), inf->ti.quality);

                if(inf->tc.comments > 0)
                    info(_("User comments section follows...\n"));

                for(i=0; i < inf->tc.comments; i++) {
                    char *comment = inf->tc.user_comments[i];
		    check_xiph_comment(stream, i, comment, 
		            inf->tc.comment_lengths[i]);
		}
	    }
	}
    }

    if(!header) {
        ogg_int64_t gp = ogg_page_granulepos(page);
        if(gp > 0) {
            if(gp < inf->lastgranulepos)
#ifdef _WIN32
                warn(_("Warning: granulepos in stream %d decreases from %I64d to %I64d" ),
                        stream->num, inf->lastgranulepos, gp);
#else
                warn(_("Warning: granulepos in stream %d decreases from %lld to %lld" ),
                        stream->num, inf->lastgranulepos, gp);
#endif
            inf->lastgranulepos = gp;
        }
        if(inf->firstgranulepos < 0) { /* Not set yet */
        }
        inf->bytes += page->header_len + page->body_len;
    }
}
コード例 #15
0
ファイル: dump_video.c プロジェクト: AlecGamble/daala
int main(int argc, char *argv[]) {
  daala_packet dp;
  ogg_packet op;

  int long_option_index;
  int c;
  ogg_sync_state oy;
  ogg_page og;
  ogg_stream_state to;
  daala_info di;
  daala_comment dc;
  daala_setup_info *ds;
  daala_dec_ctx *dd;
  daala_image img;
  const char *optstring = "o:r";
  struct option options [] = {
   { "output", required_argument, NULL, 'o' },
   { "raw", no_argument, NULL, 'r' }, /*Disable YUV4MPEG2 headers:*/
   { "version", no_argument, NULL, 0},
   { NULL, 0, NULL, 0 }
  };
  int frames = 0;
  int pix_fmt = 1;
  int daala_p = 0;
  int daala_processing_headers = 0;
  int stateflag = 0;
  /* single frame video buffering */
  int videobuf_ready = 0;
  int raw = 0;
  FILE *outfile = NULL;
  ogg_int32_t pic_width = 0;
  ogg_int32_t pic_height = 0;
  ogg_int32_t fps_num = 0;
  ogg_int32_t fps_denom = 0;
  FILE *infile = stdin;
  outfile = stdout;
  dd = NULL;
  ds = NULL;
  daala_log_init();
#ifdef _WIN32 /* We need to set stdin/stdout to binary mode on windows. */
  /* Beware the evil ifdef. We avoid these where we can, but this one we
     cannot. Don't add any more, you'll probably go to hell if you do. */
  _setmode(_fileno(stdin), _O_BINARY);
  _setmode(_fileno(stdout), _O_BINARY);
#endif
  /* Process option arguments. */
  while ((c = getopt_long(argc, argv, optstring, options, &long_option_index))
   != EOF) {
    switch (c) {
      case 'o': {
        if (strcmp(optarg, "-") != 0) {
          outfile = fopen(optarg, "wb");
          if (outfile == NULL) {
            fprintf(stderr, "Unable to open output file '%s'\n", optarg);
            exit(1);
          }
        }
        else {
          outfile = stdout;
        }
        break;
      }
      case 'r': {
        raw = 1;
        break;
      }
      case 0: {
        if (strcmp(options[long_option_index].name, "version") == 0) {
          version();
        }
        break;
      }
      default: usage(); break;
    }
  }
  if (optind < argc) {
    infile = fopen(argv[optind], "rb");
    if (infile == NULL) {
      fprintf(stderr, "Unable to open '%s' for extraction.\n", argv[optind]);
      exit(1);
    }
    if (++optind < argc) {
      usage();
      exit(1);
    }
  }
  /*Ok, Ogg parsing.
    The idea here is we have a bitstream that is made up of Ogg pages.
    The libogg sync layer will find them for us.
    There may be pages from several logical streams interleaved; we find the
     first daala stream and ignore any others.
    Then we pass the pages for our stream to the libogg stream layer which
     assembles our original set of packets out of them.
   start up Ogg stream synchronization layer */
  ogg_sync_init(&oy);

  /* init supporting Theora structures needed in header parsing */
  daala_comment_init(&dc);
  daala_info_init(&di);
  /*Ogg file open; parse the headers.
    Theora (like Vorbis) depends on some initial header packets for decoder
     setup and initialization.
    We retrieve these first before entering the main decode loop.*/
  /* Only interested in Daala streams */
  while (!stateflag) {
    int ret = buffer_data(infile, &oy);
    if (ret == 0) break;
    while (ogg_sync_pageout(&oy, &og) > 0) {
      int got_packet;
      ogg_stream_state test;
      /* is this a mandated initial header? If not, stop parsing */
      if (!ogg_page_bos(&og)) {
        /* don't leak the page; get it into the appropriate stream */
        queue_page(&og, &to, daala_p);
        stateflag = 1;
        break;
      }
      ogg_stream_init(&test, ogg_page_serialno(&og));
      ogg_stream_pagein(&test, &og);
      got_packet = ogg_stream_packetpeek(&test, &op);

      ogg_to_daala_packet(&dp, &op);
      /* identify the codec: try daala */
      if ((got_packet == 1) && !daala_p && (daala_processing_headers =
       daala_decode_header_in(&di, &dc, &ds, &dp)) >= 0) {
        /* it is daala -- save this stream state */
        memcpy(&to, &test, sizeof(test));
        daala_p = 1;
        /*Advance past the successfully processed header.*/
        if (daala_processing_headers) ogg_stream_packetout(&to, NULL);
      }
      else {
        /* whatever it is, we don't care about it */
        ogg_stream_clear(&test);
      }
    }
    /* fall through to non-bos page parsing */
  }
  /* we're expecting more header packets. */
  while (daala_p && daala_processing_headers) {
    int ret;
    /* look for further daala headers */
    while (daala_processing_headers &&
     (ret = ogg_stream_packetpeek(&to, &op))) {
      if (ret < 0) continue;
      ogg_to_daala_packet(&dp, &op);
      daala_processing_headers = daala_decode_header_in(&di, &dc, &ds, &dp);
      if (daala_processing_headers < 0) {
        fprintf(stderr, "Error parsing Daala stream headers; "
         "corrupt stream?\n");
        exit(1);
      }
      else if (daala_processing_headers >= 0) {
        /*Advance past the successfully processed header.*/
        ogg_stream_packetout(&to, NULL);
      }
      daala_p++;
    }
    /*Stop now so we don't fail if there aren't enough pages in a short
       stream.*/
    if (!(daala_p && daala_processing_headers)) break;
    /* The header pages/packets will arrive before anything else we
       care about, or the stream is not obeying spec */
    if (ogg_sync_pageout(&oy, &og) > 0) {
      queue_page(&og, &to, daala_p); /* demux into the appropriate stream */
    }
    else {
      if (buffer_data(infile, &oy) == 0) { /* someone needs more data */
        fprintf(stderr, "End of file while searching for codec headers.\n");
        exit(1);
      }
    }
  }
  /* and now we have it all.  initialize decoders */
  if (daala_p) {
    dump_comments(&dc);
    dd = daala_decode_create(&di, ds);
    fprintf(stderr, "Ogg logical stream %lx is Daala %dx%d %.02f fps video\n",
     to.serialno, di.pic_width, di.pic_height,
     di.timebase_numerator/(double)di.timebase_denominator*di.frame_duration);
  }
  else {
    /* tear down the partial daala setup */
    daala_info_clear(&di);
    daala_comment_clear(&dc);
  }
  /*Either way, we're done with the codec setup data.*/
  daala_setup_free(ds);
  if (!raw && outfile) {
    static const char *CHROMA_TYPES[5] = {
      "420jpeg", NULL, "422jpeg", "444", "mono"
    };
    pic_width = di.pic_width;
    pic_height = di.pic_height;
    fps_num = di.timebase_numerator;
    fps_denom = di.timebase_denominator*di.frame_duration;
    if (di.nplanes > 1) {
      /*calculate pixel_fmt based on the xdec & ydec values from one of the
        chroma planes.*/
      if (di.plane_info[1].xdec == 1 && di.plane_info[1].ydec == 1) {
        pix_fmt = 0;
      }
      else if (di.plane_info[1].xdec == 1 && di.plane_info[1].ydec == 0) {
        pix_fmt = 2;
      }
      else if (di.plane_info[1].xdec == 0 && di.plane_info[1].ydec == 0) {
        pix_fmt = 3;
      }
    }
    else {
      pix_fmt = 4;
    }
    if (pix_fmt >= 5 || pix_fmt == 1) {
      fprintf(stderr, "Unknown pixel format: %i\n", pix_fmt);
      exit(1);
    }
    /*Store header information*/
    fprintf(outfile, "YUV4MPEG2 W%d H%d F%d:%d Ip A%d:%d C%s\n",
     pic_width, pic_height, fps_num, fps_denom,
     di.pixel_aspect_numerator, di.pixel_aspect_denominator,
     CHROMA_TYPES[pix_fmt]);
  }
  /* install signal handler */
  signal(SIGINT, sigint_handler);

  /*Finally the main decode loop.

    It's one Daala packet per frame, so this is pretty straightforward if
     we're not trying to maintain sync with other multiplexed streams.

    The videobuf_ready flag is used to maintain the input buffer in the libogg
     stream state.
    If there's no output frame available at the end of the decode step, we must
     need more input data.
    We could simplify this by just using the return code on
     ogg_page_packetout(), but the flag system extends easily to the case where
     you care about more than one multiplexed stream (like with audio
     playback).
    In that case, just maintain a flag for each decoder you care about, and
     pull data when any one of them stalls.*/

  stateflag = 0; /* playback has not begun */
  /* queue any remaining pages from data we buffered but that did not
      contain headers */
  while (ogg_sync_pageout(&oy, &og) > 0) {
    queue_page(&og, &to, daala_p);
  }
  while (!got_sigint) {
    while (daala_p && !videobuf_ready) {
      if (ogg_stream_packetout(&to, &op) > 0) {
        ogg_to_daala_packet(&dp, &op);
        if (daala_decode_packet_in(dd, &dp) >= 0) {
          videobuf_ready = 1;
          frames++;
        }
      }
      else break;
    }
    if (!videobuf_ready && feof(infile)) break;
    if (!videobuf_ready) {
      /* no data yet for somebody.  Grab another page */
      buffer_data(infile, &oy);
      while (ogg_sync_pageout(&oy, &og) > 0) {
        queue_page(&og, &to, daala_p);
      }
    }
    /* dumpvideo frame, and get new one */
    else if (outfile && daala_decode_img_out(dd, &img)) {
      video_write(outfile, &img, raw);
    }
    videobuf_ready = 0;
  }
  /*Flush the output frame buffer of decoder.*/
  while (!got_sigint && daala_decode_img_out(dd, &img)) {
    video_write(outfile, &img, raw);
  }
  /* end of decoder loop -- close everything */
  if (daala_p) {
    ogg_stream_clear(&to);
    daala_decode_free(dd);
    daala_comment_clear(&dc);
    daala_info_clear(&di);
  }
  ogg_sync_clear(&oy);
  if (infile && infile != stdin) fclose(infile);
  if (outfile && outfile != stdout) fclose(outfile);
  fprintf(stderr, "\n\n%d frames\n", frames);
  fprintf(stderr, "\nDone.\n");

  return 0;
}
コード例 #16
0
ファイル: ripogg.c プロジェクト: hdijkema/libstreamripper
/* Return 1 if the page is a header page */
static int vorbis_process(RIP_MANAGER_INFO * rmi, stream_processor * stream, ogg_page * page, TRACK_INFO * ti)
{
	ogg_packet packet;
	misc_vorbis_info *inf = stream->data;
	int i, header = 0;
	int k;

	ogg_stream_pagein(&stream->os, page);
	if (inf->doneheaders < 3)
		header = 1;

	while (ogg_stream_packetout(&stream->os, &packet) > 0) {
		if (inf->doneheaders < 3) {
			if (vorbis_synthesis_headerin(&inf->vi, &inf->vc, &packet) < 0) {
				warn(_("Warning: Could not decode vorbis header "
				       "packet - invalid vorbis stream (%d)\n"), stream->num);
				continue;
			}
			inf->doneheaders++;
			if (inf->doneheaders == 3) {
				if (ogg_page_granulepos(page) != 0 || ogg_stream_packetpeek(&stream->os, NULL) == 1)
					warn(_("Warning: Vorbis stream %d does not have headers "
					       "correctly framed. Terminal header page contains "
					       "additional packets or has non-zero granulepos\n"), stream->num);
				debug_printf("Vorbis headers parsed for stream %d, "
					     "information follows...\n", stream->num);

				debug_printf("Version: %d\n", inf->vi.version);
				k = 0;
				while (releases[k].vendor_string) {
					if (!strcmp(inf->vc.vendor, releases[k].vendor_string)) {
						debug_printf("Vendor: %s (%s)\n", inf->vc.vendor, releases[k].desc);
						break;
					}
					k++;
				}
				if (!releases[k].vendor_string)
					debug_printf("Vendor: %s\n", inf->vc.vendor);
				debug_printf("Channels: %d\n", inf->vi.channels);
				debug_printf("Rate: %ld\n\n", inf->vi.rate);

				if (inf->vi.bitrate_nominal > 0)
					debug_printf("Nominal bitrate: %f kb/s\n",
						     (double)inf->vi.bitrate_nominal / 1000.0);
				else
					debug_printf("Nominal bitrate not set\n");

				if (inf->vi.bitrate_upper > 0)
					debug_printf("Upper bitrate: %f kb/s\n",
						     (double)inf->vi.bitrate_upper / 1000.0);
				else
					debug_printf("Upper bitrate not set\n");

				if (inf->vi.bitrate_lower > 0)
					debug_printf("Lower bitrate: %f kb/s\n",
						     (double)inf->vi.bitrate_lower / 1000.0);
				else
					debug_printf("Lower bitrate not set\n");

				if (inf->vc.comments > 0)
					debug_printf("User comments section follows...\n");

				for (i = 0; i < inf->vc.comments; i++) {
					char *sep = strchr(inf->vc.user_comments[i], '=');
					char *decoded;
					int j;
					int broken = 0;
					unsigned char *val;
					int bytes;
					int remaining;

					if (sep == NULL) {
						warn(_("Warning: Comment %d in stream %d is invalidly "
						       "formatted, does not contain '=': \"%s\"\n"),
						     i, stream->num, inf->vc.user_comments[i]);
						continue;
					}

					for (j = 0; j < sep - inf->vc.user_comments[i]; j++) {
						if (inf->vc.user_comments[i][j] < 0x20 ||
						    inf->vc.user_comments[i][j] > 0x7D) {
							warn(_("Warning: Invalid comment fieldname in "
							       "comment %d (stream %d): \"%s\"\n"),
							     i, stream->num, inf->vc.user_comments[i]);
							broken = 1;
							break;
						}
					}

					if (broken)
						continue;

					val = (unsigned char *)inf->vc.user_comments[i];

					j = sep - inf->vc.user_comments[i] + 1;
					while (j < inf->vc.comment_lengths[i]) {
						remaining = inf->vc.comment_lengths[i] - j;
						if ((val[j] & 0x80) == 0)
							bytes = 1;
						else if ((val[j] & 0x40) == 0x40) {
							if ((val[j] & 0x20) == 0)
								bytes = 2;
							else if ((val[j] & 0x10) == 0)
								bytes = 3;
							else if ((val[j] & 0x08) == 0)
								bytes = 4;
							else if ((val[j] & 0x04) == 0)
								bytes = 5;
							else if ((val[j] & 0x02) == 0)
								bytes = 6;
							else {
								warn(_("Warning: Illegal UTF-8 sequence in "
								       "comment %d (stream %d): length "
								       "marker wrong\n"), i, stream->num);
								broken = 1;
								break;
							}
						} else {
							warn(_("Warning: Illegal UTF-8 sequence in comment "
							       "%d (stream %d): length marker wrong\n"),
							     i, stream->num);
							broken = 1;
							break;
						}

						if (bytes > remaining) {
							warn(_("Warning: Illegal UTF-8 sequence in comment "
							       "%d (stream %d): too few bytes\n"), i, stream->num);
							broken = 1;
							break;
						}

						switch (bytes) {
						case 1:
							/* No more checks needed */
							break;
						case 2:
							if ((val[j + 1] & 0xC0) != 0x80)
								broken = 1;
							if ((val[j] & 0xFE) == 0xC0)
								broken = 1;
							break;
						case 3:
							if (!((val[j] == 0xE0 && val[j + 1] >= 0xA0 &&
							       val[j + 1] <= 0xBF &&
							       (val[j + 2] & 0xC0) == 0x80) ||
							      (val[j] >= 0xE1 && val[j] <= 0xEC &&
							       (val[j + 1] & 0xC0) == 0x80 &&
							       (val[j + 2] & 0xC0) == 0x80) ||
							      (val[j] == 0xED && val[j + 1] >= 0x80 &&
							       val[j + 1] <= 0x9F &&
							       (val[j + 2] & 0xC0) == 0x80) ||
							      (val[j] >= 0xEE && val[j] <= 0xEF &&
							       (val[j + 1] & 0xC0) == 0x80 &&
							       (val[j + 2] & 0xC0) == 0x80)))
								broken = 1;
							if (val[j] == 0xE0 && (val[j + 1] & 0xE0) == 0x80)
								broken = 1;
							break;
						case 4:
							if (!((val[j] == 0xF0 && val[j + 1] >= 0x90 &&
							       val[j + 1] <= 0xBF &&
							       (val[j + 2] & 0xC0) == 0x80 &&
							       (val[j + 3] & 0xC0) == 0x80) ||
							      (val[j] >= 0xF1 && val[j] <= 0xF3 &&
							       (val[j + 1] & 0xC0) == 0x80 &&
							       (val[j + 2] & 0xC0) == 0x80 &&
							       (val[j + 3] & 0xC0) == 0x80) ||
							      (val[j] == 0xF4 && val[j + 1] >= 0x80 &&
							       val[j + 1] <= 0x8F &&
							       (val[j + 2] & 0xC0) == 0x80 &&
							       (val[j + 3] & 0xC0) == 0x80)))
								broken = 1;
							if (val[j] == 0xF0 && (val[j + 1] & 0xF0) == 0x80)
								broken = 1;
							break;
							/* 5 and 6 aren't actually allowed at this point */
						case 5:
							broken = 1;
							break;
						case 6:
							broken = 1;
							break;
						}

						if (broken) {
							warn(_("Warning: Illegal UTF-8 sequence in comment "
							       "%d (stream %d): invalid sequence\n"), i, stream->num);
							broken = 1;
							break;
						}

						j += bytes;
					}

					if (!broken) {
						if (utf8_decode(sep + 1, &decoded) < 0) {
							warn(_("Warning: Failure in utf8 decoder. This "
							       "should be impossible\n"));
							continue;
						}
						*sep = 0;
						debug_printf("\t%s=%s\n", inf->vc.user_comments[i], decoded);

						/* GCS FIX: Need case insensitive compare */
						if (!strcmp(inf->vc.user_comments[i], "artist")
						    || !strcmp(inf->vc.user_comments[i], "ARTIST")
						    || !strcmp(inf->vc.user_comments[i], "Artist")) {
							/* GCS FIX: This is a bit funky, maybe I need 
							   to get rid of the ogg built-in utf8 decoder */
							gstring_from_string(rmi, ti->artist,
									    MAX_TRACK_LEN, decoded, CODESET_LOCALE);
						} else if (!strcmp(inf->vc.user_comments[i], "title")
							   || !strcmp(inf->vc.user_comments[i], "TITLE")
							   || !strcmp(inf->vc.user_comments[i], "Title")) {
							/* GCS FIX: This is a bit funky, maybe I need 
							   to get rid of the ogg built-in utf8 decoder */
							gstring_from_string(rmi, ti->title, MAX_TRACK_LEN,
									    decoded, CODESET_LOCALE);
							ti->have_track_info = 1;
						} else if (!strcmp(inf->vc.user_comments[i], "album")
							   || !strcmp(inf->vc.user_comments[i], "ALBUM")
							   || !strcmp(inf->vc.user_comments[i], "Album")) {
							/* GCS FIX: This is a bit funky, maybe I need 
							   to get rid of the ogg built-in utf8 decoder */
							gstring_from_string(rmi, ti->album, MAX_TRACK_LEN,
									    decoded, CODESET_LOCALE);
						} else if (!strcmp(inf->vc.user_comments[i], "tracknumber")
							   || !strcmp(inf->vc.user_comments[i], "TRACKNUMBER")
							   || !strcmp(inf->vc.user_comments[i], "Tracknumber")) {
							/* GCS FIX: This is a bit funky, maybe I need 
							   to get rid of the ogg built-in utf8 decoder */
							gstring_from_string(rmi, ti->track_p,
									    MAX_TRACK_LEN, decoded, CODESET_LOCALE);
						}
						free(decoded);
					}
				}
				/* Done looping through vorbis comments.  If we didn't find 
				   a title, give a default title. */
				if (!ti->have_track_info) {
					strncpy(ti->title, "Title Unknown", MAX_TRACK_LEN);
					ti->have_track_info = 1;
				}
			}
		}
	}

	if (!header) {
		ogg_int64_t gp = ogg_page_granulepos(page);
		if (gp > 0) {
			if (gp < inf->lastgranulepos)
#ifdef _WIN32
				warn(_("Warning: granulepos in stream %d decreases from %I64d to %I64d"),
				     stream->num, inf->lastgranulepos, gp);
#else
				warn(_("Warning: granulepos in stream %d decreases from %lld to %lld"),
				     stream->num, inf->lastgranulepos, gp);
#endif
			inf->lastgranulepos = gp;
		} else {
			warn(_
			     ("Negative granulepos on vorbis stream outside of headers. This file was created by a buggy encoder\n"));
		}
		if (inf->firstgranulepos < 0) {	/* Not set yet */
		}
		inf->bytes += page->header_len + page->body_len;
	}
	return header;
}