Пример #1
0
int main(void)
{
    const unsigned int FrameLen = 36;
    unsigned char *macframe = malloc(FrameLen);  // alloc MAC header until frame body
    
    // fill header with junk, to make this more interesting
    for (unsigned int i = 0; i < FrameLen; i++) {
        macframe[i] = 0xde;
    }
    
    set_proto_version(macframe, 0);
    set_type(macframe, 1);
    set_subtype(macframe, 1);
    set_to_ds(macframe, 1);
    set_from_ds(macframe, 0);
    set_retry(macframe, 0);
    set_more_data(macframe, 0);
    
    print_header(macframe);
    
    printf("Protocol version: %d\n", get_proto_version(macframe));
    printf("Type: %d\n", get_type(macframe));
    printf("Subtype: %d\n", get_subtype(macframe));
    printf("Flags: To DS: %d  From DS: %d  Retry: %d  More Data: %d\n",
            get_to_ds(macframe) != 0, get_from_ds(macframe) != 0,
            get_retry(macframe) != 0, get_more_data(macframe) != 0);
    
    free(macframe);
}
Пример #2
0
static int setup_readahead(ES_p  es)
{
	int err;

	es->read_ahead_len = 0;
	es->read_ahead_posn = 0;

	es->data = NULL;
	es->data_end = NULL;
	es->data_ptr = NULL;

	es->last_packet_posn = 0;
	es->last_packet_es_data_len = 0;

	// Try to get the first chunk of data from the file
	err = get_more_data(es);
	if (err) return err;

	if (es->reading_ES)
	{
		if (es->read_ahead_len < 3)
		{
			fprintf(stderr,"### File only contains %d byte%s\n",
			        es->read_ahead_len,(es->read_ahead_len==1?"":"s"));
			return 1;
		}
	}
	else
	{
		if (es->reader->packet->es_data_len < 3)
		{
			fprintf(stderr,"### File PES packet only contains %d byte%s\n",
			        es->reader->packet->es_data_len,
			        (es->reader->packet->es_data_len==1?"":"s"));
			return 1;
		}
	}

	if (DEBUG)
		printf("File starts %02x %02x %02x\n",es->data[0],es->data[1],es->data[2]);

	// Despite (maybe) reporting the above, we haven't actually read anything
	// yet
	es->prev2_byte = es->prev1_byte = es->cur_byte = 0xFF;
	es->posn_of_next_byte.infile = 0;
	es->posn_of_next_byte.inpacket = 0;

	return 0;
}
Пример #3
0
static spx_int64_t get_next_page(spx_ogg_sync_state *oy,spx_ogg_page *og,
                                 spx_int64_t boundary)
{
    spx_int64_t localoffset = ci->curpos;
    long more;
    long ret;

    if (boundary > 0)
        boundary += ci->curpos;

    while (1) {
        more = spx_ogg_sync_pageseek(oy,og);

        if (more < 0) {
            /* skipped n bytes */
            localoffset-=more;
        } else {
            if (more == 0) {
                /* send more paramedics */
                if(!boundary)return(-1);
                {
                    ret = get_more_data(oy);
                    if (ret == 0)
                        return(-2);

                    if (ret < 0)
                        return(-3);
                }
            } else {
                /* got a page.  Return the offset at the page beginning,
                   advance the internal offset past the page end */

                spx_int64_t ret=localoffset;

                return(ret);
            }
        }
    }
}
Пример #4
0
static int count_time (struct spx_data *data)
{
	ogg_int64_t last_granulepos = 0;

	/* Seek to somewhere near the last page */
	if (io_file_size(data->stream) > 10000) {
		debug ("Seeking near the end");
		if (io_seek(data->stream, -10000, SEEK_END) == -1)
			logit ("Seeking failed, scanning whole file");
		ogg_sync_reset (&data->oy);
	}

	/* Read granulepos from the last packet */
	while (!io_eof(data->stream)) {

		/* Sync to page and read it */
		while (!io_eof(data->stream)) {
			if (ogg_sync_pageout(&data->oy, &data->og) == 1) {
				debug ("Sync");
				break;
			}

			if (!io_eof(data->stream)) {
				debug ("Need more data");
				get_more_data (data);
			}
		}

		/* We have last packet */
		if (io_eof(data->stream))
			break;

		last_granulepos = ogg_page_granulepos (&data->og);
	}

	return last_granulepos / data->rate;
}
Пример #5
0
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    int error = CODEC_ERROR;

    SpeexBits bits;
    int eof = 0;
    spx_ogg_sync_state oy;
    spx_ogg_page og;
    spx_ogg_packet op;
    spx_ogg_stream_state os;
    spx_int64_t page_granule = 0;
    spx_int64_t cur_granule = 0;
    int enh_enabled = 1;
    int nframes = 2;
    int eos = 0;
    SpeexStereoState *stereo;
    int channels = -1;
    int samplerate = ci->id3->frequency;
    int extra_headers = 0;
    int stream_init = 0;
    /* rockbox: comment 'set but unused' variables
    int page_nb_packets;
    */
    int frame_size;
    int packet_count = 0;
    int lookahead;
    int headerssize = 0;
    unsigned long strtoffset = ci->id3->offset;
    void *st = NULL;
    int j = 0;
    intptr_t param;

    memset(&bits, 0, sizeof(bits));
    memset(&oy, 0, sizeof(oy));

    /* Ogg handling still uses mallocs, so reset the malloc buffer per track */
    if (codec_init()) {
        goto exit;
    }

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

    stereo = speex_stereo_state_init();
    spx_ogg_sync_init(&oy);
    spx_ogg_alloc_buffer(&oy,2*CHUNKSIZE);

    codec_set_replaygain(ci->id3);

    eof = 0;
    while (!eof) {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        /*seek (seeks to the page before the position) */
        if (action == CODEC_ACTION_SEEK_TIME) {
            if(samplerate!=0&&packet_count>1){
                LOGF("Speex seek page:%lld,%lld,%ld,%lld,%d\n",
                     ((spx_int64_t)param/1000) *
                     (spx_int64_t)samplerate,
                     page_granule, param,
                     (page_granule/samplerate)*1000, samplerate);

                speex_seek_page_granule(((spx_int64_t)param/1000) *
                                        (spx_int64_t)samplerate,
                                        page_granule, &oy, headerssize);
            }

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

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

        /* Loop for all complete pages we got (most likely only one) */
        while (spx_ogg_sync_pageout(&oy, &og) == 1) {
            int packet_no;
            if (stream_init == 0) {
                spx_ogg_stream_init(&os, spx_ogg_page_serialno(&og));
                stream_init = 1;
            }

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

            page_granule = spx_ogg_page_granulepos(&og);
            /* page_nb_packets = spx_ogg_page_packets(&og); */

            cur_granule = page_granule;

            /* Extract all available packets */
            packet_no=0;

            while (!eos && spx_ogg_stream_packetout(&os, &op)==1){
                /* If first packet, process as Speex header */
                if (packet_count==0){
                    st = process_header(&op, enh_enabled, &frame_size,
                                         &samplerate, &nframes, &channels,
                                         stereo, &extra_headers);

                    speex_decoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead);
                    if (!nframes)
                        nframes=1;

                    if (!st){
                        goto done;
                    }

                    ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
                    ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
                    if (channels == 2) {
                        ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
                    } else if (channels == 1) {
                        ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
                    }

                    /* Speex header in its own page, add the whole page
                       headersize */
                    headerssize += og.header_len+og.body_len;

                } else if (packet_count<=1+extra_headers){
                    /* add packet to headersize */
                    headerssize += op.bytes;

                    /* Ignore extra headers */
                } else {
                    if (packet_count <= 2+extra_headers) {
                        if (strtoffset) {
                            ci->seek_buffer(strtoffset);
                            spx_ogg_sync_reset(&oy);
                            packet_count++;
                            goto next_page;
                        }
                    }
                    packet_no++;

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

                    /* Set Speex bitstream to point to Ogg packet */
                    speex_bits_set_bit_buffer(&bits, (char *)op.packet,
                                                     op.bytes);
                    for (j = 0; j != nframes; j++){
                        int ret;

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

                        if (ret == -1)
                            break;

                        if (ret == -2)
                            break;

                        if (speex_bits_remaining(&bits) < 0)
                            break;

                        if (channels == 2)
                            speex_decode_stereo_int(output, frame_size, stereo);

                        if (frame_size > 0) {
                            spx_int16_t *frame_start = output + lookahead;

                            if (channels == 2)
                                frame_start += lookahead;
                            ci->pcmbuf_insert(frame_start, NULL,
                                              frame_size - lookahead);
                            lookahead = 0;
                            /* 2 bytes/sample */
                            cur_granule += frame_size / 2;

                            ci->set_offset((long) ci->curpos);

                            ci->set_elapsed((samplerate == 0) ? 0 :
                                             cur_granule * 1000 / samplerate);
                         }
                    }
                }
                packet_count++;
            }
        }
    }

    error = CODEC_OK;
done:
    /* Clean things up for the next track */
    speex_bits_destroy(&bits);

    if (st)
        speex_decoder_destroy(st);

    if (stream_init)
       spx_ogg_stream_destroy(&os);

    spx_ogg_sync_destroy(&oy);

exit:
    return error;
}
Пример #6
0
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    int error = CODEC_ERROR;
    intptr_t param;
    ogg_sync_state oy;
    ogg_page og;
    ogg_packet op;
    ogg_stream_state os;
    int64_t page_granule = 0;
    int stream_init = 0;
    int sample_rate = 48000;
    OpusDecoder *st = NULL;
    OpusHeader header;
    int ret;
    unsigned long strtoffset = ci->id3->offset;
    int skip = 0;
    int64_t seek_target;
    uint64_t granule_pos;

    ogg_malloc_init();

    global_stack = 0;

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

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

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

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

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

        if (action == CODEC_ACTION_HALT)
            break;

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

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

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

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

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

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

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

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

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

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

                    codec_set_replaygain(ci->id3);

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

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

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

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

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

                    if (ret > 0) {
                        if (skip > 0) {
                            if (ret <= skip) {
                                /* entire output buffer is skipped */
                                skip -= ret;
                                ret = 0;
                            } else {
                                /* part of output buffer is played */
                                ret -= skip;
                                ci->pcmbuf_insert(&output[skip * header.channels], NULL, ret);
                                skip = 0;
                            }
                        } else {
                            /* entire buffer is played */
                            ci->pcmbuf_insert(output, NULL, ret);
                        }
                        granule_pos += ret;
                    } else {
                        if (ret < 0) {
                            LOGF("opus_decode failed %d", ret);
                            goto done;
                        }
                        break;
                    }
                }
            }
        }
    }
    LOGF("Returned OK");
    error = CODEC_OK;
done:
    ogg_malloc_destroy();
    return error;
}
Пример #7
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;
}
Пример #8
0
static int spx_seek (void *prv_data, int sec)
{
	struct spx_data *data = (struct spx_data *)prv_data;
	off_t begin = 0, end, old_pos;

	assert (sec >= 0);

	end = io_file_size (data->stream);
	if (end == -1)
		return -1;
	old_pos = io_tell (data->stream);

	debug ("Seek request to %ds", sec);

	while (1) {
		off_t middle = (end + begin) / 2;
		ogg_int64_t granule_pos;
		int position_seconds;

		debug ("Seek to %"PRId64, middle);

		if (io_seek(data->stream, middle, SEEK_SET) == -1) {
			io_seek (data->stream, old_pos, SEEK_SET);
			ogg_stream_reset (&data->os);
			ogg_sync_reset (&data->oy);
			return -1;
		}

		debug ("Syncing...");

		/* Sync to page and read it */
		ogg_sync_reset (&data->oy);
		while (!io_eof(data->stream)) {
			if (ogg_sync_pageout(&data->oy, &data->og) == 1) {
				debug ("Sync");
				break;
			}

			if (!io_eof(data->stream)) {
				debug ("Need more data");
				get_more_data (data);
			}
		}

		if (io_eof(data->stream)) {
			debug ("EOF when syncing");
			return -1;
		}

		granule_pos = ogg_page_granulepos(&data->og);
		position_seconds = granule_pos / data->rate;

		debug ("We are at %ds", position_seconds);

		if (position_seconds == sec) {
			ogg_stream_pagein (&data->os, &data->og);
			debug ("We have it at granulepos %"PRId64, granule_pos);
			break;
		}
		else if (sec < position_seconds) {
			end = middle;
			debug ("going back");
		}
		else {
			begin = middle;
			debug ("going forward");
		}

		debug ("begin - end %"PRId64" - %"PRId64, begin, end);

		if (end - begin <= 200) {

			/* Can't find the exact position. */
			sec = position_seconds;
			break;
		}
	}

	ogg_sync_reset (&data->oy);
	ogg_stream_reset (&data->os);

	return sec;
}