Exemple #1
0
/* Opens the Ogg stream, searching for and initializing Theora and Vorbis media
 */
int alogg_open(APEG_LAYER *layer)
{
	ALOGG_INFO *info;
	int vok = 0, aok = 0;
	int flag, cs, size;

	info = calloc(1, sizeof(ALOGG_INFO));
	if(!info)
		return APEG_ERROR;
	LOCK_DATA(info, sizeof(ALOGG_INFO));

	ogg_sync_init(&info->osync);

	theora_comment_init(&info->tcomment);
	theora_info_init(&info->tinfo);

	vorbis_info_init(&info->vinfo);
	vorbis_comment_init(&info->vcomment);

	flag = FALSE;
	while(!flag)
	{
		int ret = buffer_data(layer, info);
		if(ret == 0)
			break;

		while(ogg_sync_pageout(&info->osync, &info->opage) > 0)
		{
			ogg_stream_state test;

			/* is this a mandated initial header? If not, stop parsing */
			if(!ogg_page_bos(&info->opage))
			{
				if(vok > 0)
					ogg_stream_pagein(&info->ostream[0], &info->opage);
				if(aok > 0)
					ogg_stream_pagein(&info->ostream[1], &info->opage);
				flag = TRUE;
				break;
			}

			ogg_stream_init(&test, ogg_page_serialno(&info->opage));
			ogg_stream_pagein(&test, &info->opage);
			ogg_stream_packetout(&test, &info->opkt);

			/* identify the codec: try theora */
			if(!vok && theora_decode_header(&info->tinfo, &info->tcomment,
			                                &info->opkt) >= 0)
			{
				/* it is theora */
				if(!_apeg_ignore_video)
				{
					memcpy(&info->ostream[0], &test, sizeof(test));
					vok = 1;
				}
				else
					ogg_stream_clear(&test);
			}
			else if(!aok && vorbis_synthesis_headerin(&info->vinfo,
			                                &info->vcomment, &info->opkt) >= 0)
			{
				/* it is vorbis */
				if(!_apeg_ignore_audio)
				{
					memcpy(&info->ostream[1], &test, sizeof(test));
					aok = 1;
				}
				else
					ogg_stream_clear(&test);
			}
			/* whatever it is, we don't care about it */
			else
				ogg_stream_clear(&test);
		}
		/* fall through to non-bos page parsing */
	}

	/* look for further theora headers */
	while((vok > 0 && vok < 3) || (aok > 0 && aok < 3))
	{
		int ret;
		// Get the last two of three Theora headers
		while(vok > 0 && vok < 3 &&
		      (ret = ogg_stream_packetout(&info->ostream[0], &info->opkt)))
		{
			if(ret < 0)
				goto error;

			if(theora_decode_header(&info->tinfo, &info->tcomment, &info->opkt))
				goto error;

			++vok;
		}

		// Get the last two of three Vorbis headers
		while(aok > 0 && aok < 3 &&
		      (ret = ogg_stream_packetout(&info->ostream[1], &info->opkt)))
		{
			if(ret < 0)
				goto error;

			if(vorbis_synthesis_headerin(&info->vinfo, &info->vcomment,
			                             &info->opkt))
				goto error;

			++aok;
		}

		if(ogg_sync_pageout(&info->osync, &info->opage) <= 0)
		{
			/* need more data */
			if(buffer_data(layer, info) == 0)
				break;
		}
		else
		{
			if(vok > 0)
				ogg_stream_pagein(&info->ostream[0], &info->opage);
			if(aok > 0)
				ogg_stream_pagein(&info->ostream[1], &info->opage);
		}
    }

	// Neither Vorbis or Theora fully initialized. Error.
	if(vok != 3 && aok != 3)
		goto error;

	layer->ogg_info = info;

	if(aok == 3)
	{
		vorbis_synthesis_init(&info->vdsp, &info->vinfo);
		vorbis_block_init(&info->vdsp, &info->vblock);

		if(info->vinfo.channels == 1)
			layer->stream.audio.down_channel = FALSE;

		layer->stream.audio.channels = info->vinfo.channels;
		layer->stream.audio.freq = info->vinfo.rate >>
		                           layer->stream.audio.down_sample;

		if(_apeg_audio_reset_parameters(layer) != APEG_OK)
		{
			vorbis_block_clear(&info->vblock);
			vorbis_dsp_clear(&info->vdsp);
			goto error;
		}

//		layer->audio.inited = TRUE;
		layer->stream.flags |= APEG_VORBIS_AUDIO;
	}
Exemple #2
0
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;
}
Exemple #3
0
static int play_vorbis(lua_State *lstate) {
	char buf[BLOCKSIZE];
	char *pt, *oggbuf, **comm, *mark;
	int n, sock, sr_err, port;
	const char *host, *mount;
	VORBIS_FEED *feed;
	lua_pushstring(lstate, "host");
	lua_gettable(lstate, -2);
	lua_pushstring(lstate, "port");
	lua_gettable(lstate, -3);
	lua_pushstring(lstate, "mount");
	lua_gettable(lstate, -4);
	mount = lua_tostring(lstate, -1);
	port = lua_tointeger(lstate, -2);
	host = lua_tostring(lstate, -3);
	sock = stream_connect(host, port, mount, buf, &mark);
	lua_pop(lstate, 3);
	if (sock == 0) {
		lua_pop(lstate, 1);
		return 0;
		}
	lua_pushstring(lstate, "intern");
	lua_gettable(lstate, -2);
	feed = (VORBIS_FEED *)lua_touserdata(lstate, -1);
	lua_pop(lstate, 1);
	feed->base.sock = sock;
	pthread_mutex_init(&(feed->base.thread_lock), NULL);
	pthread_cond_init(&(feed->base.data_ready), NULL);
	ogg_sync_init(&(feed->oy));
	oggbuf = ogg_sync_buffer(&(feed->oy), BLOCKSIZE);
	n = BLOCKSIZE - (mark - buf);
	memcpy(oggbuf, mark, n);
	read_sock(feed->base.sock, oggbuf + n, BLOCKSIZE - n);
	ogg_sync_wrote(&(feed->oy), BLOCKSIZE);
	if ((n = ogg_sync_pageout(&(feed->oy), &(feed->og))) != 1) {
		logmsg("out of data: %d\n", n);
		free_vorbis((FEED *)feed);
		lua_pop(lstate, 1);
		return 0;
		}
	ogg_stream_init(&(feed->os), ogg_page_serialno(&(feed->og)));
	vorbis_info_init(&(feed->vi));
	vorbis_comment_init(&(feed->vc));
	if (ogg_stream_pagein(&(feed->os), &(feed->og)) < 1) {
		logmsg("error reading first ogg page\n");
		//free_feed(feed);
		//return 0;
		}
	if (ogg_stream_packetout(&(feed->os), &(feed->op)) != 1) {
		logmsg("error reading first header packet\n");
		free_vorbis((FEED *)feed);
		lua_pop(lstate, 1);
		return 0;
		}
	if (vorbis_synthesis_headerin(&(feed->vi),
			&(feed->vc), &(feed->op)) < 0) {
		logmsg("stream is not vorbis\n");
		free_vorbis((FEED *)feed);
		lua_pop(lstate, 1);
		return 0;
		}
	vorbis_headers(feed);
	add_table(lstate, "info");
	add_table(lstate, "comments");
	comm = feed->vc.user_comments;
	while (*comm) {
		if ((pt = index(*comm, '=')) != NULL) {
			*pt++ = '\0';
			set_string(lstate, *comm, pt);
			}
		++comm;
		}
	lua_pop(lstate, 1); // comments
	feed->base.channels = feed->vi.channels;
	set_integer(lstate, "channels", feed->base.channels);
	set_integer(lstate, "srate", feed->vi.rate);
	lua_pop(lstate, 1); // info
	feed->base.cbuf = new_ringbuf(feed->vi.rate, feed->base.channels,
			BUFSECS, 0.333, 0.667);
	if (jack_sr != feed->vi.rate) {
		feed->base.converter = src_new(SRC_SINC_MEDIUM_QUALITY,
				feed->base.channels, &sr_err);
		feed->base.src_data_in = (float *)malloc(SRC_DATA_FRAMES *
				feed->base.channels * sizeof(float));
		feed->base.src_data.data_in = feed->base.src_data_in;
		feed->base.src_data_remain = 0;
		feed->base.src_data.src_ratio = jack_sr
					/ (double)feed->vi.rate;
		feed->base.src_data_out = (float *)malloc(
				(int)ceil(SRC_DATA_FRAMES *
				feed->base.channels * sizeof(float) *
				feed->base.src_data.src_ratio));
		}
	feed->base.init = 1;
	lua_pop(lstate, 1);
	pthread_create(&(feed->base.thread_id), NULL, vorbis_thread, feed);
	return 0;
	}
/* handle incoming page. as the stream is being rebuilt, we need to
 * add all pages from the stream before processing packets
 */
static refbuf_t *process_vorbis_page (ogg_state_t *ogg_info,
                                      ogg_codec_t *codec, ogg_page *page)
{
    ogg_packet header;
    vorbis_codec_t *source_vorbis = codec->specific;
    char *comment;

    if (ogg_stream_pagein (&codec->os, page) < 0)
    {
        ogg_info->error = 1;
        return NULL;
    }
    if (codec->headers == 3)
    {
        if (source_vorbis->initial_audio_page)
        {
            source_vorbis->initial_page_granulepos = ogg_page_granulepos (page);
            source_vorbis->initial_audio_page = 0;
        }
        return NULL;
    }

    while (codec->headers < 3)
    {
        /* now, lets extract the packets */
        DEBUG1 ("processing incoming header packet (%d)", codec->headers);

        if (ogg_stream_packetout (&codec->os, &header) <= 0)
        {
            if (ogg_info->codecs->next)
                format_ogg_attach_header (codec, page);
            return NULL;
        }

        /* change comments here if need be */
        if (vorbis_synthesis_headerin (&source_vorbis->vi, &source_vorbis->vc, &header) < 0)
        {
            ogg_info->error = 1;
            WARN0 ("Problem parsing ogg vorbis header");
            return NULL;
        }
        header.granulepos = 0;
        source_vorbis->header [codec->headers] = copy_ogg_packet (&header);
        codec->headers++;
    }
    DEBUG0 ("we have the header packets now");

    /* if vorbis is the only codec then allow rebuilding of the streams */
    if (ogg_info->codecs->next == NULL && ogg_info->passthrough == 0)
    {
        /* set queued vorbis pages to contain about 1/2 second worth of samples */
        source_vorbis->page_samples_trigger = (ogg_int64_t)(source_vorbis->vi.rate/2);
        if (ogg_info->admin_comments_only)
            source_vorbis->rebuild_comment = 1;
        source_vorbis->process_packet = process_vorbis_headers;
        source_vorbis->initial_audio_page = 1;
    }
    else
    {
        format_ogg_attach_header (codec, &source_vorbis->bos_page);
        format_ogg_attach_header (codec, page);
        codec->process_page = process_vorbis_passthru_page;
    }

    if (ogg_info->admin_comments_only == 0)
    {
        free (ogg_info->title);
        comment = vorbis_comment_query (&source_vorbis->vc, "TITLE", 0);
        if (comment)
            ogg_info->title = strdup (comment);
        else
            ogg_info->title = NULL;

        free (ogg_info->artist);
        comment = vorbis_comment_query (&source_vorbis->vc, "ARTIST", 0);
        if (comment)
            ogg_info->artist = strdup (comment);
        else
            ogg_info->artist = NULL;
    }
    ogg_info->log_metadata = 1;

    stats_event_args (ogg_info->mount, "audio_samplerate", "%ld", (long)source_vorbis->vi.rate);
    stats_event_args (ogg_info->mount, "audio_channels", "%ld", (long)source_vorbis->vi.channels);
    stats_event_args (ogg_info->mount, "audio_bitrate", "%ld", (long)source_vorbis->vi.bitrate_nominal);
    stats_event_args (ogg_info->mount, "ice-bitrate", "%ld", (long)source_vorbis->vi.bitrate_nominal/1000);

    return NULL;
}
Exemple #5
0
static int ReadHeader(OGG_context *ctx, SYS_FILEHANDLE file)
{
	const size_t size = 4096;
	int theError;
	void *buffer;
	int i, serialNo;
	size_t bytes = 0;

	ogg_sync_init(&ctx->oy); /* Now we can read pages */
	/* submit a 4k block to libvorbis' Ogg layer */
	if (!ctx->eos)
	{
		buffer = ogg_sync_buffer(&ctx->oy, (int32_t)size);
		bytes = FIO_cur->fread(buffer, 1 , size, file);
		ogg_sync_wrote(&ctx->oy, (int32_t)size);
	}

	/* Get the first page. */
	theError = ogg_sync_pageout(&ctx->oy, &ctx->og);
	SYS_ASSERT(theError == 1);
	if (theError!=1)
	{
		/* error case.	Must not be Vorbis data */
		SYS_ASSERT(bytes<size);
		return 0;
	}

	/* Get the serial number and set up the rest of decode. */
	/* serialno first; use it to set up a logical stream */
	serialNo = ogg_page_serialno(&ctx->og);
	theError = ogg_stream_init(&ctx->os, serialNo);
	SYS_ASSERT(theError==0);

	/* extract the initial header from the first page and verify that the
	   Ogg bitstream is in fact Vorbis data */

	/* I handle the initial header first instead of just having the code
	   read all three Vorbis headers at once because reading the initial
	   header is an easy way to identify a Vorbis bitstream and it's
	   useful to see that functionality seperated out. */

	theError = ogg_stream_pagein(&ctx->os, &ctx->og);
	SYS_ASSERT(theError>=0);
	if (theError < 0)
	{
		/* error; stream version mismatch perhaps */
		return 0;
	}
	theError = ogg_stream_packetout(&ctx->os, &ctx->op);
	SYS_ASSERT(theError == 1);
	if (theError!=1)
	{
		/* no page? must not be vorbis */
		return 0;
	}
	theError = vorbis_synthesis_headerin(&ctx->vi, &ctx->vc, &ctx->op);
	SYS_ASSERT(theError >=0);
	if (theError < 0)
	{
		return 0;
	}
	/* At this point, we're sure we're Vorbis.	We've set up the logical
	   (Ogg) bitstream decoder.  Get the comment and codebook headers and
	   set up the Vorbis decoder */

	/* The next two packets in order are the comment and codebook headers.
	   They're likely large and may span multiple pages.  Thus we reead
	   and submit data until we get our two pacakets, watching that no
	   pages are missing.  If a page is missing, error out; losing a
	   header page is the only place where missing data is fatal. */

	i=0;
	while(i<2)
	{
		while(i<2)
		{
			int result = ogg_sync_pageout(&ctx->oy, &ctx->og);
			if (result==0)
				break; /* Need more data */
			/* Don't complain about missing or corrupt data yet.  We'll
			catch it at the packet output phase */
			if(result==1)
			{
				ogg_stream_pagein(&ctx->os, &ctx->og); /* we can ignore any errors here
				as they'll also become apparent
				at packetout */
				while(i<2)
				{
					result = ogg_stream_packetout(&ctx->os, &ctx->op);
					if (result==0)
						break;
					if (result<0)
					{
						/* Uh oh; data at some point was corrupted or missing!
						We can't tolerate that in a header.  Die. */
						SYS_ASSERT(0);
						return 0;
					}
					vorbis_synthesis_headerin(&ctx->vi, &ctx->vc, &ctx->op);
					i++;
				}
			}
		}
		buffer = ogg_sync_buffer(&ctx->oy, (int32_t)size);
		bytes  = FIO_cur->fread(buffer, 1 , size, file);
		SYS_ASSERT(!(bytes==0 && i<2));
		ogg_sync_wrote(&ctx->oy,(int32_t) size);
	}
	/* OK, got and parsed all three headers. Initialize the Vorbis
	 packet->PCM decoder. */
	vorbis_synthesis_init(&ctx->vd, &ctx->vi); /*	central decode state */
	vorbis_block_init(&ctx->vd, &ctx->vb);		/*	local state for most of the decode
													so multiple block decodes can
													proceed in parallel.  We could init
													multiple vorbis_block structures
													for vd here */

	ctx->input_size = size;
	ctx->state = 0;
	return 1;
}
bool SFB::Audio::OggSpeexDecoder::_Open(CFErrorRef *error)
{
	// Initialize Ogg data struct
	ogg_sync_init(&mOggSyncState);

	// Get the ogg buffer for writing
	char *data = ogg_sync_buffer(&mOggSyncState, READ_SIZE_BYTES);
	
	// Read bitstream from input file
	ssize_t bytesRead = (ssize_t)GetInputSource().Read(data, READ_SIZE_BYTES);
	if(-1 == bytesRead) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” could not be read."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Read error"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("Unable to read from the input file."), ""));
			
			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}
		
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	
	// Tell the sync layer how many bytes were written to its internal buffer
	int result = ogg_sync_wrote(&mOggSyncState, bytesRead);
	if(-1 == result) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
			
			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}
		
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	
	// Turn the data we wrote into an ogg page
	result = ogg_sync_pageout(&mOggSyncState, &mOggPage);
	if(1 != result) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
			
			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}
		
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	// Initialize the stream and grab the serial number
	ogg_stream_init(&mOggStreamState, ogg_page_serialno(&mOggPage));
	
	// Get the first Ogg page
	result = ogg_stream_pagein(&mOggStreamState, &mOggPage);
	if(0 != result) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
			
			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	
	// Get the first packet (should be the header) from the page
	ogg_packet op;
	result = ogg_stream_packetout(&mOggStreamState, &op);
	if(1 != result) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
			
			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}
		
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	if(op.bytes >= 5 && !memcmp(op.packet, "Speex", 5))
		mSpeexSerialNumber = mOggStreamState.serialno;

	++mOggPacketCount;
	
	// Convert the packet to the Speex header
	SpeexHeader *header = speex_packet_to_header((char *)op.packet, (int)op.bytes);
	if(nullptr == header) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg Speex file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an Ogg Speex file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));
			
			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::FileFormatNotRecognizedError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	else if(SPEEX_NB_MODES <= header->mode) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The Speex mode in the file “%@” is not supported."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Unsupported Ogg Speex file mode"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("This file may have been encoded with a newer version of Speex."), ""));
			
			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::FileFormatNotSupportedError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}
		
		speex_header_free(header), header = nullptr;
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	
	const SpeexMode *mode = speex_lib_get_mode(header->mode);
	if(mode->bitstream_version != header->mode_bitstream_version) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The Speex version in the file “%@” is not supported."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Unsupported Ogg Speex file version"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("This file was encoded with a different version of Speex."), ""));
			
			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::FileFormatNotSupportedError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}
		
		speex_header_free(header), header = nullptr;
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	
	// Initialize the decoder
	mSpeexDecoder = speex_decoder_init(mode);
	if(nullptr== mSpeexDecoder) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("Unable to initialize the Speex decoder."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Error initializing Speex decoder"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("An unknown error occurred."), ""));
			
			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}
		
		speex_header_free(header), header = nullptr;
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	
	speex_decoder_ctl(mSpeexDecoder, SPEEX_SET_SAMPLING_RATE, &header->rate);
	
	mSpeexFramesPerOggPacket = (0 == header->frames_per_packet ? 1 : header->frames_per_packet);
	mExtraSpeexHeaderCount = (UInt32)header->extra_headers;

	// Initialize the speex bit-packing data structure
	speex_bits_init(&mSpeexBits);
	
	// Initialize the stereo mode
	mSpeexStereoState = speex_stereo_state_init();
	
	if(2 == header->nb_channels) {
		SpeexCallback callback;
		callback.callback_id = SPEEX_INBAND_STEREO;
		callback.func = speex_std_stereo_request_handler;
		callback.data = mSpeexStereoState;
		speex_decoder_ctl(mSpeexDecoder, SPEEX_SET_HANDLER, &callback);
	}
	
	// Canonical Core Audio format
	mFormat.mFormatID			= kAudioFormatLinearPCM;
	mFormat.mFormatFlags		= kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;
	
	mFormat.mBitsPerChannel		= 8 * sizeof(float);
	mFormat.mSampleRate			= header->rate;
	mFormat.mChannelsPerFrame	= (UInt32)header->nb_channels;
	
	mFormat.mBytesPerPacket		= (mFormat.mBitsPerChannel / 8);
	mFormat.mFramesPerPacket	= 1;
	mFormat.mBytesPerFrame		= mFormat.mBytesPerPacket * mFormat.mFramesPerPacket;
	
	mFormat.mReserved			= 0;
	
	// Set up the source format
	mSourceFormat.mFormatID				= 'SPEE';
	
	mSourceFormat.mSampleRate			= header->rate;
	mSourceFormat.mChannelsPerFrame		= (UInt32)header->nb_channels;
	
	switch(header->nb_channels) {
		case 1:		mChannelLayout = ChannelLayout::ChannelLayoutWithTag(kAudioChannelLayoutTag_Mono);		break;
		case 2:		mChannelLayout = ChannelLayout::ChannelLayoutWithTag(kAudioChannelLayoutTag_Stereo);	break;
	}
	
	speex_header_free(header), header = nullptr;

	// Allocate the buffer list
	spx_int32_t speexFrameSize = 0;
	speex_decoder_ctl(mSpeexDecoder, SPEEX_GET_FRAME_SIZE, &speexFrameSize);
	
	if(!mBufferList.Allocate(mFormat, (UInt32)speexFrameSize)) {
		if(error)
			*error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, nullptr);

		speex_header_free(header), header = nullptr;
		speex_stereo_state_destroy(mSpeexStereoState), mSpeexStereoState = nullptr;
		speex_decoder_destroy(mSpeexDecoder), mSpeexDecoder = nullptr;
		speex_bits_destroy(&mSpeexBits);

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	
	for(UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i)
		mBufferList->mBuffers[i].mDataByteSize = 0;

	return true;
}
Exemple #7
0
static gboolean
xmms_speex_init (xmms_xform_t *xform)
{
	gint pe;

	xmms_config_property_t *val;
	xmms_speex_data_t *data;
	xmms_error_t error;

	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_speex_data_t, 1);
	g_return_val_if_fail (data, FALSE);

	xmms_xform_private_data_set (xform, data);

	ogg_sync_init (&data->sync_state);
	speex_bits_init (&data->speex_bits);

	/* Find the speex header */

	while (42) {
		gint ret;

		data->ogg_data = ogg_sync_buffer (&data->sync_state, 1024);
		ret = xmms_xform_read (xform, data->ogg_data, 1024, &error);
		ogg_sync_wrote (&data->sync_state, ret);

		if (ret <= 0) {
			return FALSE;
		}

		if (ogg_sync_pageout (&data->sync_state, &data->ogg_page) == 1) {
			break;
		}
	}

	ogg_stream_init (&data->stream_state, ogg_page_serialno (&data->ogg_page));

	if (ogg_stream_pagein (&data->stream_state, &data->ogg_page) < 0) {
		return FALSE;
	}

	if (ogg_stream_packetout (&data->stream_state, &data->ogg_packet) != 1) {
		return FALSE;
	}

	data->speexheader = speex_packet_to_header ((char *)data->ogg_packet.packet,
	                                            data->ogg_packet.bytes);
	data->speex_state = speex_decoder_init (speex_mode_list[data->speexheader->mode]);

	val = xmms_xform_config_lookup (xform, "perceptual_enhancer");
	pe = xmms_config_property_get_int (val);
	speex_decoder_ctl (data->speex_state, SPEEX_SET_ENH, &pe);

	ogg_sync_pageout (&data->sync_state, &data->ogg_page);
	ogg_stream_pagein (&data->stream_state, &data->ogg_page);
	ogg_stream_packetout (&data->stream_state, &data->ogg_packet);

	data->samples_buf = g_new (gint16,
	                           data->speexheader->frames_per_packet *
	                           data->speexheader->frame_size *
	                           data->speexheader->nb_channels);
	data->samples_start = data->samples_buf;
	data->samples_count = 0;

	xmms_speex_read_metadata (xform, data);

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "audio/pcm",
	                             XMMS_STREAM_TYPE_FMT_FORMAT,
	                             XMMS_SAMPLE_FORMAT_S16,
	                             XMMS_STREAM_TYPE_FMT_CHANNELS,
	                             data->speexheader->nb_channels,
	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
	                             data->speexheader->rate,
	                             XMMS_STREAM_TYPE_END);

	return TRUE;
}
/*!
 * \brief Create a new OGG/Vorbis filestream and set it up for reading.
 * \param fd Descriptor that points to on disk storage of the OGG/Vorbis data.
 * \return The new filestream.
 */
static struct cw_filestream *ogg_vorbis_open(FILE *fp)
{
    int i;
    int bytes;
    int result;
    char **ptr;
    char *buffer;

    struct cw_filestream *tmp;

    if ((tmp = malloc(sizeof(struct cw_filestream))))
    {
        memset(tmp, 0, sizeof(struct cw_filestream));

        tmp->writing = 0;
        tmp->fp = fp;

        ogg_sync_init(&tmp->oy);

        buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
        bytes = fread(buffer, 1, BLOCK_SIZE, tmp->fp);

        ogg_sync_wrote(&tmp->oy, bytes);

        result = ogg_sync_pageout(&tmp->oy, &tmp->og);
        if (result != 1)
        {
            if (bytes < BLOCK_SIZE)
                cw_log(LOG_ERROR, "Run out of data... %d %s\n", errno, strerror(errno));
            else
                cw_log(LOG_ERROR, "Input does not appear to be an Ogg bitstream.\n");
            fclose(fp);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        ogg_stream_init(&tmp->os, ogg_page_serialno(&tmp->og));
        vorbis_info_init(&tmp->vi);
        vorbis_comment_init(&tmp->vc);

        if (ogg_stream_pagein(&tmp->os, &tmp->og) < 0)
        {
            cw_log(LOG_ERROR, "Error reading first page of Ogg bitstream data.\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        if (ogg_stream_packetout(&tmp->os, &tmp->op) != 1)
        { 
            cw_log(LOG_ERROR, "Error reading initial header packet.\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        if (vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op) < 0)
        { 
            cw_log(LOG_ERROR, "This Ogg bitstream does not contain Vorbis audio data.\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        i = 0;
        while (i < 2)
        {
            while (i < 2)
            {
                result = ogg_sync_pageout(&tmp->oy, &tmp->og);
                if (result == 0)
                    break;
                if (result == 1)
                {
                    ogg_stream_pagein(&tmp->os, &tmp->og);
                    while (i < 2)
                    {
                        result = ogg_stream_packetout(&tmp->os,&tmp->op);
                        if (result == 0)
                            break;
                        if (result < 0)
                        {
                            cw_log(LOG_ERROR, "Corrupt secondary header.  Exiting.\n");
                            fclose(fp);
                            ogg_stream_clear(&tmp->os);
                            vorbis_comment_clear(&tmp->vc);
                            vorbis_info_clear(&tmp->vi);
                            ogg_sync_clear(&tmp->oy);
                            free(tmp);
                            return NULL;
                        }
                        vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op);
                        i++;
                    }
                }
            }

            buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
            bytes = fread(buffer, 1, BLOCK_SIZE, tmp->fp);
            if (bytes == 0  &&  i < 2)
            {
                cw_log(LOG_ERROR, "End of file before finding all Vorbis headers!\n");
                fclose(fp);
                ogg_stream_clear(&tmp->os);
                vorbis_comment_clear(&tmp->vc);
                vorbis_info_clear(&tmp->vi);
                ogg_sync_clear(&tmp->oy);
                free(tmp);
                return NULL;
            }
            ogg_sync_wrote(&tmp->oy, bytes);
        }
        
        ptr = tmp->vc.user_comments;
        while (*ptr)
        {
            cw_log(LOG_DEBUG, "OGG/Vorbis comment: %s\n", *ptr);
            ++ptr;
        }
        cw_log(LOG_DEBUG, "OGG/Vorbis bitstream is %d channel, %ldHz\n", tmp->vi.channels, tmp->vi.rate);
        cw_log(LOG_DEBUG, "OGG/Vorbis file encoded by: %s\n", tmp->vc.vendor);

        if (tmp->vi.channels != 1)
        {
            cw_log(LOG_ERROR, "Only monophonic OGG/Vorbis files are currently supported!\n");
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        

        if (tmp->vi.rate != 8000)
        {
            cw_log(LOG_ERROR, "Only 8000Hz OGG/Vorbis files are currently supported!\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_block_clear(&tmp->vb);
            vorbis_dsp_clear(&tmp->vd);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        vorbis_synthesis_init(&tmp->vd, &tmp->vi);
        vorbis_block_init(&tmp->vd, &tmp->vb);

        if (cw_mutex_lock(&ogg_vorbis_lock))
        {
            cw_log(LOG_WARNING, "Unable to lock ogg_vorbis list\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_block_clear(&tmp->vb);
            vorbis_dsp_clear(&tmp->vd);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        glistcnt++;
        cw_mutex_unlock(&ogg_vorbis_lock);
        cw_update_use_count();
    }
    return tmp;
}
Exemple #9
0
static int64_t find_first_page( demux_t *p_demux, int64_t i_pos1, int64_t i_pos2,
                                logical_stream_t *p_stream,
                                int64_t *pi_kframe, int64_t *pi_frame )
{
    int64_t i_result;
    int64_t i_granulepos;
    int64_t i_bytes_to_read = i_pos2 - i_pos1 + 1;
    int64_t i_bytes_read;
    int64_t i_pages_checked = 0;
    int64_t i_packets_checked;

    demux_sys_t *p_sys  = p_demux->p_sys;

    ogg_packet op;

    seek_byte( p_demux, i_pos1 );

    if ( i_pos1 == p_stream->i_data_start )
    {
        /* set a dummy granulepos at data_start */
        *pi_kframe = p_stream->i_keyframe_offset;
        *pi_frame = p_stream->i_keyframe_offset;

        p_sys->b_page_waiting = true;
        return p_sys->i_input_position;
    }

    if ( i_bytes_to_read > OGGSEEK_BYTES_TO_READ ) i_bytes_to_read = OGGSEEK_BYTES_TO_READ;

    while ( 1 )
    {

        if ( p_sys->i_input_position >= i_pos2 )
        {
            /* we reached the end and found no pages */
            *pi_frame=-1;
            return -1;
        }

        /* read next chunk */
        if ( ! ( i_bytes_read = get_data( p_demux, i_bytes_to_read ) ) )
        {
            /* EOF */
            *pi_frame = -1;
            return -1;
        }

        i_bytes_to_read = OGGSEEK_BYTES_TO_READ;

        i_result = ogg_sync_pageseek( &p_sys->oy, &p_sys->current_page );

        if ( i_result < 0 )
        {
            /* found a page, sync to page start */
            p_sys->i_input_position -= i_result;
            i_pos1 = p_sys->i_input_position;
            continue;
        }

        if ( i_result > 0 || ( i_result == 0 && p_sys->oy.fill > 3 &&
                               ! strncmp( (char *)p_sys->oy.data, "OggS" , 4 ) ) )
        {
            i_pos1 = p_sys->i_input_position;
            break;
        }

        p_sys->i_input_position += i_bytes_read;

    };

    seek_byte( p_demux, p_sys->i_input_position );
    ogg_stream_reset( &p_stream->os );

    while( 1 )
    {

        if ( p_sys->i_input_position >= i_pos2 )
        {
            /* reached the end of the search region and nothing was found */
            *pi_frame = -1;
            return p_sys->i_input_position;
        }

        p_sys->b_page_waiting = false;

        if ( ! ( i_result = oggseek_read_page( p_demux ) ) )
        {
            /* EOF */
            *pi_frame = -1;
            return p_sys->i_input_position;
        }

        // found a page
        if ( p_stream->os.serialno != ogg_page_serialno( &p_sys->current_page ) )
        {
            /* page is not for this stream */
            p_sys->i_input_position += i_result;
            if ( ! i_pages_checked ) i_pos1 = p_sys->i_input_position;
            continue;
        }


        ogg_stream_pagein( &p_stream->os, &p_sys->current_page );

        i_pages_checked++;
        i_packets_checked = 0;

        if ( ogg_stream_packetout( &p_stream->os, &op ) > 0 )
        {
            i_packets_checked++;
        }

        if ( i_packets_checked )
        {
            i_granulepos = ogg_page_granulepos( &p_sys->current_page );

            oggseek_theora_index_entry_add( p_stream, i_granulepos, i_pos1 );

            *pi_kframe =
                i_granulepos >> p_stream->i_granule_shift;

            *pi_frame = *pi_kframe +
                i_granulepos - ( *pi_kframe << p_stream->i_granule_shift );

            p_sys->b_page_waiting = true;
            return i_pos1;

        }

        /*  -> start of next page */
        p_sys->i_input_position += i_result;
    }
}
int AudioStreamPlaybackSpeex::mix(int16_t* p_buffer,int p_frames) {



	//printf("update, loops %i, read ofs %i\n", (int)loops, read_ofs);
	//printf("playing %i, paused %i\n", (int)playing, (int)paused);

	if (!active || !playing || paused || !data.size())
		return 0;

	/*
	if (read_ofs >= data.size()) {
		if (loops) {
			reload();
			++loop_count;
		} else {
			return;
		};
	};
	*/

	int todo = p_frames;
	if (todo < page_size) {
		return 0;
	};

	int eos = 0;	
	bool reloaded=false;

	while (todo > page_size) {

		int ret=0;
		while ((todo>page_size && packets_available && !eos) || (ret = ogg_sync_pageout(&oy, &og))==1) {

			if (!packets_available) {
			/*Add page to the bitstream*/
				ogg_stream_pagein(&os, &og);
				page_granule = ogg_page_granulepos(&og);
				page_nb_packets = ogg_page_packets(&og);
				packet_no=0;
				if (page_granule>0 && frame_size)
				{
					skip_samples = page_nb_packets*frame_size*nframes - (page_granule-last_granule);
					if (ogg_page_eos(&og))
						skip_samples = -skip_samples;
					/*else if (!ogg_page_bos(&og))
					skip_samples = 0;*/
				} else
				{
					skip_samples = 0;
				}


				last_granule = page_granule;
				packets_available=true;
			}
			/*Extract all available packets*/
			//int packet_no=0;
			while (todo > page_size && !eos) {

				if (ogg_stream_packetout(&os, &op)!=1) {
					packets_available=false;
					break;
				}

				packet_no++;


				/*End of stream condition*/
				if (op.e_o_s)
					eos=1;

				/*Copy Ogg packet to Speex bitstream*/
				speex_bits_read_from(&bits, (char*)op.packet, op.bytes);


				for (int j=0;j!=nframes;j++)
				{

					int16_t* out = p_buffer;

					int ret;
					/*Decode frame*/
					ret = speex_decode_int(st, &bits, out);

					/*for (i=0;i<frame_size*channels;i++)
					  printf ("%d\n", (int)output[i]);*/

					if (ret==-1) {
						printf("decode returned -1\n");
						break;
					};
					if (ret==-2)
					{
						OS::get_singleton()->printerr( "Decoding error: corrupted stream?\n");
						break;
					}
					if (speex_bits_remaining(&bits)<0)
					{
						OS::get_singleton()->printerr( "Decoding overflow: corrupted stream?\n");
						break;
					}
					//if (channels==2)
					//	speex_decode_stereo_int(output, frame_size, &stereo);


					/*Convert to short and save to output file*/
					for (int i=0;i<frame_size*stream_channels;i++) {
						out[i]=le_short(out[i]);
					}


					{

						int frame_offset = 0;
						int new_frame_size = frame_size;

						/*printf ("packet %d %d\n", packet_no, skip_samples);*/
						if (packet_no == 1 && j==0 && skip_samples > 0)
						{
							/*printf ("chopping first packet\n");*/
							new_frame_size -= skip_samples;
							frame_offset = skip_samples;
						}
						if (packet_no == page_nb_packets && skip_samples < 0)
						{
							int packet_length = nframes*frame_size+skip_samples;
							new_frame_size = packet_length - j*frame_size;
							if (new_frame_size<0)
								new_frame_size = 0;
							if (new_frame_size>frame_size)
								new_frame_size = frame_size;
							/*printf ("chopping end: %d %d %d\n", new_frame_size, packet_length, packet_no);*/
						}


						p_buffer+=new_frame_size*stream_channels;
						todo-=new_frame_size;
					}
				}

			};
		};
		//todo = get_todo();

		//todo is still greater than page size, can write more
		if (todo > page_size || eos) {
			if (read_ofs < data.size()) {

				//char *buf;
				int nb_read = MIN(data.size() - read_ofs, READ_CHUNK);

				/*Get the ogg buffer for writing*/
				char* ogg_dst = ogg_sync_buffer(&oy, nb_read);
				/*Read bitstream from input file*/
				copymem(ogg_dst, &data[read_ofs], nb_read);
				read_ofs += nb_read;
				ogg_sync_wrote(&oy, nb_read);
			} else {
				if (loops) {					
					reload();
					++loop_count;
					//break;
				} else {
					playing=false;
					unload();
					break;
				};
			}
		};
	};

	return p_frames-todo;
};
void AudioStreamPlaybackSpeex::reload() {



	if (active)
		unload();

	if (!data.size())
		return;

	ogg_sync_init(&oy);
	speex_bits_init(&bits);

	read_ofs = 0;
//	char *buf;

	int packet_count = 0;
	int extra_headers = 0;
	int stream_init = 0;

	page_granule=0;
	last_granule=0;
	skip_samples=0;
	page_nb_packets=0;
	packets_available=false;
	packet_no=0;

	int eos = 0;

	do {

		/*Get the ogg buffer for writing*/
		int nb_read = MIN(data.size() - read_ofs, READ_CHUNK);
		char* ogg_dst = ogg_sync_buffer(&oy, nb_read);
		/*Read bitstream from input file*/
		copymem(ogg_dst, &data[read_ofs], nb_read);
		read_ofs += nb_read;
		ogg_sync_wrote(&oy, nb_read);

		/*Loop for all complete pages we got (most likely only one)*/
		while (ogg_sync_pageout(&oy, &og)==1) {

			int packet_no;
			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);
			page_nb_packets = ogg_page_packets(&og);
			if (page_granule>0 && frame_size)
			{
				skip_samples = page_nb_packets*frame_size*nframes - (page_granule-last_granule);
				if (ogg_page_eos(&og))
					skip_samples = -skip_samples;
				/*else if (!ogg_page_bos(&og))
				  skip_samples = 0;*/
			} else
			{
				skip_samples = 0;
			}


			last_granule = page_granule;
			/*Extract all available packets*/
			packet_no=0;
			while (!eos && ogg_stream_packetout(&os, &op)==1)
			{
				/*If first packet, process as Speex header*/
				if (packet_count==0)
				{
					int rate = 0;
					int channels;
					st = process_header(&op, &frame_size, &rate, &nframes, &channels, &extra_headers);
					if (!nframes)
						nframes=1;
					if (!st) {
						unload();
						return;
					};

					page_size = nframes * frame_size;
					stream_srate=rate;
					stream_channels=channels;
					stream_minbuff_size=page_size;


				} else if (packet_count==1)
				{
				} else if (packet_count<=1+extra_headers)
				{
					/* Ignore extra headers */
				};
			};
			++packet_count;
		};

	} while (packet_count <= extra_headers);

	active=true;

}
Exemple #12
0
int OggDec::DecodeOGG(char *inmemory,int inmemsize,
                char *outmemory,int outmemsize,int *done)
{
	char	*buffer;
	int		i;

	*done = 0;
	if(leakSize){
		if(outmemsize >= leakSize){
			memcpy(outmemory,leak_mem,leakSize);
			*done = leakSize;
			free(leak_mem);
			leak_mem = NULL;
			leakSize = 0;
			allocMemSize = 0;
		}else{
			memcpy(outmemory,leak_mem,outmemsize);
			*done = outmemsize;
			memmove(leak_mem,leak_mem+outmemsize,leakSize-outmemsize);
			leakSize -= outmemsize;
		}
		if(inmemsize==0) return (OGG_DEC_CONTINUE);
	}
	if(0==decStep){
		eos = 0;
		buffer=ogg_sync_buffer(&oy,4096);
		memcpy(buffer,inmemory,inmemsize);
		ogg_sync_wrote(&oy,inmemsize);
		if(ogg_sync_pageout(&oy,&og)!=1){
			if(inmemsize<4096){
				Clear_ogg();
				return(OGG_DEC_END);
			}
			return(OGG_DEC_ERR);
		}
		ogg_stream_init(&os,ogg_page_serialno(&og));
		vorbis_info_init(&vi);
		vorbis_comment_init(&vc);
		if(ogg_stream_pagein(&os,&og)<0){ 
			return(OGG_DEC_ERR);
		}
		if(ogg_stream_packetout(&os,&op)!=1){ 
			return(OGG_DEC_ERR);
		}
		if(vorbis_synthesis_headerin(&vi,&vc,&op)<0){ 
			return(OGG_DEC_ERR);
		}
		wfmt.wFormatTag = WAVE_FORMAT_PCM;
		wfmt.nChannels = vi.channels;
		wfmt.wBitsPerSample = 16;
		wfmt.nSamplesPerSec = vi.rate;
		wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample/8);
		wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
		wfmt.cbSize = 0;
		bWaveGet = TRUE;
		decStep = 1;
		d1loop=0;
		return (OGG_DEC_CONTINUE);
	}
	if(1==decStep){
		while(d1loop<2){
			while(d1loop<2){
				int result=ogg_sync_pageout(&oy,&og);
				if(result==0)break;
				if(result==1){
					ogg_stream_pagein(&os,&og);
					while(d1loop<2){
						result=ogg_stream_packetout(&os,&op);
						if(result==0)break;
						if(result<0){
							return(OGG_DEC_ERR);
						}
						vorbis_synthesis_headerin(&vi,&vc,&op);
						d1loop++;
					}
				}
			}
			buffer=ogg_sync_buffer(&oy,4096);
			memcpy(buffer,inmemory,inmemsize);
			if(inmemsize==0 && d1loop<2){
				return(OGG_DEC_ERR);
			}
			ogg_sync_wrote(&oy,inmemsize);
			if(d1loop<2)
				return (OGG_DEC_CONTINUE);
		}
		decStep = 2;
		convsize=4096/vi.channels;
		vorbis_synthesis_init(&vd,&vi);
		vorbis_block_init(&vd,&vb);
		return (OGG_DEC_CONTINUE);
	}
	while(!eos){
	  while(!eos){
		int result=ogg_sync_pageout(&oy,&og);
		if(result==0)break;
		if(result<0){
		}else{
			ogg_stream_pagein(&os,&og);
			while(1){
				result=ogg_stream_packetout(&os,&op);
				if(result==0)break;
				if(result<0){
				}else{
					float **pcm;
					int samples;
		  
					if(vorbis_synthesis(&vb,&op)==0)
						vorbis_synthesis_blockin(&vd,&vb);
					while((samples=vorbis_synthesis_pcmout(&vd,&pcm))>0){
						int j;
						int clipflag=0;
						int bout=(samples<convsize?samples:convsize);
		
						for(i=0;i<vi.channels;i++){
							ogg_int16_t *ptr=convbuffer+i;
							float  *mono=pcm[i];
							for(j=0;j<bout;j++){
#if 1
								int val=int(mono[j]*32767.f);
#else
								int val=mono[j]*32767.f+drand48()-0.5f;
#endif
								if(val>32767){
								  val=32767;
								  clipflag=1;
								}
								if(val<-32768){
								  val=-32768;
								  clipflag=1;
								}
								*ptr=val;
								ptr+=(vi.channels);
							}
						}
						if(NULL==leak_mem){
							if(outmemsize >= (*done +2*vi.channels*bout)){
								memcpy(outmemory+(*done),convbuffer,2*vi.channels*bout);
								*done += 2*vi.channels*bout;
							}else{
								allocMemSize = 0x100000;
								leak_mem = (char *)malloc(allocMemSize);
							}
						}
						if(leak_mem){
							if(allocMemSize < (leakSize + 2*vi.channels*bout)){
								allocMemSize += 0x100000;
								realloc(leak_mem,allocMemSize);
							}
							memcpy(leak_mem+leakSize,convbuffer,2*vi.channels*bout);
							leakSize += 2*vi.channels*bout;
						}
						vorbis_synthesis_read(&vd,bout);
					}	    
				}
			}
			if(ogg_page_eos(&og))eos=1;
		}
	  }
	  if(!eos){
		buffer=ogg_sync_buffer(&oy,4096);
		memcpy(buffer,inmemory,inmemsize);
		ogg_sync_wrote(&oy,inmemsize);
		if(inmemsize==0) eos=1;
		return (OGG_DEC_CONTINUE);
	  }
	}
	if(bLoop){
		eos = 0;
		return OGG_DEC_REPLAY;
	}
	ogg_stream_clear(&os);
	vorbis_block_clear(&vb);
	vorbis_dsp_clear(&vd);
	vorbis_comment_clear(&vc);
	vorbis_info_clear(&vi);
	decStep = 0;

	return (OGG_DEC_CONTINUE);
}
Exemple #13
0
static int read_packet(struct ast_filestream *fs)
{
	struct speex_desc *s = (struct speex_desc *)fs->_private;
	char *buffer;
	int result;
	size_t bytes;

	while (1) {
		/* Get one packet */
		result = ogg_stream_packetout(&s->os, &s->op);
		if (result > 0) {
			if (s->op.bytes >= 5 && !memcmp(s->op.packet, "Speex", 5)) {
				s->serialno = s->os.serialno;
			}
			if (s->serialno == -1 || s->os.serialno != s->serialno) {
				continue;
			}
			return 0;
		}

		if (result < 0) {
			ast_log(LOG_WARNING,
				"Corrupt or missing data at this page position; continuing...\n");
		}

		/* No more packets left in the current page... */
		if (s->eos) {
			/* No more pages left in the stream */
			return -1;
		}

		while (!s->eos) {
			/* See if OGG has any pages in it's internal buffers */
			result = ogg_sync_pageout(&s->oy, &s->og);
			if (result > 0) {
				/* Read all streams. */
				if (ogg_page_serialno(&s->og) != s->os.serialno) {
					ogg_stream_reset_serialno(&s->os, ogg_page_serialno(&s->og));
				}
				/* Yes, OGG has more pages in it's internal buffers,
				   add the page to the stream state */
				result = ogg_stream_pagein(&s->os, &s->og);
				if (result == 0) {
					/* Yes, got a new, valid page */
					if (ogg_page_eos(&s->og) &&
					    ogg_page_serialno(&s->og) == s->serialno)
						s->eos = 1;
					break;
				}
				ast_log(LOG_WARNING,
					"Invalid page in the bitstream; continuing...\n");
			}

			if (result < 0) {
				ast_log(LOG_WARNING,
					"Corrupt or missing data in bitstream; continuing...\n");
			}

			/* No, we need to read more data from the file descrptor */
			/* get a buffer from OGG to read the data into */
			buffer = ogg_sync_buffer(&s->oy, BLOCK_SIZE);
			bytes = fread(buffer, 1, BLOCK_SIZE, fs->f);
			ogg_sync_wrote(&s->oy, bytes);
			if (bytes == 0) {
				s->eos = 1;
			}
		}
	}
}
Exemple #14
0
int main(void){

  ogg_stream_init(&os_en,0x04030201);
  ogg_stream_init(&os_de,0x04030201);
  ogg_sync_init(&oy);

  /* Exercise each code path in the framing code.  Also verify that
     the checksums are working.  */

  {
    /* 17 only */
    const int packets[]={17, -1};
    const int *headret[]={head1_0,NULL};
    
    fprintf(stderr,"testing single page encoding... ");
    test_pack(packets,headret,0,0,0);
  }

  {
    /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
    const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
    const int *headret[]={head1_1,head2_1,NULL};
    
    fprintf(stderr,"testing basic page encoding... ");
    test_pack(packets,headret,0,0,0);
  }

  {
    /* nil packets; beginning,middle,end */
    const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
    const int *headret[]={head1_2,head2_2,NULL};
    
    fprintf(stderr,"testing basic nil packets... ");
    test_pack(packets,headret,0,0,0);
  }

  {
    /* large initial packet */
    const int packets[]={4345,259,255,-1};
    const int *headret[]={head1_3,head2_3,NULL};
    
    fprintf(stderr,"testing initial-packet lacing > 4k... ");
    test_pack(packets,headret,0,0,0);
  }

  {
    /* continuing packet test */
    const int packets[]={0,4345,259,255,-1};
    const int *headret[]={head1_4,head2_4,head3_4,NULL};
    
    fprintf(stderr,"testing single packet page span... ");
    test_pack(packets,headret,0,0,0);
  }

  /* page with the 255 segment limit */
  {

    const int packets[]={0,10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,50,-1};
    const int *headret[]={head1_5,head2_5,head3_5,NULL};
    
    fprintf(stderr,"testing max packet segments... ");
    test_pack(packets,headret,0,0,0);
  }

  {
    /* packet that overspans over an entire page */
    const int packets[]={0,100,9000,259,255,-1};
    const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
    
    fprintf(stderr,"testing very large packets... ");
    test_pack(packets,headret,0,0,0);
  }

  {
    /* test for the libogg 1.1.1 resync in large continuation bug
       found by Josh Coalson)  */
    const int packets[]={0,100,9000,259,255,-1};
    const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
    
    fprintf(stderr,"testing continuation resync in very large packets... ");
    test_pack(packets,headret,100,2,3);
  }

  {
    /* term only page.  why not? */
    const int packets[]={0,100,4080,-1};
    const int *headret[]={head1_7,head2_7,head3_7,NULL};
    
    fprintf(stderr,"testing zero data page (1 nil packet)... ");
    test_pack(packets,headret,0,0,0);
  }



  {
    /* build a bunch of pages for testing */
    unsigned char *data=_ogg_malloc(1024*1024);
    int pl[]={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1};
    int inptr=0,i,j;
    ogg_page og[5];
    
    ogg_stream_reset(&os_en);

    for(i=0;pl[i]!=-1;i++){
      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=(i+1)*1000;

      for(j=0;j<len;j++)data[inptr++]=i+j;
      ogg_stream_packetin(&os_en,&op);
    }

    _ogg_free(data);

    /* retrieve finished pages */
    for(i=0;i<5;i++){
      if(ogg_stream_pageout(&os_en,&og[i])==0){
	fprintf(stderr,"Too few pages output building sync tests!\n");
	exit(1);
      }
      copy_page(&og[i]);
    }

    /* Test lost pages on pagein/packetout: no rollback */
    {
      ogg_page temp;
      ogg_packet test;

      fprintf(stderr,"Testing loss of pages... ");

      ogg_sync_reset(&oy);
      ogg_stream_reset(&os_de);
      for(i=0;i<5;i++){
	memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
	       og[i].header_len);
	ogg_sync_wrote(&oy,og[i].header_len);
	memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
	ogg_sync_wrote(&oy,og[i].body_len);
      }

      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);
      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);
      ogg_sync_pageout(&oy,&temp);
      /* skip */
      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);

      /* do we get the expected results/packets? */
      
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,0,0,0);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,100,1,-1);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,4079,2,3000);
      if(ogg_stream_packetout(&os_de,&test)!=-1){
	fprintf(stderr,"Error: loss of page did not return error\n");
	exit(1);
      }
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,76,5,-1);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,34,6,-1);
      fprintf(stderr,"ok.\n");
    }

    /* Test lost pages on pagein/packetout: rollback with continuation */
    {
      ogg_page temp;
      ogg_packet test;

      fprintf(stderr,"Testing loss of pages (rollback required)... ");

      ogg_sync_reset(&oy);
      ogg_stream_reset(&os_de);
      for(i=0;i<5;i++){
	memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
	       og[i].header_len);
	ogg_sync_wrote(&oy,og[i].header_len);
	memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
	ogg_sync_wrote(&oy,og[i].body_len);
      }

      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);
      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);
      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);
      ogg_sync_pageout(&oy,&temp);
      /* skip */
      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);

      /* do we get the expected results/packets? */
      
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,0,0,0);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,100,1,-1);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,4079,2,3000);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,2956,3,4000);
      if(ogg_stream_packetout(&os_de,&test)!=-1){
	fprintf(stderr,"Error: loss of page did not return error\n");
	exit(1);
      }
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,300,13,14000);
      fprintf(stderr,"ok.\n");
    }
    
    /* the rest only test sync */
    {
      ogg_page og_de;
      /* Test fractional page inputs: incomplete capture */
      fprintf(stderr,"Testing sync on partial inputs... ");
      ogg_sync_reset(&oy);
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
	     3);
      ogg_sync_wrote(&oy,3);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      
      /* Test fractional page inputs: incomplete fixed header */
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
	     20);
      ogg_sync_wrote(&oy,20);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      
      /* Test fractional page inputs: incomplete header */
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
	     5);
      ogg_sync_wrote(&oy,5);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      
      /* Test fractional page inputs: incomplete body */
      
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
	     og[1].header_len-28);
      ogg_sync_wrote(&oy,og[1].header_len-28);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
      ogg_sync_wrote(&oy,1000);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
	     og[1].body_len-1000);
      ogg_sync_wrote(&oy,og[1].body_len-1000);
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
      
      fprintf(stderr,"ok.\n");
    }

    /* Test fractional page inputs: page + incomplete capture */
    {
      ogg_page og_de;
      fprintf(stderr,"Testing sync on 1+partial inputs... ");
      ogg_sync_reset(&oy); 

      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
	     og[1].header_len);
      ogg_sync_wrote(&oy,og[1].header_len);

      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
	     og[1].body_len);
      ogg_sync_wrote(&oy,og[1].body_len);

      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
	     20);
      ogg_sync_wrote(&oy,20);
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
      if(ogg_sync_pageout(&oy,&og_de)>0)error();

      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
	     og[1].header_len-20);
      ogg_sync_wrote(&oy,og[1].header_len-20);
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
	     og[1].body_len);
      ogg_sync_wrote(&oy,og[1].body_len);
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();

      fprintf(stderr,"ok.\n");
    }
    
    /* Test recapture: garbage + page */
    {
      ogg_page og_de;
      fprintf(stderr,"Testing search for capture... ");
      ogg_sync_reset(&oy); 
      
      /* 'garbage' */
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
	     og[1].body_len);
      ogg_sync_wrote(&oy,og[1].body_len);

      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
	     og[1].header_len);
      ogg_sync_wrote(&oy,og[1].header_len);

      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
	     og[1].body_len);
      ogg_sync_wrote(&oy,og[1].body_len);

      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
	     20);
      ogg_sync_wrote(&oy,20);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
      if(ogg_sync_pageout(&oy,&og_de)>0)error();

      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
	     og[2].header_len-20);
      ogg_sync_wrote(&oy,og[2].header_len-20);
      memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
	     og[2].body_len);
      ogg_sync_wrote(&oy,og[2].body_len);
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();

      fprintf(stderr,"ok.\n");
    }

    /* Test recapture: page + garbage + page */
    {
      ogg_page og_de;
      fprintf(stderr,"Testing recapture... ");
      ogg_sync_reset(&oy); 

      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
	     og[1].header_len);
      ogg_sync_wrote(&oy,og[1].header_len);

      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
	     og[1].body_len);
      ogg_sync_wrote(&oy,og[1].body_len);

      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
	     og[2].header_len);
      ogg_sync_wrote(&oy,og[2].header_len);

      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
	     og[2].header_len);
      ogg_sync_wrote(&oy,og[2].header_len);

      if(ogg_sync_pageout(&oy,&og_de)<=0)error();

      memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
	     og[2].body_len-5);
      ogg_sync_wrote(&oy,og[2].body_len-5);

      memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
	     og[3].header_len);
      ogg_sync_wrote(&oy,og[3].header_len);

      memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
	     og[3].body_len);
      ogg_sync_wrote(&oy,og[3].body_len);

      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();

      fprintf(stderr,"ok.\n");
    }

    /* Free page data that was previously copied */
    {
      for(i=0;i<5;i++){
	free_page(&og[i]);
      }
    }
  }    

  return(0);
}
/** central buffer management function 
  * @param openmaxStandComp the component handle
  * @param inputbuffer contains the input ogg file content
  * @param outputbuffer is returned along with its output pcm file content that is produced as a result of this function execution
  */
void omx_vorbisdec_component_BufferMgmtCallbackVorbis(OMX_COMPONENTTYPE *openmaxStandComp, OMX_BUFFERHEADERTYPE* inputbuffer, OMX_BUFFERHEADERTYPE* outputbuffer) {

  omx_vorbisdec_component_PrivateType* omx_vorbisdec_component_Private = openmaxStandComp->pComponentPrivate;
  OMX_U8* outputCurrBuffer;
  OMX_U32 outputLength;
  OMX_S32 result;  
  float **pcm;
  OMX_S32 samples;
  OMX_S32 i, j;
  OMX_S32 bout;
  OMX_S32 clipflag=0;
  int val;
  float  *mono;
  int eos=0;
  char *vorbis_buffer;
  ogg_int16_t convbuffer[4096];

 
  DEBUG(DEB_LEV_FULL_SEQ, "input buf %x filled len : %d \n", (int)inputbuffer->pBuffer, (int)inputbuffer->nFilledLen);  
  /** Fill up the current input buffer when a new buffer has arrived */
  if(omx_vorbisdec_component_Private->isNewBuffer) {
    omx_vorbisdec_component_Private->inputCurrBuffer = inputbuffer->pBuffer;
    omx_vorbisdec_component_Private->inputCurrLength = inputbuffer->nFilledLen;
    omx_vorbisdec_component_Private->positionInOutBuf = 0;

    DEBUG(DEB_LEV_SIMPLE_SEQ, "new -- input buf %x filled len : %d \n", (int)inputbuffer->pBuffer, (int)inputbuffer->nFilledLen);  

    /** for each new input buffer --- copy buffer content into into ogg sync state structure data */
    vorbis_buffer = ogg_sync_buffer(&omx_vorbisdec_component_Private->oy, inputbuffer->nAllocLen);
    memcpy(vorbis_buffer, inputbuffer->pBuffer, inputbuffer->nFilledLen);
    ogg_sync_wrote(&omx_vorbisdec_component_Private->oy, inputbuffer->nFilledLen);
    DEBUG(DEB_LEV_FULL_SEQ,"***** bytes read to buffer (of first header): %d \n",(int)inputbuffer->nFilledLen);
  }
  outputCurrBuffer = outputbuffer->pBuffer;
  outputLength = outputbuffer->nAllocLen;
  outputbuffer->nFilledLen = 0;
  outputbuffer->nOffset = 0;
  
  if(omx_vorbisdec_component_Private->packetNumber < 3) {
    omx_vorbisdec_component_Private->isNewBuffer = 0;
    if(omx_vorbisdec_component_Private->packetNumber == 0) {
      DEBUG(DEB_LEV_SIMPLE_SEQ, "in processing the first header buffer\n");      
      if(ogg_sync_pageout(&omx_vorbisdec_component_Private->oy, &omx_vorbisdec_component_Private->og) != 1)  {
        DEBUG(DEB_LEV_ERR, "this input stream is not an Ogg stream\n");
        return;
      }  
      ogg_stream_init(&omx_vorbisdec_component_Private->os, ogg_page_serialno(&omx_vorbisdec_component_Private->og));    
      vorbis_info_init(&omx_vorbisdec_component_Private->vi);
      vorbis_comment_init(&omx_vorbisdec_component_Private->vc);

      if(ogg_stream_pagein(&omx_vorbisdec_component_Private->os, &omx_vorbisdec_component_Private->og) < 0)  {
        DEBUG(DEB_LEV_ERR, "Error reading first page of Ogg bitstream data.\n");
        return;
      }
      if(ogg_stream_packetout(&omx_vorbisdec_component_Private->os, &omx_vorbisdec_component_Private->op) != 1)  {
        DEBUG(DEB_LEV_ERR, "Error reading initial header packet.\n");
        return;
      }
      
      omx_vorbisdec_component_Private->packetNumber++;

      if(vorbis_synthesis_headerin(&omx_vorbisdec_component_Private->vi, &omx_vorbisdec_component_Private->vc, &omx_vorbisdec_component_Private->op) < 0)  {
        DEBUG(DEB_LEV_ERR, "This Ogg bitstream does not contain Vorbis audio data\n");
        return;
      }  
    }

    while(omx_vorbisdec_component_Private->packetNumber < 3)
    {
      int result=ogg_sync_pageout(&omx_vorbisdec_component_Private->oy,&omx_vorbisdec_component_Private->og);
      if(result==0) { //break; /* Need more data */
        omx_vorbisdec_component_Private->isNewBuffer = 1;
        inputbuffer->nFilledLen = 0;
        return;
      }
      /* Don't complain about missing or corrupt data yet.  We'll
      catch it at the packet output phase */
      if(result==1) 
      {
        ogg_stream_pagein(&omx_vorbisdec_component_Private->os,&omx_vorbisdec_component_Private->og);
        /* we can ignore any errors here as they'll also become apparent at packetout */
        while(omx_vorbisdec_component_Private->packetNumber < 3) {
          result=ogg_stream_packetout(&omx_vorbisdec_component_Private->os,&omx_vorbisdec_component_Private->op);
          if(result==0)break;
          if(result<0) {
          /* Uh oh; data at some point was corrupted or missing!
            We can't tolerate that in a header.  Die. */
            DEBUG(DEB_LEV_ERR,"Corrupt secondary header.  Exiting.\n");
            break;
          }//end if
          omx_vorbisdec_component_Private->packetNumber++;
          vorbis_synthesis_headerin(&omx_vorbisdec_component_Private->vi,&omx_vorbisdec_component_Private->vc,&omx_vorbisdec_component_Private->op);
        }//end while
      }//end if
    }//end while

    omx_vorbisdec_component_Private->isNewBuffer = 1;
    inputbuffer->nFilledLen = 0;
    return;

  }

  /* A Vorbis logical bitstream begins with 3 headers. Once the last of these has been processed,
   * we can report the metadata and set up the output audio port appropriately. */
  if(omx_vorbisdec_component_Private->packetNumber == 3) {
    /* Throw the comments plus a few lines about the bitstream we're decoding */
    {
      // ptr should be declared earlier//
      char **ptr=omx_vorbisdec_component_Private->vc.user_comments;
      while(*ptr){
        DEBUG(DEB_LEV_ERR,"%s\n",*ptr);
        ++ptr;
      }
      DEBUG(DEB_LEV_ERR,"Bitstream is %d channel, %ldHz\n",omx_vorbisdec_component_Private->vi.channels,omx_vorbisdec_component_Private->vi.rate);
      DEBUG(DEB_LEV_ERR,"Encoded by: %s\n\n",omx_vorbisdec_component_Private->vc.vendor);
    }

    /* Update pAudioVorbis settings */
    omx_vorbisdec_component_Private->pAudioVorbis.nSampleRate = omx_vorbisdec_component_Private->vi.rate;
    omx_vorbisdec_component_Private->pAudioVorbis.nChannels = omx_vorbisdec_component_Private->vi.channels;

    /* Update audio port settings for this Vorbis bitstream */
    if ((omx_vorbisdec_component_Private->pAudioPcmMode.nSamplingRate != omx_vorbisdec_component_Private->pAudioVorbis.nSampleRate) ||
        (omx_vorbisdec_component_Private->pAudioPcmMode.nChannels != omx_vorbisdec_component_Private->pAudioVorbis.nChannels)) {
      omx_vorbisdec_component_Private->pAudioPcmMode.nSamplingRate = omx_vorbisdec_component_Private->pAudioVorbis.nSampleRate;
      omx_vorbisdec_component_Private->pAudioPcmMode.nChannels = omx_vorbisdec_component_Private->pAudioVorbis.nChannels;

      /*Send Port Settings changed call back*/
      (*(omx_vorbisdec_component_Private->callbacks->EventHandler))
        (openmaxStandComp,
        omx_vorbisdec_component_Private->callbackData,
        OMX_EventPortSettingsChanged, /* The command was completed */
        0,
        1, /* This is the output port index */
        NULL);
    }

    omx_vorbisdec_component_Private->convsize=inputbuffer->nFilledLen/omx_vorbisdec_component_Private->vi.channels;
    /* OK, got and parsed all three headers. Initialize the Vorbis
    packet->PCM decoder. */
    vorbis_synthesis_init(&omx_vorbisdec_component_Private->vd,&omx_vorbisdec_component_Private->vi); /* central decode state */
    vorbis_block_init(&omx_vorbisdec_component_Private->vd,&omx_vorbisdec_component_Private->vb);/* local state for most of the decode
                               so multiple block decodes can
                               proceed in parallel.  We could init
                               multiple vorbis_block structures
                               for vd here */
  }
  DEBUG(DEB_LEV_FULL_SEQ,"***** now the decoding will start *****\n");

  if(omx_vorbisdec_component_Private->isNewBuffer)  {
    omx_vorbisdec_component_Private->isNewBuffer=0;
    int result=ogg_sync_pageout(&omx_vorbisdec_component_Private->oy,&omx_vorbisdec_component_Private->og);
    DEBUG(DEB_LEV_FULL_SEQ," --->  page (read in decoding) - header len :  %ld body len : %ld \n",omx_vorbisdec_component_Private->og.header_len,omx_vorbisdec_component_Private->og.body_len);
    if(result == 0)  {
      omx_vorbisdec_component_Private->isNewBuffer = 1;
      inputbuffer->nFilledLen = 0;
      return;
    }
    if(result<0)
    { 
      /* missing or corrupt data at this page position */
      DEBUG(DEB_LEV_ERR,"Corrupt or missing data in bitstream; continuing...\n");
    }
    else {
      ogg_stream_pagein(&omx_vorbisdec_component_Private->os,&omx_vorbisdec_component_Private->og); /* can safely ignore errors at */
    }
  }
  
  result=ogg_stream_packetout(&omx_vorbisdec_component_Private->os,&omx_vorbisdec_component_Private->op);
  DEBUG(DEB_LEV_FULL_SEQ," packet length (read in decoding a particular page): %ld \n",omx_vorbisdec_component_Private->op.bytes);
  if(result == 0)  {
    omx_vorbisdec_component_Private->isNewBuffer = 1;
    inputbuffer->nFilledLen = 0;
    return;
  }
  if(result<0)
  {
    /* missing or corrupt data at this page position */
    /* no reason to complain; already complained above */
    DEBUG(DEB_LEV_ERR,"Corrupt or missing data in bitstream; continuing...\n");
  } else {
    /* we have a packet.  Decode it */
    omx_vorbisdec_component_Private->packetNumber++;

    if(vorbis_synthesis(&omx_vorbisdec_component_Private->vb,&omx_vorbisdec_component_Private->op)==0) /* test for success! */
    vorbis_synthesis_blockin(&omx_vorbisdec_component_Private->vd,&omx_vorbisdec_component_Private->vb);
    /**pcm is a multichannel float vector.  In stereo, for
      example, pcm[0] is left, and pcm[1] is right.  samples is
      the size of each channel.  Convert the float values
      (-1.<=range<=1.) to whatever PCM format and write it out */

    while((samples=vorbis_synthesis_pcmout(&omx_vorbisdec_component_Private->vd,&pcm))>0)
    {
      bout=(samples<omx_vorbisdec_component_Private->convsize?samples:omx_vorbisdec_component_Private->convsize);

      /* convert floats to 16 bit signed ints (host order) and interleave */
      for(i=0;i<omx_vorbisdec_component_Private->vi.channels;i++)
      {
        ogg_int16_t *ptr=convbuffer+i;
        mono=pcm[i];
        for(j=0;j<bout;j++)
        {
#if 1
          val=mono[j]*32767.f;
#else     /* optional dither */
          val=mono[j]*32767.f+drand48()-0.5f;
#endif
          /* might as well guard against clipping */
          if(val>32767)
          {
            val=32767;
            clipflag=1;
          }
          if(val<-32768)
          {
            val=-32768;
            clipflag=1;
          }
          *ptr=val;
          ptr+=omx_vorbisdec_component_Private->vi.channels;
        }
      }

      outputbuffer->nFilledLen=2*omx_vorbisdec_component_Private->vi.channels*bout;
      memcpy(outputCurrBuffer,(char *)convbuffer,outputbuffer->nFilledLen);

      if(clipflag) {
        DEBUG(DEB_LEV_FULL_SEQ,"Clipping in frame %ld\n",(long)(omx_vorbisdec_component_Private->vd.sequence));
      }
      vorbis_synthesis_read(&omx_vorbisdec_component_Private->vd,bout); /* tell libvorbis how many samples we actually consumed */
    }
  }
  if(ogg_page_eos(&omx_vorbisdec_component_Private->og)) {
    DEBUG(DEB_LEV_FULL_SEQ, "In %s EOS Detected\n",__func__);
    eos=1;
  }
 
  DEBUG(DEB_LEV_FULL_SEQ, "One output buffer %x len=%d is full returning\n", (int)outputbuffer->pBuffer, (int)outputbuffer->nFilledLen);  
}
Exemple #16
0
/*
   The page is the beginning of a new stream. Check the contents for known
   stream headers. If it is a known stream and the user has requested that
   it should be extracted then allocate a new packetizer based on the
   stream type and store the needed data in a new ogm_demuxer_c.
*/
void
ogm_reader_c::handle_new_stream(ogg_page *og) {
  ogg_stream_state os;
  ogg_packet op;

  if (ogg_stream_init(&os, ogg_page_serialno(og))) {
    mxwarn_fn(m_ti.m_fname, boost::format(Y("ogg_stream_init for stream number %1% failed. Will try to continue and ignore this stream.\n")) % sdemuxers.size());
    return;
  }

  // Read the first page and get its first packet.
  ogg_stream_pagein(&os, og);
  ogg_stream_packetout(&os, &op);

  ogm_demuxer_c *dmx = nullptr;

  /*
   * Check the contents for known stream headers. This one is the
   * standard Vorbis header.
   */
  if ((7 <= op.bytes) && !strncmp((char *)&op.packet[1], "vorbis", 6))
    dmx = new ogm_a_vorbis_demuxer_c(this);

  else if ((8 <= op.bytes) && !memcmp(&op.packet[0], "OpusHead", 8))
    dmx = new ogm_a_opus_demuxer_c(this);

  else if ((7 <= op.bytes) && !strncmp((char *)&op.packet[1], "theora", 6))
    dmx = new ogm_v_theora_demuxer_c(this);

  else if ((8 <= op.bytes) && !memcmp(&op.packet[1], "kate\0\0\0", 7))
    dmx = new ogm_s_kate_demuxer_c(this);

  // FLAC
  else if (   ((4 <= op.bytes) && !strncmp(reinterpret_cast<char *>(&op.packet[0]), "fLaC", 4))
           || ((5 <= op.bytes) && !strncmp(reinterpret_cast<char *>(&op.packet[1]), "FLAC", 4) && (0x7f == op.packet[0]))) {
#if !defined(HAVE_FLAC_FORMAT_H)
    if (demuxing_requested('a', sdemuxers.size()))
      mxerror_fn(m_ti.m_fname, Y("mkvmerge has not been compiled with FLAC support but handling of this stream has been requested.\n"));

    else {
      dmx         = new ogm_demuxer_c(this);
      dmx->stype  = OGM_STREAM_TYPE_A_FLAC;
      dmx->in_use = true;
    }

#else
    dmx = new ogm_a_flac_demuxer_c(this, 0x7f == op.packet[0] ? ofm_post_1_1_1 : ofm_pre_1_1_1);
#endif

  } else if ((static_cast<size_t>(op.bytes) >= sizeof(vp8_ogg_header_t)) && (0x4f == op.packet[0]) && (get_uint32_be(&op.packet[1]) == 0x56503830))
    dmx = new ogm_v_vp8_demuxer_c(this, op);

  else if (((*op.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER) && (op.bytes >= ((int)sizeof(stream_header) + 1))) {
    // The new stream headers introduced by OggDS (see ogmstreams.h).

    stream_header *sth = (stream_header *)(op.packet + 1);
    char buf[5];
    buf[4] = 0;

    if (!strncmp(sth->streamtype, "video", 5)) {
      memcpy(buf, (char *)sth->subtype, 4);

      if (mpeg4::p10::is_avc_fourcc(buf) && !hack_engaged(ENGAGE_ALLOW_AVC_IN_VFW_MODE))
        dmx = new ogm_v_avc_demuxer_c(this);
      else
        dmx = new ogm_v_mscomp_demuxer_c(this);

    } else if (!strncmp(sth->streamtype, "audio", 5)) {
      memcpy(buf, (char *)sth->subtype, 4);

      uint32_t codec_id = strtol(buf, (char **)nullptr, 16);

      if (0x0001 == codec_id)
        dmx = new ogm_a_pcm_demuxer_c(this);

      else if ((0x0050 == codec_id) || (0x0055 == codec_id))
        dmx = new ogm_a_mp3_demuxer_c(this);

      else if (0x2000 == codec_id)
        dmx = new ogm_a_ac3_demuxer_c(this);

      else if (0x00ff == codec_id)
        dmx = new ogm_a_aac_demuxer_c(this);

      else
        mxwarn_fn(m_ti.m_fname, boost::format(Y("Unknown audio stream type 0x%|1$04x|. Stream ID %2% will be ignored.\n")) % codec_id % sdemuxers.size());

    } else if (!strncmp(sth->streamtype, "text", 4))
      dmx = new ogm_s_text_demuxer_c(this);
  }

  /*
   * The old OggDS headers (see MPlayer's source, libmpdemux/demux_ogg.c)
   * are not supported.
   */

  if (!dmx)
    dmx = new ogm_demuxer_c(this);

  std::string type = dmx->get_type();

  dmx->serialno    = ogg_page_serialno(og);
  dmx->track_id    = sdemuxers.size();
  dmx->in_use      = (type != "unknown") && demuxing_requested(type[0], dmx->track_id);

  dmx->packet_data.push_back(memory_c::clone(op.packet, op.bytes));

  memcpy(&dmx->os, &os, sizeof(ogg_stream_state));

  sdemuxers.push_back(ogm_demuxer_cptr(dmx));

  dmx->initialize();
}
UInt32 SFB::Audio::OggSpeexDecoder::_ReadAudio(AudioBufferList *bufferList, UInt32 frameCount)
{
	if(bufferList->mNumberBuffers != mFormat.mChannelsPerFrame) {
		LOGGER_WARNING("org.sbooth.AudioEngine.Decoder.OggSpeex", "_ReadAudio() called with invalid parameters");
		return 0;
	}

	UInt32 framesRead = 0;
	
	// Reset output buffer data size
	for(UInt32 i = 0; i < bufferList->mNumberBuffers; ++i)
		bufferList->mBuffers[i].mDataByteSize = 0;

	for(;;) {
		
		UInt32	framesRemaining	= frameCount - framesRead;
		UInt32	framesToSkip	= (UInt32)(bufferList->mBuffers[0].mDataByteSize / sizeof(float));
		UInt32	framesInBuffer	= (UInt32)(mBufferList->mBuffers[0].mDataByteSize / sizeof(float));
		UInt32	framesToCopy	= std::min(framesInBuffer, framesRemaining);
		
		// Copy data from the buffer to output
		for(UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i) {
			float *floatBuffer = (float *)bufferList->mBuffers[i].mData;
			memcpy(floatBuffer + framesToSkip, mBufferList->mBuffers[i].mData, framesToCopy * sizeof(float));
			bufferList->mBuffers[i].mDataByteSize += framesToCopy * sizeof(float);
			
			// Move remaining data in buffer to beginning
			if(framesToCopy != framesInBuffer) {
				floatBuffer = (float *)mBufferList->mBuffers[i].mData;
				memmove(floatBuffer, floatBuffer + framesToCopy, (framesInBuffer - framesToCopy) * sizeof(float));
			}
			
			mBufferList->mBuffers[i].mDataByteSize -= framesToCopy * sizeof(float);
		}
		
		framesRead += framesToCopy;
		
		// All requested frames were read
		if(framesRead == frameCount)
			break;
		
		// EOS reached
		if(mSpeexEOSReached)
			break;

		// Attempt to process the desired number of packets
		unsigned packetsDesired = 1;
		while(0 < packetsDesired && !mSpeexEOSReached) {

			// Process any packets in the current page
			while(0 < packetsDesired && !mSpeexEOSReached) {

				// Grab a packet from the streaming layer
				ogg_packet oggPacket;
				int result = ogg_stream_packetout(&mOggStreamState, &oggPacket);
				if(-1 == result) {
					LOGGER_ERR("org.sbooth.AudioEngine.Decoder.OggSpeex", "Ogg Speex decoding error: Ogg loss of streaming");
					break;
				}
				
				// If result is 0, there is insufficient data to assemble a packet
				if(0 == result)
					break;

				// Otherwise, we got a valid packet for processing
				if(1 == result) {
					if(5 <= oggPacket.bytes && !memcmp(oggPacket.packet, "Speex", 5))
						mSpeexSerialNumber = mOggStreamState.serialno;
					
					if(-1 == mSpeexSerialNumber || mOggStreamState.serialno != mSpeexSerialNumber)
						break;
					
					// Ignore the following:
					//  - Speex comments in packet #2
					//  - Extra headers (optionally) in packets 3+
					if(1 != mOggPacketCount && 1 + mExtraSpeexHeaderCount <= mOggPacketCount) {
						// Detect Speex EOS
						if(oggPacket.e_o_s && mOggStreamState.serialno == mSpeexSerialNumber)
							mSpeexEOSReached = true;

						// SPEEX_GET_FRAME_SIZE is in samples
						spx_int32_t speexFrameSize;
						speex_decoder_ctl(mSpeexDecoder, SPEEX_GET_FRAME_SIZE, &speexFrameSize);
						float buffer [(2 == mFormat.mChannelsPerFrame) ? 2 * speexFrameSize : speexFrameSize];
						
						// Copy the Ogg packet to the Speex bitstream
						speex_bits_read_from(&mSpeexBits, (char *)oggPacket.packet, (int)oggPacket.bytes);
						
						// Decode each frame in the Speex packet
						for(spx_int32_t i = 0; i < mSpeexFramesPerOggPacket; ++i) {
							
							result = speex_decode(mSpeexDecoder, &mSpeexBits, buffer);

							// -1 indicates EOS
							if(-1 == result)
								break;
							else if(-2 == result) {
								LOGGER_ERR("org.sbooth.AudioEngine.Decoder.OggSpeex", "Ogg Speex decoding error: possible corrupted stream");
								break;
							}
							
							if(0 > speex_bits_remaining(&mSpeexBits)) {
								LOGGER_ERR("org.sbooth.AudioEngine.Decoder.OggSpeex", "Ogg Speex decoding overflow: possible corrupted stream");
								break;
							}
							
							// Normalize the values
							float maxSampleValue = 1u << 15;
							vDSP_vsdiv(buffer, 1, &maxSampleValue, buffer, 1, (vDSP_Length)speexFrameSize);

							// Copy the frames from the decoding buffer to the output buffer, skipping over any frames already decoded
							framesInBuffer = mBufferList->mBuffers[0].mDataByteSize / sizeof(float);
							memcpy((float *)mBufferList->mBuffers[0].mData + framesInBuffer, buffer, (size_t)speexFrameSize * sizeof(float));
							mBufferList->mBuffers[0].mDataByteSize += (size_t)speexFrameSize * sizeof(float);
							
							// Process stereo channel, if present
							if(2 == mFormat.mChannelsPerFrame) {
								speex_decode_stereo(buffer, speexFrameSize, mSpeexStereoState);
								vDSP_vsdiv(buffer + speexFrameSize, 1, &maxSampleValue, buffer + speexFrameSize, 1, (vDSP_Length)speexFrameSize);

								memcpy((float *)mBufferList->mBuffers[1].mData + framesInBuffer, buffer + speexFrameSize, (size_t)speexFrameSize * sizeof(float));
								mBufferList->mBuffers[1].mDataByteSize += (size_t)speexFrameSize * sizeof(float);
							}
							
							// Packet processing finished
							--packetsDesired;
						}
					}

					++mOggPacketCount;
				}
			}
			
			// Grab a new Ogg page for processing, if necessary
			if(!mSpeexEOSReached && 0 < packetsDesired) {
				while(1 != ogg_sync_pageout(&mOggSyncState, &mOggPage)) {
					// Get the ogg buffer for writing
					char *data = ogg_sync_buffer(&mOggSyncState, READ_SIZE_BYTES);
					
					// Read bitstream from input file
					ssize_t bytesRead = (ssize_t)GetInputSource().Read(data, READ_SIZE_BYTES);
					if(-1 == bytesRead) {
						LOGGER_ERR("org.sbooth.AudioEngine.Decoder.OggSpeex", "Unable to read from the input file");
						break;
					}
					
					ogg_sync_wrote(&mOggSyncState, bytesRead);

					// No more data available from input file
					if(0 == bytesRead)
						break;
				}
				
				// Ensure all Ogg streams are read
				if(ogg_page_serialno(&mOggPage) != mOggStreamState.serialno)
					ogg_stream_reset_serialno(&mOggStreamState, ogg_page_serialno(&mOggPage));

				// Get the resultant Ogg page
				int result = ogg_stream_pagein(&mOggStreamState, &mOggPage);
				if(0 != result) {
					LOGGER_ERR("org.sbooth.AudioEngine.Decoder.OggSpeex", "Error reading Ogg page");
					break;
				}
			}
		}
	}
	
	mCurrentFrame += framesRead;

	if(0 == framesRead && mSpeexEOSReached)
		mTotalFrames = mCurrentFrame;

	return framesRead;
}
static int read_samples(struct ast_filestream *fs, float ***pcm)
{
	int samples_in;
	int result;
	char *buffer;
	int bytes;
	struct vorbis_desc *s = (struct vorbis_desc *)fs->_private;

	while (1) {
		samples_in = vorbis_synthesis_pcmout(&s->vd, pcm);
		if (samples_in > 0) {
			return samples_in;
		}

		/* The Vorbis decoder needs more data... */
		/* See ifOGG has any packets in the current page for the Vorbis decoder. */
		result = ogg_stream_packetout(&s->os, &s->op);
		if (result > 0) {
			/* Yes OGG had some more packets for the Vorbis decoder. */
			if (vorbis_synthesis(&s->vb, &s->op) == 0) {
				vorbis_synthesis_blockin(&s->vd, &s->vb);
			}

			continue;
		}

		if (result < 0)
			ast_log(LOG_WARNING,
					"Corrupt or missing data at this page position; continuing...\n");

		/* No more packets left in the current page... */

		if (s->eos) {
			/* No more pages left in the stream */
			return -1;
		}

		while (!s->eos) {
			/* See ifOGG has any pages in it's internal buffers */
			result = ogg_sync_pageout(&s->oy, &s->og);
			if (result > 0) {
				/* Yes, OGG has more pages in it's internal buffers,
				   add the page to the stream state */
				result = ogg_stream_pagein(&s->os, &s->og);
				if (result == 0) {
					/* Yes, got a new,valid page */
					if (ogg_page_eos(&s->og)) {
						s->eos = 1;
					}
					break;
				}
				ast_log(LOG_WARNING,
						"Invalid page in the bitstream; continuing...\n");
			}

			if (result < 0)
				ast_log(LOG_WARNING,
						"Corrupt or missing data in bitstream; continuing...\n");

			/* No, we need to read more data from the file descrptor */
			/* get a buffer from OGG to read the data into */
			buffer = ogg_sync_buffer(&s->oy, BLOCK_SIZE);
			/* read more data from the file descriptor */
			bytes = fread(buffer, 1, BLOCK_SIZE, fs->f);
			/* Tell OGG how many bytes we actually read into the buffer */
			ogg_sync_wrote(&s->oy, bytes);
			if (bytes == 0) {
				s->eos = 1;
			}
		}
	}
}
Exemple #19
0
static gint
xmms_speex_read (xmms_xform_t *xform, gpointer buf, gint len,
                 xmms_error_t *err)
{
	gint ret = 0, n;
	gfloat outfloat [2000];
	gint16 *outbuf = (gint16 *) buf;
	xmms_speex_data_t *data;
	xmms_error_t error;
	SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT;

	g_return_val_if_fail (xform, -1);

	data = xmms_xform_private_data_get (xform);
	g_return_val_if_fail (data, -1);

	/* convert from bytes to samples */
	len /= 2;

	/* first, copy already decoded samples over if we have any. */
	if (data->samples_count) {
		n = MIN (data->samples_count, len);

		memcpy (outbuf, data->samples_start, n * 2);
		data->samples_count -= n;

		if (!data->samples_count) {
			data->samples_start = data->samples_buf;
		} else {
			data->samples_start += n;
		}

		/* convert from samples to bytes */
		return n * 2;
	}

	while (42) {
		gint samples_per_frame;

		samples_per_frame = data->speexheader->frame_size *
		                    data->speexheader->nb_channels;

		while (ogg_stream_packetout (&data->stream_state, &data->ogg_packet) == 1) {
			gint frame;

			speex_bits_read_from (&data->speex_bits,
			                      (char *)data->ogg_packet.packet,
			                      data->ogg_packet.bytes);

			for (frame = 0; frame < data->speexheader->frames_per_packet; frame++) {
				gint cnt;

				speex_decode (data->speex_state, &data->speex_bits, outfloat);

				if (data->speexheader->nb_channels == 2) {
					speex_decode_stereo (outfloat, data->speexheader->frame_size,&stereo);
				}

				n = MIN (samples_per_frame, len);

				/* copy as many samples to the output buffer as
				 * possible.
				 */
				for (cnt = 0; cnt < n; cnt++) {
					*outbuf++ = outfloat[cnt];
					len--;
					ret += 2;
				}

				/* store the remaining samples for later use */
				for (; cnt < samples_per_frame; cnt++) {
					data->samples_buf[data->samples_count++] =
						outfloat[cnt];
				}
			}

			return ret;
		}

		/* Need more data */

		do {
			gint ret;

			data->ogg_data = ogg_sync_buffer (&data->sync_state, 200);
			ret = xmms_xform_read (xform, data->ogg_data, 200, &error);
			ogg_sync_wrote (&data->sync_state, ret);

			if (ret <= 0) {
				return ret;
			}
		} while (ogg_sync_pageout (&data->sync_state, &data->ogg_page) != 1);

		ogg_stream_pagein (&data->stream_state, &data->ogg_page);
	}
}
/*!
 * \brief Create a new OGG/Vorbis filestream and set it up for reading.
 * \param s File that points to on disk storage of the OGG/Vorbis data.
 * \return The new filestream.
 */
static int ogg_vorbis_open(struct ast_filestream *s)
{
	int i;
	int bytes;
	int result;
	char **ptr;
	char *buffer;
	struct vorbis_desc *tmp = (struct vorbis_desc *)s->_private;

	tmp->writing = 0;

	ogg_sync_init(&tmp->oy);

	buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
	bytes = fread(buffer, 1, BLOCK_SIZE, s->f);
	ogg_sync_wrote(&tmp->oy, bytes);

	result = ogg_sync_pageout(&tmp->oy, &tmp->og);
	if (result != 1) {
		if(bytes < BLOCK_SIZE) {
			ast_log(LOG_ERROR, "Run out of data...\n");
		} else {
			ast_log(LOG_ERROR, "Input does not appear to be an Ogg bitstream.\n");
		}
		ogg_sync_clear(&tmp->oy);
		return -1;
	}
	
	ogg_stream_init(&tmp->os, ogg_page_serialno(&tmp->og));
	vorbis_info_init(&tmp->vi);
	vorbis_comment_init(&tmp->vc);

	if (ogg_stream_pagein(&tmp->os, &tmp->og) < 0) { 
		ast_log(LOG_ERROR, "Error reading first page of Ogg bitstream data.\n");
error:
		ogg_stream_clear(&tmp->os);
		vorbis_comment_clear(&tmp->vc);
		vorbis_info_clear(&tmp->vi);
		ogg_sync_clear(&tmp->oy);
		return -1;
	}
	
	if (ogg_stream_packetout(&tmp->os, &tmp->op) != 1) { 
		ast_log(LOG_ERROR, "Error reading initial header packet.\n");
		goto error;
	}
	
	if (vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op) < 0) { 
		ast_log(LOG_ERROR, "This Ogg bitstream does not contain Vorbis audio data.\n");
		goto error;
	}
	
	for (i = 0; i < 2 ; ) {
		while (i < 2) {
			result = ogg_sync_pageout(&tmp->oy, &tmp->og);
			if (result == 0)
				break;
			if (result == 1) {
				ogg_stream_pagein(&tmp->os, &tmp->og);
				while(i < 2) {
					result = ogg_stream_packetout(&tmp->os,&tmp->op);
					if(result == 0)
						break;
					if(result < 0) {
						ast_log(LOG_ERROR, "Corrupt secondary header.  Exiting.\n");
						goto error;
					}
					vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op);
					i++;
				}
			}
		}

		buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
		bytes = fread(buffer, 1, BLOCK_SIZE, s->f);
		if (bytes == 0 && i < 2) {
			ast_log(LOG_ERROR, "End of file before finding all Vorbis headers!\n");
			goto error;
		}
		ogg_sync_wrote(&tmp->oy, bytes);
	}
	
	for (ptr = tmp->vc.user_comments; *ptr; ptr++)
		ast_debug(1, "OGG/Vorbis comment: %s\n", *ptr);
		ast_debug(1, "OGG/Vorbis bitstream is %d channel, %ldHz\n", tmp->vi.channels, tmp->vi.rate);
		ast_debug(1, "OGG/Vorbis file encoded by: %s\n", tmp->vc.vendor);

	if (tmp->vi.channels != 1) {
		ast_log(LOG_ERROR, "Only monophonic OGG/Vorbis files are currently supported!\n");
		goto error;
	}
	
	if (tmp->vi.rate != DEFAULT_SAMPLE_RATE) {
		ast_log(LOG_ERROR, "Only 8000Hz OGG/Vorbis files are currently supported!\n");
		vorbis_block_clear(&tmp->vb);
		vorbis_dsp_clear(&tmp->vd);
		goto error;
	}
	
	vorbis_synthesis_init(&tmp->vd, &tmp->vi);
	vorbis_block_init(&tmp->vd, &tmp->vb);

	return 0;
}
/* process the vorbis audio packets. Here we just take each packet out
 * and add them into the new stream, flushing after so many samples. We
 * also check if an new headers are requested after each processed page
 */
static int process_vorbis_audio (ogg_state_t *ogg_info, ogg_codec_t *codec)
{
    vorbis_codec_t *source_vorbis = codec->specific;

    while (1)
    {
        int window;
        ogg_packet packet;

        /* now, lets extract what packets we can */
        if (ogg_stream_packetout (&codec->os, &packet) <= 0)
            break;

        /* calculate granulepos for the packet */
        window = vorbis_packet_blocksize (&source_vorbis->vi, &packet) / 4;

        source_vorbis->granulepos += window;
        if (source_vorbis->prev_packet)
        {
            ogg_packet *prev_packet = source_vorbis->prev_packet;

            add_audio_packet (source_vorbis, prev_packet);
            free_ogg_packet (prev_packet);

            /* check for short values on first initial page */
            if (packet . packetno == 4)
            {
                source_vorbis->initial_page_granulepos = codec->os.granulepos;
                if (source_vorbis->initial_page_granulepos < source_vorbis->granulepos)
                    source_vorbis->granulepos -= source_vorbis->initial_page_granulepos;
            }
            /* check for long values on first page */
            if (packet.granulepos == source_vorbis->initial_page_granulepos)
            {
                if (source_vorbis->initial_page_granulepos > source_vorbis->granulepos)
                    source_vorbis->granulepos = source_vorbis->initial_page_granulepos;
            }

            if (packet.e_o_s == 0)
                packet . granulepos = source_vorbis->granulepos;
        }
        else
        {
            packet . granulepos = 0;
        }

        /* store the current packet details */
        source_vorbis->prev_window = window;
        source_vorbis->prev_packet = copy_ogg_packet (&packet);
        if (packet.e_o_s)
        {
            initiate_flush (source_vorbis);
            free_ogg_packet (source_vorbis->prev_packet);
            source_vorbis->prev_packet = NULL;
            return 1;
        }

        /* allow for pages to be flushed if there's over a certain number of samples */
        if (source_vorbis->samples_in_page > source_vorbis->page_samples_trigger)
            return 1;
    }
    if (source_vorbis->stream_notify)
    {
        initiate_flush (source_vorbis);
        source_vorbis->stream_notify = 0;
        return 1;
    }
    return -1;
}
Exemple #22
0
/* Read the speex header. Return 0 on error. */
static int read_speex_header (struct spx_data *data)
{
	int packet_count = 0;
	int stream_init = 0;
	char *buf;
	int nb_read;

	while (packet_count < 2) {

		/* Get the ogg buffer for writing */
		buf = ogg_sync_buffer (&data->oy, 200);

		/* Read bitstream from input file */
		nb_read = io_read (data->stream, buf, 200);

		if (nb_read < 0) {
			decoder_error (&data->error, ERROR_FATAL, 0,
					"Can't open speex file: IO error: %s",
					io_strerror(data->stream));
			return 0;
		}

		if (nb_read == 0) {
			decoder_error (&data->error, ERROR_FATAL, 0,
					"Can't open speex header");
			return 0;
		}
		
		ogg_sync_wrote (&data->oy, nb_read);

		/* Loop for all complete pages we got (most likely only one) */
		while (ogg_sync_pageout(&data->oy, &data->og) == 1) {

			if (stream_init == 0) {
				ogg_stream_init(&data->os,
						ogg_page_serialno(&data->og));
				stream_init = 1;
			}

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

			/* Extract all available packets FIXME: EOS! */
			while (ogg_stream_packetout(&data->os, &data->op)
					== 1) {
				
				/* If first packet, process as Speex header */
				if (packet_count == 0) {
					data->st = process_header (data);

					if (!data->st) {
						ogg_stream_clear (&data->os);
						return 0;
					}

					data->rate = data->header->rate;
					data->nchannels
						= data->header->nb_channels;
					data->frames_per_packet
						= data->header->frames_per_packet; 
					/*data->vbr = data->header->vbr; */

					if (!data->frames_per_packet)
						data->frames_per_packet=1;

					data->output = xmalloc (data->frame_size *
							data->nchannels *
							data->frames_per_packet *
							sizeof(int16_t));
					data->output_start = 0;
					data->output_left = 0;
				}
				else if (packet_count == 1) {
					data->comment_packet_len
						= data->op.bytes;
					data->comment_packet = xmalloc (
							sizeof(char) * 
							data->comment_packet_len);
					memcpy (data->comment_packet,
							data->op.packet,
							data->comment_packet_len);
				}
				/* FIXME: ignore extra headers */

				packet_count++;
			}
		}
	}

	return 1;
}
Exemple #23
0
// Decode
static int Decode(void *context, const void *dataRAW,
					size_t sizeRAW, void **ppdataPCM, size_t *sizePCM)
{
	OGG_context *ctx = (OGG_context*)context;

	*sizePCM = 0;
	*ppdataPCM = 0;

	if (!dataRAW)
		return 0;

	switch(ctx->state)
	{
		// Sync buffer
		case 0xff:
		{
			sysMemCpy(ogg_sync_buffer(&ctx->oy, (int32_t)sizeRAW), dataRAW, sizeRAW);
			ctx->input_size = sizeRAW;
			ogg_sync_wrote(&ctx->oy, (int32_t)ctx->input_size);
			ctx->state = 0;
		}
		break;
		// Sync page out
		case 0:
		{
			int result = ogg_sync_pageout(&ctx->oy, &ctx->og);
			if (result == 0)
			{
				ctx->state = 0xff;
			}
			else
			if (result < 0)
			{
				ctx->state = -1;
			}
			else
			{
				ogg_stream_pagein(&ctx->os, &ctx->og); /* can safely ignore errors at this point */
				ctx->state = 1;
			}
		}
		break;

		// Stream packet out
		case 1:
		{
			int result = ogg_stream_packetout(&ctx->os, &ctx->op);
			if (result == 0)
			{
				ctx->state = 0;
			}
			else
			if (result < 0)
			{
				ctx->state = -2;
			}
			else
			{
				/* we have a packet.	Decode it */
				if (vorbis_synthesis(&ctx->vb, &ctx->op)==0) /* test for success! */
					vorbis_synthesis_blockin(&ctx->vd, &ctx->vb);
				ctx->state = 3;
			}
		}
		break;

		// synthetis pcm out
		case 3:
		{
			size_t samples;
			float **pcm;
			samples = vorbis_synthesis_pcmout(&ctx->vd, &pcm);
			if (samples<=0)
			{
				ctx->state = 1;
			}
			else
			{
				size_t convsize = ctx->input_size / ctx->vi.channels;
				size_t bytesCount = samples < convsize ? samples : convsize;
				SYS_ASSERT(bytesCount < OGG_BUFFER_SIZE);
#ifdef SUPPORT_IEEE_AUDIO
				DeinterleaveAudio(ctx->uncompressed, pcm, ctx->vi.channels, bytesCount);
				*sizePCM = 4 * ctx->vi.channels * bytesCount;
#else
				ConvertFloatToInteger(ctx->uncompressed, pcm, ctx->vi.channels, bytesCount);
				*sizePCM = 2 * ctx->vi.channels * bytesCount;
#endif
				/* tell libvorbis how many samples we actually consumed */
				vorbis_synthesis_read(&ctx->vd, (int32_t)bytesCount);
				*ppdataPCM = ctx->uncompressed;
			}
		}
		break;

		// Invalid state
		default:
			SYS_ASSERT(0);
			return -1;
		break;

	}
	return ctx->state != 0xff ? 1 : 0;
}
Exemple #24
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);
  }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);

}
Exemple #25
0
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    int error = CODEC_ERROR;
    long action;
    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 = -1;
    int sample_rate = 48000;
    OpusDecoder *st = NULL;
    OpusHeader header;
    int ret;
    unsigned long strtoffset;
    int skip = 0;
    int64_t seek_target;
    uint64_t granule_pos;

    ogg_malloc_init();

    action = CODEC_ACTION_NULL;
    param = ci->id3->elapsed;
    strtoffset = ci->id3->offset;

#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);

    goto next_page; /* need to decode header before we do anything else */

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

    process_action:
        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);
                opus_seek_page_granule(seek_target, page_granule, &oy, &os);
            }

            ci->set_elapsed(param);
            ci->seek_complete();
            param = 0;
        } else  if (action == CODEC_ACTION_HALT)
            break;

    next_page:
        /*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) {
                stream_init = ogg_stream_init(&os, ogg_page_serialno(&og));
                if (stream_init != 0) {
                    LOGF("Stream init failed");
                    goto done;
                }
            }

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

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

            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);

                    if (strtoffset)
                        seek_ogg_page(strtoffset);
                    else if (param) {
                        action = CODEC_ACTION_SEEK_TIME;
                        goto process_action;
                    } else {
                    /* seek buffer directly to the first audio packet to avoid 
                       allocating space for huge comment packets
                       (embedded Album Art) */
                        if (seek_opus_tags())
                            seek_ogg_page(ci->curpos);
                        else {
                            LOGF("Could not find comment header");
                            goto done;
                        }
                    }
                    LOGF("sync reset");
                    ogg_sync_reset(&oy); /* next page */
                    break;
                } else {
                    /* report progress */
                    ci->set_offset((size_t) ci->curpos);
                    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 > skip) {
                        /* part of or entire output buffer is played */
                        ret -= skip;
                        ci->pcmbuf_insert(&output[skip * header.channels], NULL, ret);
                        skip = 0;
                    } else {
                        if (ret < 0) {
                            LOGF("opus_decode failed %d", ret);
                            goto done;
                        } else if (ret == 0)
                            break;
                        else {
                            /* entire output buffer is skipped */
                            skip -= ret;
                            ret = 0;
                        }
                    }
                }
            }
        }
    }
    LOGF("Returned OK");
    error = CODEC_OK;
done:
    ogg_malloc_destroy();
    return error;
}
Exemple #26
0
/* this is void and does not propogate errors up because we want to be
   able to open and use damaged bitstreams as well as we can.  Just
   watch out for missing information for links in the OggVorbis_File
   struct */
static void _prefetch_all_headers(OggVorbis_File *vf, ogg_int64_t dataoffset){
  ogg_page og;
  int i;
  ogg_int64_t ret;
  
  vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
  vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
  vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
  vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
  
  for(i=0;i<vf->links;i++){
    if(i==0){
      /* we already grabbed the initial header earlier.  Just set the offset */
      vf->dataoffsets[i]=dataoffset;
      _seek_helper(vf,dataoffset);

    }else{

      /* seek to the location of the initial header */

      _seek_helper(vf,vf->offsets[i]);
      if(_fetch_headers(vf,vf->vi+i,vf->vc+i,NULL,NULL)<0){
    	vf->dataoffsets[i]=-1;
      }else{
	vf->dataoffsets[i]=vf->offset;
      }
    }

    /* fetch beginning PCM offset */

    if(vf->dataoffsets[i]!=-1){
      ogg_int64_t accumulated=0;
      long        lastblock=-1;
      int         result;

      ogg_stream_reset_serialno(&vf->os,vf->serialnos[i]);

      while(1){
	ogg_packet op;

	ret=_get_next_page(vf,&og,-1);
	if(ret<0)
	  /* this should not be possible unless the file is
             truncated/mangled */
	  break;
       
	if(ogg_page_serialno(&og)!=vf->serialnos[i])
	  break;
	
	/* count blocksizes of all frames in the page */
	ogg_stream_pagein(&vf->os,&og);
	while((result=ogg_stream_packetout(&vf->os,&op))){
	  if(result>0){ /* ignore holes */
	    long thisblock=vorbis_packet_blocksize(vf->vi+i,&op);
	    if(lastblock!=-1)
	      accumulated+=(lastblock+thisblock)>>2;
	    lastblock=thisblock;
	  }
	}

	if(ogg_page_granulepos(&og)!=-1){
	  /* pcm offset of last packet on the first audio page */
	  accumulated= ogg_page_granulepos(&og)-accumulated;
	  break;
	}
      }

      /* less than zero?  This is a stream with samples trimmed off
         the beginning, a normal occurrence; set the offset to zero */
      if(accumulated<0)accumulated=0;

      vf->pcmlengths[i*2]=accumulated;
    }
Exemple #27
0
static int decode(quicktime_t *file, 
					int16_t *output_i, 
					float *output_f, 
					long samples, 
					int track, 
					int channel)
{
	int result = 0;
	int i, j;
	quicktime_audio_map_t *track_map = &(file->atracks[track]);
	quicktime_trak_t *trak = track_map->track;
	quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
	long current_position = track_map->current_position;
	long end_position = current_position + samples;
  	char *buffer;
// End of data in ogg buffer
	int eos = 0;
	float *pcm;
	int have_chunk = 0;


	if(samples > OUTPUT_ALLOCATION)
		printf("vorbis.c decode: can't read more than %d samples at a time.\n", OUTPUT_ALLOCATION);



	if(output_i) bzero(output_i, sizeof(int16_t) * samples);
	if(output_f) bzero(output_f, sizeof(float) * samples);







// Seeked outside output buffer's range or not initialized: restart
	if(current_position < codec->output_position - codec->output_size ||
		current_position > codec->output_position ||
		!codec->decode_initialized)
	{

		quicktime_chunk_of_sample(&codec->output_position, 
			&codec->chunk, 
			trak, 
			current_position);
// We know the first ogg packet in the chunk has a pcm_offset from the encoding.

		codec->output_size = 0;
		codec->output_end = 0;
		codec->chunk_samples = 0;



	
// Initialize and load initial buffer for decoding
		if(!codec->decode_initialized)
		{
			int init_chunk = 1;
			codec->decode_initialized = 1;

			codec->output = malloc(sizeof(float*) * track_map->channels);
			for(i = 0; i < track_map->channels; i++)
			{
				codec->output[i] = malloc(sizeof(float) * OUTPUT_ALLOCATION);
			}

			codec->output_allocated = OUTPUT_ALLOCATION;

        	ogg_sync_init(&codec->dec_oy); /* Now we can read pages */




			READ_CHUNK(init_chunk);
			init_chunk++;

   	 		if(ogg_sync_pageout(&codec->dec_oy, &codec->dec_og)!=1)
			{
				fprintf(stderr, "decode: ogg_sync_pageout: Must not be Vorbis data\n");
				return 1;
			}


    		ogg_stream_init(&codec->dec_os, ogg_page_serialno(&codec->dec_og));
    		vorbis_info_init(&codec->dec_vi);
    		vorbis_comment_init(&codec->dec_vc);

    		if(ogg_stream_pagein(&codec->dec_os, &codec->dec_og) < 0)
			{
    	  		fprintf(stderr,"decode: ogg_stream_pagein: stream version mismatch perhaps.\n");
    	  		return 1;
    		}

			if(ogg_stream_packetout(&codec->dec_os, &codec->dec_op) != 1)
			{
				fprintf(stderr, "decode: ogg_stream_packetout: Must not be Vorbis data\n");
    	  		return 1;
			}

			if(vorbis_synthesis_headerin(&codec->dec_vi, &codec->dec_vc, &codec->dec_op) < 0)
			{
				fprintf(stderr, "decode: vorbis_synthesis_headerin: not a vorbis header\n");
				return 1;
			}


			i = 0;
			while(i < 2)
			{
				while(i < 2)
				{
					result = ogg_sync_pageout(&codec->dec_oy, &codec->dec_og);
					if(result == 0) break;

					if(result == 1)
					{
						ogg_stream_pagein(&codec->dec_os, &codec->dec_og);

						while(i < 2)
						{
							result = ogg_stream_packetout(&codec->dec_os, &codec->dec_op);

							if(result == 0) break;

							if(result < 0)
							{
								fprintf(stderr, "decode: ogg_stream_packetout: corrupt secondary header\n");
								return 1;
							}

							vorbis_synthesis_headerin(&codec->dec_vi, &codec->dec_vc, &codec->dec_op);
							i++;




						}
					}
				}

				if(i < 2)
				{
					READ_CHUNK(init_chunk);
					init_chunk++;
				}

// Header should never span more than one chunk so assume it's done here
			}

			vorbis_synthesis_init(&codec->dec_vd, &codec->dec_vi);
			vorbis_block_init(&codec->dec_vd, &codec->dec_vb);

// Also the first chunk needed in decoding so don't reread after this.
			if(codec->chunk == init_chunk - 1) 
			{
				have_chunk = 1;
				codec->chunk++;
			}
		}




// Don't already have initial chunk from header
		if(!have_chunk)
		{
// Get initial chunk for decoding at new location
// From vorbisfile.c
/* clear out decoding machine state */
			ogg_stream_clear(&codec->dec_os);
			vorbis_dsp_clear(&codec->dec_vd);
			vorbis_block_clear(&codec->dec_vb);
    		ogg_sync_reset(&codec->dec_oy);

    		ogg_stream_init(&codec->dec_os, ogg_page_serialno(&codec->dec_og));
        	ogg_sync_init(&codec->dec_oy);
			vorbis_synthesis_init(&codec->dec_vd, &codec->dec_vi);
			vorbis_block_init(&codec->dec_vd, &codec->dec_vb);


			READ_CHUNK(codec->chunk);
			codec->chunk++;
			have_chunk = 1;
		}
	}

// Assume the chunk exists by now and rely on libogg to say if it's out of
// data.
	have_chunk = 1;











// Read chunks until output buffer is on or after end_position
	result = 0;
	while(codec->output_position < end_position)
	{


// Read chunk to decode if it hasn't been read yet.
		if(!have_chunk)
		{
			codec->chunk_samples = 0;

			READ_CHUNK(codec->chunk);
			if(result) break;
			codec->chunk++;
		}

		eos = 0;
		while(!eos)
		{
			result = ogg_sync_pageout(&codec->dec_oy, &codec->dec_og);







// Need more data from chunk
			if(result == 0)
			{
// End of chunk
				eos = 1;
			}
			else
// This stage checks for OggS and a checksum error.
// It doesn't tell if it's the end of a chunk.  Need to manually parse OggS
// pages to figure out how big the chunk is.
			if(result < 0)
			{
//printf("ogg_sync_pageout=-1\n");
				;
			}
			else
			{
				ogg_stream_pagein(&codec->dec_os, &codec->dec_og);



				while(!eos)
				{
//printf("decode 7\n");
					result = ogg_stream_packetout(&codec->dec_os, &codec->dec_op);

//printf("decode 8 %d\n", result);
					if(result == 0)
					{
//printf("ogg_stream_packetout=0\n");
// End of page
						eos = 1;
					}
					else
// This stage doesn't check for OggS.
					if(result < 0)
					{
//printf("ogg_stream_packetout=-1\n");
					}
					else
					{
						float **pcm;







						if(vorbis_synthesis(&codec->dec_vb, &codec->dec_op) == 0)
						{
							vorbis_synthesis_blockin(&codec->dec_vd, 
								&codec->dec_vb);
						}


						while((result = vorbis_synthesis_pcmout(&codec->dec_vd, &pcm)) > 0)
						{
//printf("vorbis_synthesis_pcmout=%x\n", result);
							for(i = 0; i < track_map->channels; i++)
							{
								float *output_channel = codec->output[i];
								float *input_channel = pcm[i];
								int k = codec->output_end;

								for(j = 0; j < result; j++)
								{
									output_channel[k++] = input_channel[j];
									if(k >= codec->output_allocated)
										k = 0;
								}
								
								if(i == track_map->channels - 1) 
									codec->output_end = k;
							}
//printf("codec->output_end = %d\n", codec->output_end);

							codec->output_position += result;
							codec->output_size += result;
							codec->chunk_samples += result;
							if(codec->output_size > codec->output_allocated)
								codec->output_size = codec->output_allocated;
							vorbis_synthesis_read(&codec->dec_vd, result);
						}
					}
//printf("decode 11\n");
				}

// Reset end of page so it isn't interpreted as an end of chunk
				eos = 0;
			}
		}


// Next chunk
		if(eos)
		{
//printf("decode 12 got=%x\n", codec->chunk_samples);
			have_chunk = 0;
		}
	}


// Fill silence
	while(codec->output_position < end_position)
	{
		for(i = 0; i < track_map->channels; i++)
			codec->output[i][codec->output_end] = 0;
		
		codec->output_end++;
		if(codec->output_end >= codec->output_allocated)
			codec->output_end = 0;
		codec->output_position++;
	}
//printf("decode 15\n");


//printf("decode 2 codec->output_position=%lld codec->output_end=%d codec->output_size=%d\n", 
//	codec->output_position, codec->output_end, codec->output_size);

	current_position = track_map->current_position;
	i = codec->output_end - (codec->output_position - current_position);
	j = 0;
	while(i < 0) i += codec->output_allocated;
	pcm = codec->output[channel];

	if(output_i)
	{
		for( ; j < samples; j++)
		{
			int sample = pcm[i] * 32767;
			CLAMP(sample, -32768, 32767);
			output_i[j] = sample;

			i++;
			if(i >= codec->output_allocated) i = 0;
		}
	}
	else
	if(output_f)
	{
		for( ; j < samples; j++)
		{
			output_f[j] = pcm[i];
			i++;
			if(i >= codec->output_allocated) i = 0;
		}
	}
//printf("decode 16\n");

	return 0;
}
Exemple #28
0
int
main (int argc, char **argv)
{
  int indexing, ch;
  FILE *in;
  ogg_sync_state    oy;
  ogg_page          og;
  ogg_stream_state  os;
  
  indexing = 0;
  
  while ((ch = getopt(argc, argv, "io:")) != -1) 
  {
    switch (ch) 
    {
      case 'i':
        indexing = 1;
        break;

      case 'o':
        break;

      case '?':
      default:
        usage();
    }
  }

  argc -= optind;
  argv += optind;
  
  if (argc == 0)
  {
    usage ();
    return 1;
  }
  
  in = fopen (argv[0], "rb");
  if (in == NULL)
  {
    perror ("error opening input");
    return -1;
  }

  /* initialise ogg_sync_state */
  ogg_sync_init (&oy);
  
  /* process all the headers of the Ogg container */
  while (1)
  {
    int ret = buffer_data (in, &oy);
    if (ret == 0) break;
    while (ogg_sync_pageout (&oy, &og) > 0)
    {
      ogg_packet        op;
      int               got_packet;

      ogg_stream_init (&os, ogg_page_serialno (&og));
      ogg_stream_pagein (&os, &og);
      if ((got_packet = ogg_stream_packetout (&os, &op)))
      {
      }
    }
  }

  fclose (in);
  
  return 0;
}
Exemple #29
0
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");
}
Exemple #30
0
static int spx_decode (void *prv_data, char *sound_buf, int nbytes,
		struct sound_params *sound_params)
{
	struct spx_data *data = (struct spx_data *)prv_data;
  	int bytes_requested = nbytes;
	int16_t *out = (int16_t *)sound_buf;

	sound_params->channels = data->nchannels;
	sound_params->rate = data->rate;
	sound_params->fmt = SFMT_S16 | SFMT_NE;

	while (nbytes) {
		int j;

		/* First see if there is anything left in the output buffer and
		 * empty it out */
		if (data->output_left > 0) {
			int to_copy = nbytes / sizeof(int16_t);

			to_copy = MIN(data->output_left, to_copy);

			memcpy (out, data->output + data->output_start,
					to_copy * sizeof(int16_t));

			out += to_copy;
			data->output_start += to_copy;
			data->output_left -= to_copy;

			nbytes -= to_copy * sizeof(int16_t);
		}
		else if (ogg_stream_packetout (&data->os, &data->op) == 1) {
			int16_t *temp_output = data->output;

			/* Decode some more samples */

			/* Copy Ogg packet to Speex bitstream */
			speex_bits_read_from (&data->bits,
					(char*)data->op.packet, data->op.bytes);

			for (j = 0; j < data->frames_per_packet; j++) {

				/* Decode frame */
				speex_decode_int (data->st, &data->bits,
						temp_output);
				if (data->nchannels == 2)
					speex_decode_stereo_int (temp_output,
							data->frame_size,
							&data->stereo);

				speex_decoder_ctl (data->st, SPEEX_GET_BITRATE,
						&data->bitrate);
				/*data->samples_decoded += data->frame_size;*/

				temp_output += data->frame_size *
					data->nchannels;
			}

			/*logit ("Read %d bytes from page", data->frame_size *
					data->nchannels *
					data->frames_per_packet);*/

			data->output_start = 0;
			data->output_left = data->frame_size *
				data->nchannels * data->frames_per_packet;
		}
		else if (ogg_sync_pageout(&data->oy, &data->og) == 1) {

			/* Read in another ogg page */
			ogg_stream_pagein (&data->os, &data->og);
			debug ("Granulepos: %"PRId64, ogg_page_granulepos(&data->og));

		}
		else if (!io_eof(data->stream)) {
			/* Finally, pull in some more data and try again on the next pass */
			get_more_data (data);
		}
		else
			break;
	}

	return bytes_requested - nbytes;
}