Esempio n. 1
0
File: ffvorbis.c Progetto: stsaz/FF
int ffvorbis_decode(ffvorbis *v, const char *pkt, size_t len)
{
	enum { R_HDR, R_TAGS, R_TAG, R_BOOK, R_DATA };
	int r;

	if (len == 0)
		return FFVORBIS_RMORE;

	ogg_packet opkt;
	ffmem_tzero(&opkt);
	opkt.packet = (void*)pkt,  opkt.bytes = len;
	opkt.packetno = v->pktno++;
	opkt.granulepos = -1;
	opkt.e_o_s = v->fin;

	switch (v->state) {
	case R_HDR:
		if (0 != vorb_info(pkt, len, &v->info.channels, &v->info.rate, &v->info.bitrate_nominal))
			return ERR(v, FFVORBIS_EPKT);

		if (0 != (r = vorbis_decode_init(&v->vctx, &opkt)))
			return ERR(v, r);
		v->state = R_TAGS;
		return FFVORBIS_RHDR;

	case R_TAGS:
		if (NULL == (v->vtag.data = vorb_comm(pkt, len, &v->vtag.datalen)))
			return ERR(v, FFVORBIS_ETAG);
		v->state = R_TAG;
		// break

	case R_TAG:
		r = ffvorbtag_parse(&v->vtag);
		if (r == FFVORBTAG_ERR)
			return ERR(v, FFVORBIS_ETAG);
		else if (r == FFVORBTAG_DONE) {
			if (!(v->vtag.datalen != 0 && v->vtag.data[0] == 1))
				return ERR(v, FFVORBIS_ETAG);
			v->state = R_BOOK;
			return FFVORBIS_RHDRFIN;
		}
		return FFVORBIS_RTAG;

	case R_BOOK:
		if (0 != (r = vorbis_decode_init(&v->vctx, &opkt)))
			return ERR(v, r);
		v->state = R_DATA;
		return FFVORBIS_RMORE;
	}

	r = vorbis_decode(v->vctx, &opkt, &v->pcm);
	if (r < 0)
		return v->err = r,  FFVORBIS_RWARN;
	else if (r == 0)
		return FFVORBIS_RMORE;

	if (v->seek_sample != (uint64)-1) {
		if (v->seek_sample < v->cursample) {
			//couldn't find the target packet within the page
			v->seek_sample = v->cursample;
		}

		uint skip = ffmin(v->seek_sample - v->cursample, r);
		v->cursample += skip;
		if (v->cursample != v->seek_sample || (uint)r == skip)
			return FFVORBIS_RMORE; //not yet reached the target packet

		v->seek_sample = (uint64)-1;
		for (uint i = 0;  i != v->info.channels;  i++) {
			v->pcm_arr[i] = v->pcm[i] + skip;
		}
		v->pcm = v->pcm_arr;
		r -= skip;
	}

	if (v->total_samples != (uint64)-1)
		r = ffmin(r, v->total_samples - v->cursample);
	v->pkt_samples = r;
	v->pcmlen = r * sizeof(float) * v->info.channels;
	v->cursample += r;
	return FFVORBIS_RDATA;
}
Esempio n. 2
0
int main(int argc,char *argv[]){
  int c,long_option_index;
  int eof=0;
  int vorbiscount=0;

  /* get options */
  while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){
    switch(c){
    case 'c':
      codebook_p=1;
      break;
    case 'g':
      pageinfo_p=1;
      break;
    case 'h':
      usage(stdout);
      exit(0);
    case 'H':
      headerinfo_p=1;
      break;
    case 'p':
      packetinfo_p=1;
      break;
    case 's':
      streaminfo_p=1;
      break;
    case 't':
      truncpacket_p=1;
      break;
    case 'v':
      codebook_p=1;
      pageinfo_p=1;
      headerinfo_p=1;
      packetinfo_p=1;
      streaminfo_p=1;
      truncpacket_p=1;
      warn_p=1;
      break;
    case 'w':
      warn_p=1;
      break;
    default:
      usage(stderr);
      exit(1);
    }
  }

  /* set up sync */
  
  oy=ogg2_sync_create(); 
  os=ogg2_stream_create(0);


  while(!eof){
    long ret;
    long garbagecounter=0;
    long pagecounter=0;
    long packetcounter=0;
    int initialphase=0;

    memset(&vi,0,sizeof(vi));

    /* packet parsing loop */
    while(1){
      
      /* is there a packet available? */
      if(ogg2_stream_packetout(os,&op)>0){
	/* yes, process it */

	if(packetcounter<3){
	  /* header packet */
	  ret=vorbis_info_headerin(&vi,&op);
	  if(ret){
	    switch(packetcounter){
	    case 0: /* initial header packet */
	      if((streaminfo_p || warn_p || headerinfo_p) && syncp)
		printf("WARN stream: page did not contain a valid Vorbis I "
		       "identification\n"
		       "             header. Stream is not decodable as "
		       "Vorbis I.\n\n");
	      break;
	    case 1:
	      if((streaminfo_p || warn_p || headerinfo_p) && syncp)
		printf("WARN stream: next packet is not a valid Vorbis I "
		       "comment header as expected.\n"
		       "             Stream is not decodable as "
		       "Vorbis I.\n\n");
	      break;
	    case 2:
	      if((streaminfo_p || warn_p || headerinfo_p) && syncp)
		printf("WARN stream: next packet is not a valid Vorbis I "
		       "setup header as expected.\n"
		       "             Stream is not decodable as "
		       "Vorbis I.\n\n");
	      
	      break;
	    }
	    syncp=0;
	  }else{
	    syncp=1;
	    packetcounter++;
	    if(packetcounter==3){
	      if(streaminfo_p || headerinfo_p)
		printf("info stream: Vorbis I header triad parsed successfully.\n\n");
	      vorbiscount++;
	    }
	  }
	}else{
	  /* audio packet */

	  vorbis_decode(&vi,&op);
	  packetcounter++;
	}
	continue;
      }

      /* is there a page available? */
	  
      ret=ogg2_sync_pageseek(oy,&og);
      if(ret<0){
	garbagecounter-=ret;
      }
      if(ret>0){
	/* Garbage between pages? */
	if(garbagecounter){
	  if(streaminfo_p || warn_p || pageinfo_p)
	    fprintf(stdout,"WARN stream: %ld bytes of garbage before page %ld\n\n",
		    garbagecounter,pagecounter);
	  garbagecounter=0;
	}

	if(initialphase && !ogg2_page_bos(&og)){
	  /* initial header pages phase has ended */
	  if(streaminfo_p || headerinfo_p){
	    printf("info stream: All identification header pages parsed.\n"
		   "             %d logical stream%s muxed in this link.\n\n",
		   initialphase,(initialphase==1?"":"s"));
	    if(initialphase>1 && (warn_p || streaminfo_p))
	      printf("WARN stream: A 'Vorbis I audio stream' must contain uninterleaved\n"
		     "             Vorbis I logical streams only.  This is a legal\n"
		     "             multimedia Ogg stream, but not a Vorbis I audio\n"
		     "             stream.\n\n");
	  }
	  initialphase=0;
	}

	if(pageinfo_p)dump_page(&og);


	/* is this a stream transition? */
	if(ogg2_page_bos(&og) || pagecounter==0){
	  if(initialphase){
	    /* we're in a muxed stream, which is illegal for Vorbis I
               audio-only, but perfectly legal for Ogg. */
	    if(!syncp){
	      /* we've not yet seen the Vorbis header go past; keep trying new streams */
	      ogg2_stream_reset_serialno(os,ogg2_page_serialno(&og));
	    }
	  }else{
	    /* first new packet, signals new stream link.  Dump the current vorbis stream, if any */
	    ogg2_stream_reset_serialno(os,ogg2_page_serialno(&og));
	    memset(&vi,0,sizeof(vi));
	    packetcounter=0;
	    vorbis_info_clear(&vi);
	  }
	  initialphase++;

	  /* got an initial page.  Is it beginning of stream? */
	  if(!ogg2_page_bos(&og) && pagecounter==0 && streaminfo_p)
	    if(warn_p || streaminfo_p)
	      fprintf(stdout,"WARN stream: first page (0) is not marked beginning of stream.\n\n");
	}	
	
	ogg2_stream_pagein(os,&og);
	pagecounter++;
	continue;
      }
    
      if(get_data()<=0){
	eof=1;
	break;
      }
    }
  }

  if(streaminfo_p)
    fprintf(stdout, "\nHit physical end of stream at %ld bytes.\n",
	    ftell(stdin));

  if(vorbiscount==0)
    fprintf(stdout,"No logical Vorbis streams found in data.\n");
  else
    fprintf(stdout,"%d logical Vorbis stream%s found in data.\n",
	    vorbiscount,(vorbiscount==1?"":"s"));
  
  fprintf(stdout,"Done.\n");
  
  ogg2_page_release(&og);
  ogg2_stream_destroy(os);
  ogg2_sync_destroy(oy);
  
  return 0;
}