static int Fieldcopy(void *dest, const void *src, size_t count, int rows, int dst_pitch, int src_pitch) { unsigned char* pDest = (unsigned char*) dest; unsigned char* pSrc = (unsigned char*) src; int i; for (i=0; i < rows; i++) { xine_fast_memcpy(pDest, pSrc, count); pSrc += src_pitch; pDest += dst_pitch; } return 0; }
static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { mad_decoder_t *this = (mad_decoder_t *) this_gen; int bytes_in_buffer_at_pts; lprintf ("decode data, size: %d, decoder_flags: %d\n", buf->size, buf->decoder_flags); if (buf->size>(INPUT_BUF_SIZE-this->bytes_in_buffer)) { xprintf (this->xstream->xine, XINE_VERBOSITY_DEBUG, "libmad: ALERT input buffer too small (%d bytes, %d avail)!\n", buf->size, INPUT_BUF_SIZE-this->bytes_in_buffer); buf->size = INPUT_BUF_SIZE-this->bytes_in_buffer; } if ((buf->decoder_flags & BUF_FLAG_HEADER) == 0) { /* reset decoder on leaving preview mode */ if ((buf->decoder_flags & BUF_FLAG_PREVIEW) == 0) { if (this->preview_mode) { mad_reset (this_gen); } } else { this->preview_mode = 1; } bytes_in_buffer_at_pts = this->bytes_in_buffer; xine_fast_memcpy (&this->buffer[this->bytes_in_buffer], buf->content, buf->size); this->bytes_in_buffer += buf->size; /* printf ("libmad: decode data - doing it\n"); */ mad_stream_buffer (&this->stream, this->buffer, this->bytes_in_buffer); if (this->bytes_in_buffer < MAD_MIN_SIZE && buf->pts == 0) return; if (!this->needs_more_data) { this->pts = buf->pts; if (buf->decoder_flags & BUF_FLAG_AUDIO_PADDING) { this->start_padding = buf->decoder_info[1]; this->end_padding = buf->decoder_info[2]; } else { this->start_padding = 0; this->end_padding = 0; } } while (1) { if (mad_frame_decode (&this->frame, &this->stream) != 0) { if (this->stream.next_frame) { int num_bytes = this->buffer + this->bytes_in_buffer - this->stream.next_frame; /* printf("libmad: MAD_ERROR_BUFLEN\n"); */ memmove(this->buffer, this->stream.next_frame, num_bytes); this->bytes_in_buffer = num_bytes; } switch (this->stream.error) { case MAD_ERROR_BUFLEN: /* libmad wants more data */ this->needs_more_data = 1; return; default: lprintf ("error 0x%04X, mad_stream_buffer %d bytes\n", this->stream.error, this->bytes_in_buffer); mad_stream_buffer (&this->stream, this->buffer, this->bytes_in_buffer); } } else { int mode = (this->frame.header.mode == MAD_MODE_SINGLE_CHANNEL) ? AO_CAP_MODE_MONO : AO_CAP_MODE_STEREO; if (!this->output_open || (this->output_sampling_rate != this->frame.header.samplerate) || (this->output_mode != mode)) { lprintf ("audio sample rate %d mode %08x\n", this->frame.header.samplerate, mode); /* the mpeg audio demuxer can set audio bitrate */ if (! _x_stream_info_get(this->xstream, XINE_STREAM_INFO_AUDIO_BITRATE)) { _x_stream_info_set(this->xstream, XINE_STREAM_INFO_AUDIO_BITRATE, this->frame.header.bitrate); } /* the mpeg audio demuxer can set this meta info */ if (! _x_meta_info_get(this->xstream, XINE_META_INFO_AUDIOCODEC)) { switch (this->frame.header.layer) { case MAD_LAYER_I: _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, "MPEG audio layer 1 (lib: MAD)"); break; case MAD_LAYER_II: _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, "MPEG audio layer 2 (lib: MAD)"); break; case MAD_LAYER_III: _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, "MPEG audio layer 3 (lib: MAD)"); break; default: _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, "MPEG audio (lib: MAD)"); } } if (this->output_open) { this->xstream->audio_out->close (this->xstream->audio_out, this->xstream); this->output_open = 0; } if (!this->output_open) { this->output_open = (this->xstream->audio_out->open) (this->xstream->audio_out, this->xstream, 16, this->frame.header.samplerate, mode) ; } if (!this->output_open) { return; } this->output_sampling_rate = this->frame.header.samplerate; this->output_mode = mode; } mad_synth_frame (&this->synth, &this->frame); if ( (buf->decoder_flags & BUF_FLAG_PREVIEW) == 0 ) { unsigned int nchannels, nsamples; mad_fixed_t const *left_ch, *right_ch; struct mad_pcm *pcm = &this->synth.pcm; audio_buffer_t *audio_buffer; uint16_t *output; int bitrate; int pts_offset; audio_buffer = this->xstream->audio_out->get_buffer (this->xstream->audio_out); output = audio_buffer->mem; nchannels = pcm->channels; nsamples = pcm->length; left_ch = pcm->samples[0]; right_ch = pcm->samples[1]; /* padding */ if (this->start_padding || this->end_padding) { /* check padding validity */ if (nsamples < (this->start_padding + this->end_padding)) { lprintf("invalid padding data"); this->start_padding = 0; this->end_padding = 0; } lprintf("nsamples=%d, start_padding=%d, end_padding=%d\n", nsamples, this->start_padding, this->end_padding); nsamples -= this->start_padding + this->end_padding; left_ch += this->start_padding; right_ch += this->start_padding; } audio_buffer->num_frames = nsamples; audio_buffer->vpts = this->pts; while (nsamples--) { /* output sample(s) in 16-bit signed little-endian PCM */ *output++ = scale(*left_ch++); if (nchannels == 2) *output++ = scale(*right_ch++); } audio_buffer->num_frames = pcm->length; /* pts computing */ if (this->frame.header.bitrate > 0) { bitrate = this->frame.header.bitrate; } else { bitrate = _x_stream_info_get(this->xstream, XINE_STREAM_INFO_AUDIO_BITRATE); lprintf("offset %d bps\n", bitrate); } audio_buffer->vpts = buf->pts; if (audio_buffer->vpts && (bitrate > 0)) { pts_offset = (bytes_in_buffer_at_pts * 8 * 90) / (bitrate / 1000); lprintf("pts: %"PRId64", offset: %d pts, %d bytes\n", buf->pts, pts_offset, bytes_in_buffer_at_pts); if (audio_buffer->vpts < pts_offset) pts_offset = audio_buffer->vpts; audio_buffer->vpts -= pts_offset; } this->xstream->audio_out->put_buffer (this->xstream->audio_out, audio_buffer, this->xstream); this->pts = buf->pts; buf->pts = 0; if (buf->decoder_flags & BUF_FLAG_AUDIO_PADDING) { this->start_padding = buf->decoder_info[1]; this->end_padding = buf->decoder_info[2]; buf->decoder_info[1] = 0; buf->decoder_info[2] = 0; } else { this->start_padding = 0; this->end_padding = 0; } } lprintf ("decode worked\n"); } } } }
static void nsf_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { nsf_decoder_t *this = (nsf_decoder_t *) this_gen; audio_buffer_t *audio_buffer; if (buf->decoder_flags & BUF_FLAG_HEADER) { /* When the engine sends a BUF_FLAG_HEADER flag, it is time to initialize * the decoder. The buffer element type has 4 decoder_info fields, * 0..3. Field 1 is the sample rate. Field 2 is the bits/sample. Field * 3 is the number of channels. */ this->sample_rate = buf->decoder_info[1]; this->bits_per_sample = buf->decoder_info[2]; this->channels = buf->decoder_info[3]; /* take this opportunity to initialize stream/meta information */ this->stream->meta_info[XINE_META_INFO_AUDIOCODEC] = strdup("NES Music (Nosefart)"); this->song_number = buf->content[4]; /* allocate a buffer for the file */ this->nsf_size = BE_32(&buf->content[0]); this->nsf_file = xine_xmalloc(this->nsf_size); this->nsf_index = 0; /* peform any other required initialization */ this->last_pts = -1; this->iteration = 0; return; } /* accumulate chunks from the NSF file until whole file is received */ if (this->nsf_index < this->nsf_size) { xine_fast_memcpy(&this->nsf_file[this->nsf_index], buf->content, buf->size); this->nsf_index += buf->size; if (this->nsf_index == this->nsf_size) { /* file has been received, proceed to initialize engine */ nsf_init(); this->nsf = nsf_load(NULL, this->nsf_file, this->nsf_size); if (!this->nsf) { printf ("nsf: could not initialize NSF\n"); /* make the decoder return on every subsequent buffer */ this->nsf_index = 0; } this->nsf->current_song = this->song_number; nsf_playtrack(this->nsf, this->nsf->current_song, this->sample_rate, this->bits_per_sample, this->channels); } return; } /* if the audio output is not open yet, open the audio output */ if (!this->output_open) { this->output_open = this->stream->audio_out->open( this->stream->audio_out, this->stream, this->bits_per_sample, this->sample_rate, (this->channels == 2) ? AO_CAP_MODE_STEREO : AO_CAP_MODE_MONO); } /* if the audio still isn't open, do not go any further with the decode */ if (!this->output_open) return; /* check if a song change was requested */ if (buf->decoder_info[1]) { this->nsf->current_song = buf->decoder_info[1]; nsf_playtrack(this->nsf, this->nsf->current_song, this->sample_rate, this->bits_per_sample, this->channels); } /* time to decode a frame */ if (this->last_pts != -1) { /* process a frame */ nsf_frame(this->nsf); /* get an audio buffer */ audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); if (audio_buffer->mem_size == 0) { printf ("nsf: Help! Allocated audio buffer with nothing in it!\n"); return; } apu_process(audio_buffer->mem, this->sample_rate / this->nsf->playback_rate); audio_buffer->vpts = buf->pts; audio_buffer->num_frames = this->sample_rate / this->nsf->playback_rate; this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); } this->last_pts = buf->pts; }
static void rgb_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { rgb_decoder_t *this = (rgb_decoder_t *) this_gen; xine_bmiheader *bih; palette_entry_t *palette; int i; int pixel_ptr, row_ptr; int palette_index; int buf_ptr; unsigned int packed_pixel; unsigned char r, g, b; int pixels_left; unsigned char pixel_byte = 0; vo_frame_t *img; /* video out frame */ /* a video decoder does not care about this flag (?) */ if (buf->decoder_flags & BUF_FLAG_PREVIEW) return; if ((buf->decoder_flags & BUF_FLAG_SPECIAL) && (buf->decoder_info[1] == BUF_SPECIAL_PALETTE)) { palette = (palette_entry_t *)buf->decoder_info_ptr[2]; for (i = 0; i < buf->decoder_info[2]; i++) { this->yuv_palette[i * 4 + 0] = COMPUTE_Y(palette[i].r, palette[i].g, palette[i].b); this->yuv_palette[i * 4 + 1] = COMPUTE_U(palette[i].r, palette[i].g, palette[i].b); this->yuv_palette[i * 4 + 2] = COMPUTE_V(palette[i].r, palette[i].g, palette[i].b); } } if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { this->video_step = buf->decoder_info[0]; _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); } if (buf->decoder_flags & BUF_FLAG_STDHEADER) { /* need to initialize */ (this->stream->video_out->open) (this->stream->video_out, this->stream); bih = (xine_bmiheader *) buf->content; this->width = (bih->biWidth + 3) & ~0x03; this->height = (bih->biHeight + 3) & ~0x03; if (this->height < 0) { this->upside_down = 1; this->height = -this->height; } else { this->upside_down = 0; } this->ratio = (double)this->width/(double)this->height; this->bit_depth = bih->biBitCount; if (this->bit_depth > 32) this->bit_depth &= 0x1F; /* round this number up in case of 15 */ lprintf("width = %d, height = %d, bit_depth = %d\n", this->width, this->height, this->bit_depth); this->bytes_per_pixel = (this->bit_depth + 1) / 8; free (this->buf); /* minimal buffer size */ this->bufsize = this->width * this->height * this->bytes_per_pixel; this->buf = calloc(1, this->bufsize); this->size = 0; init_yuv_planes(&this->yuv_planes, this->width, this->height); (this->stream->video_out->open) (this->stream->video_out, this->stream); this->decoder_ok = 1; /* load the stream/meta info */ _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "Raw RGB"); return; } else if (this->decoder_ok) { if (this->size + buf->size > this->bufsize) { this->bufsize = this->size + 2 * buf->size; this->buf = realloc (this->buf, this->bufsize); } xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size); this->size += buf->size; if (buf->decoder_flags & BUF_FLAG_FRAME_END) { img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, this->ratio, XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); img->duration = this->video_step; img->pts = buf->pts; img->bad_frame = 0; /* iterate through each row */ buf_ptr = 0; if (this->upside_down) { for (row_ptr = this->yuv_planes.row_width * (this->yuv_planes.row_count - 1); row_ptr >= 0; row_ptr -= this->yuv_planes.row_width) { for (pixel_ptr = 0; pixel_ptr < this->width; pixel_ptr++) { if (this->bytes_per_pixel == 1) { palette_index = this->buf[buf_ptr++]; this->yuv_planes.y[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 0]; this->yuv_planes.u[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 1]; this->yuv_planes.v[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 2]; } else if (this->bytes_per_pixel == 2) { /* ABGR1555 format, little-endian order */ packed_pixel = _X_LE_16(&this->buf[buf_ptr]); buf_ptr += 2; UNPACK_BGR15(packed_pixel, r, g, b); this->yuv_planes.y[row_ptr + pixel_ptr] = COMPUTE_Y(r, g, b); this->yuv_planes.u[row_ptr + pixel_ptr] = COMPUTE_U(r, g, b); this->yuv_planes.v[row_ptr + pixel_ptr] = COMPUTE_V(r, g, b); } else { /* BGR24 or BGRA32 */ b = this->buf[buf_ptr++]; g = this->buf[buf_ptr++]; r = this->buf[buf_ptr++]; /* the next line takes care of 'A' in the 32-bit case */ buf_ptr += this->bytes_per_pixel - 3; this->yuv_planes.y[row_ptr + pixel_ptr] = COMPUTE_Y(r, g, b); this->yuv_planes.u[row_ptr + pixel_ptr] = COMPUTE_U(r, g, b); this->yuv_planes.v[row_ptr + pixel_ptr] = COMPUTE_V(r, g, b); } } } } else { for (row_ptr = 0; row_ptr < this->yuv_planes.row_width * this->yuv_planes.row_count; row_ptr += this->yuv_planes.row_width) { pixels_left = 0; for (pixel_ptr = 0; pixel_ptr < this->width; pixel_ptr++) { if (this->bit_depth == 1) { if (pixels_left == 0) { pixels_left = 8; pixel_byte = *this->buf++; } if (pixel_byte & 0x80) { this->yuv_planes.y[row_ptr + pixel_ptr] = this->yuv_palette[1 * 4 + 0]; this->yuv_planes.u[row_ptr + pixel_ptr] = this->yuv_palette[1 * 4 + 1]; this->yuv_planes.v[row_ptr + pixel_ptr] = this->yuv_palette[1 * 4 + 2]; } else { this->yuv_planes.y[row_ptr + pixel_ptr] = this->yuv_palette[0 * 4 + 0]; this->yuv_planes.u[row_ptr + pixel_ptr] = this->yuv_palette[0 * 4 + 1]; this->yuv_planes.v[row_ptr + pixel_ptr] = this->yuv_palette[0 * 4 + 2]; } pixels_left--; pixel_byte <<= 1; } else if (this->bit_depth == 2) { if (pixels_left == 0) { pixels_left = 4; pixel_byte = *this->buf++; } palette_index = (pixel_byte & 0xC0) >> 6; this->yuv_planes.y[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 0]; this->yuv_planes.u[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 1]; this->yuv_planes.v[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 2]; pixels_left--; pixel_byte <<= 2; } else if (this->bit_depth == 4) { if (pixels_left == 0) { pixels_left = 2; pixel_byte = *this->buf++; } palette_index = (pixel_byte & 0xF0) >> 4; this->yuv_planes.y[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 0]; this->yuv_planes.u[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 1]; this->yuv_planes.v[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 2]; pixels_left--; pixel_byte <<= 4; } else if (this->bytes_per_pixel == 1) { palette_index = this->buf[buf_ptr++]; this->yuv_planes.y[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 0]; this->yuv_planes.u[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 1]; this->yuv_planes.v[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 2]; } else if (this->bytes_per_pixel == 2) { /* ARGB1555 format, big-endian order */ packed_pixel = _X_BE_16(&this->buf[buf_ptr]); buf_ptr += 2; UNPACK_RGB15(packed_pixel, r, g, b); this->yuv_planes.y[row_ptr + pixel_ptr] = COMPUTE_Y(r, g, b); this->yuv_planes.u[row_ptr + pixel_ptr] = COMPUTE_U(r, g, b); this->yuv_planes.v[row_ptr + pixel_ptr] = COMPUTE_V(r, g, b); } else { /* RGB24 or ARGB32; the next line takes care of 'A' in the * 32-bit case */ buf_ptr += this->bytes_per_pixel - 3; r = this->buf[buf_ptr++]; g = this->buf[buf_ptr++]; b = this->buf[buf_ptr++]; this->yuv_planes.y[row_ptr + pixel_ptr] = COMPUTE_Y(r, g, b); this->yuv_planes.u[row_ptr + pixel_ptr] = COMPUTE_U(r, g, b); this->yuv_planes.v[row_ptr + pixel_ptr] = COMPUTE_V(r, g, b); } } } }
static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { mad_decoder_t *this = (mad_decoder_t *) this_gen; #ifdef LOG printf ("libmad: decode data, decoder_flags: %d\n", buf->decoder_flags); #endif if (buf->size>(INPUT_BUF_SIZE-this->bytes_in_buffer)) { printf ("libmad: ALERT input buffer too small (%d bytes, %d avail)!\n", buf->size, INPUT_BUF_SIZE-this->bytes_in_buffer); buf->size = INPUT_BUF_SIZE-this->bytes_in_buffer; } if ((buf->decoder_flags & BUF_FLAG_HEADER) == 0) { /* reset decoder on leaving preview mode */ if ((buf->decoder_flags & BUF_FLAG_PREVIEW) == 0) { if (this->preview_mode) { mad_reset (this_gen); } } else { this->preview_mode = 1; } xine_fast_memcpy (&this->buffer[this->bytes_in_buffer], buf->content, buf->size); this->bytes_in_buffer += buf->size; /* printf ("libmad: decode data - doing it\n"); */ mad_stream_buffer (&this->stream, this->buffer, this->bytes_in_buffer); while (1) { if (mad_frame_decode (&this->frame, &this->stream) != 0) { if (this->stream.next_frame) { int num_bytes = this->buffer + this->bytes_in_buffer - this->stream.next_frame; /* printf("libmad: MAD_ERROR_BUFLEN\n"); */ memmove(this->buffer, this->stream.next_frame, num_bytes); this->bytes_in_buffer = num_bytes; } switch (this->stream.error) { case MAD_ERROR_BUFLEN: return; default: mad_stream_buffer (&this->stream, this->buffer, this->bytes_in_buffer); } } else { int mode = (this->frame.header.mode == MAD_MODE_SINGLE_CHANNEL) ? AO_CAP_MODE_MONO : AO_CAP_MODE_STEREO; if (!this->output_open || (this->output_sampling_rate != this->frame.header.samplerate) || (this->output_mode != mode)) { #ifdef LOG printf ("libmad: audio sample rate %d mode %08x\n", this->frame.header.samplerate, mode); #endif this->xstream->stream_info[XINE_STREAM_INFO_AUDIO_BITRATE] = this->frame.header.bitrate; switch (this->frame.header.layer) { case MAD_LAYER_I: this->xstream->meta_info[XINE_META_INFO_AUDIOCODEC] = strdup ("MPEG audio layer 1"); break; case MAD_LAYER_II: this->xstream->meta_info[XINE_META_INFO_AUDIOCODEC] = strdup ("MPEG audio layer 2"); break; case MAD_LAYER_III: this->xstream->meta_info[XINE_META_INFO_AUDIOCODEC] = strdup ("MPEG audio layer 3"); break; default: this->xstream->meta_info[XINE_META_INFO_AUDIOCODEC] = strdup ("MPEG audio"); } if (this->output_open) { this->xstream->audio_out->close (this->xstream->audio_out, this->xstream); this->output_open = 0; } if (!this->output_open) { this->output_open = this->xstream->audio_out->open(this->xstream->audio_out, this->xstream, 16, this->frame.header.samplerate, mode) ; } if (!this->output_open) { return; } this->output_sampling_rate = this->frame.header.samplerate; this->output_mode = mode; } mad_synth_frame (&this->synth, &this->frame); if ( (buf->decoder_flags & BUF_FLAG_PREVIEW) == 0 ) { unsigned int nchannels, nsamples; mad_fixed_t const *left_ch, *right_ch; struct mad_pcm *pcm = &this->synth.pcm; audio_buffer_t *audio_buffer; uint16_t *output; audio_buffer = this->xstream->audio_out->get_buffer (this->xstream->audio_out); output = audio_buffer->mem; nchannels = pcm->channels; nsamples = pcm->length; left_ch = pcm->samples[0]; right_ch = pcm->samples[1]; while (nsamples--) { /* output sample(s) in 16-bit signed little-endian PCM */ *output++ = scale(*left_ch++); if (nchannels == 2) *output++ = scale(*right_ch++); } audio_buffer->num_frames = pcm->length; audio_buffer->vpts = buf->pts; this->xstream->audio_out->put_buffer (this->xstream->audio_out, audio_buffer, this->xstream); buf->pts = 0; } #ifdef LOG printf ("libmad: decode worked\n"); #endif } } } }
static void gsm610_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { gsm610_decoder_t *this = (gsm610_decoder_t *) this_gen; audio_buffer_t *audio_buffer; int in_ptr; if (buf->decoder_flags & BUF_FLAG_STDHEADER) { this->sample_rate = buf->decoder_info[1]; this->buf = calloc(1, AUDIOBUFSIZE); this->bufsize = AUDIOBUFSIZE; this->size = 0; /* stream/meta info */ _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "GSM 6.10"); return; } if (!this->output_open) { this->gsm_state = gsm_create(); this->buf_type = buf->type; this->output_open = (this->stream->audio_out->open) (this->stream->audio_out, this->stream, GSM610_SAMPLE_SIZE, this->sample_rate, AO_CAP_MODE_MONO); } /* if the audio still isn't open, bail */ if (!this->output_open) return; if( this->size + buf->size > this->bufsize ) { this->bufsize = this->size + 2 * buf->size; xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "gsm610: increasing source buffer to %d to avoid overflow.\n", this->bufsize); this->buf = realloc( this->buf, this->bufsize ); } xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size); this->size += buf->size; if (buf->decoder_flags & BUF_FLAG_FRAME_END) { /* time to decode a frame */ int16_t decode_buffer[GSM610_BLOCK_SIZE]; /* handle the Microsoft variant of GSM data */ if (this->buf_type == BUF_AUDIO_MSGSM) { this->gsm_state->wav_fmt = 1; /* the data should line up on a 65-byte boundary */ if ((buf->size % 65) != 0) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "gsm610: received MS GSM block that does not line up\n"); this->size = 0; return; } in_ptr = 0; while (this->size) { gsm_decode(this->gsm_state, &this->buf[in_ptr], decode_buffer); if ((in_ptr % 65) == 0) { in_ptr += 33; this->size -= 33; } else { in_ptr += 32; this->size -= 32; } /* dispatch the decoded audio; assume that the audio buffer will * always contain at least 160 samples */ audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); xine_fast_memcpy(audio_buffer->mem, decode_buffer, GSM610_BLOCK_SIZE * 2); audio_buffer->num_frames = GSM610_BLOCK_SIZE; audio_buffer->vpts = buf->pts; buf->pts = 0; /* only first buffer gets the real pts */ this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); } } else { /* handle the other variant, which consists of 33-byte blocks */ this->gsm_state->wav_fmt = 0; /* the data should line up on a 33-byte boundary */ if ((buf->size % 33) != 0) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "gsm610: received GSM block that does not line up\n"); this->size = 0; return; } in_ptr = 0; while (this->size) { gsm_decode(this->gsm_state, &this->buf[in_ptr], decode_buffer); in_ptr += 33; this->size -= 33; /* dispatch the decoded audio; assume that the audio buffer will * always contain at least 160 samples */ audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); xine_fast_memcpy(audio_buffer->mem, decode_buffer, GSM610_BLOCK_SIZE * 2); audio_buffer->num_frames = GSM610_BLOCK_SIZE; audio_buffer->vpts = buf->pts; buf->pts = 0; /* only first buffer gets the real pts */ this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); } } } }
static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame ) { win32_driver_t *win32_driver = ( win32_driver_t * ) vo_driver; win32_frame_t *win32_frame = ( win32_frame_t * ) vo_frame; /* if the required width, height or format has changed * then recreate the secondary buffer */ if( ( win32_driver->req_format != win32_frame->format ) || ( win32_driver->width != win32_frame->width ) || ( win32_driver->height != win32_frame->height ) ) { CreateSecondary( win32_driver, win32_frame->width, win32_frame->height, win32_frame->format ); } /* determine desired ratio */ win32_driver->ratio = win32_frame->ratio; /* lock our surface to update its contents */ win32_driver->contents = Lock( win32_driver, win32_driver->secondary ); /* surface unavailable, skip frame render */ if( !win32_driver->contents ) { vo_frame->free( vo_frame ); return; } /* if our actual frame format is the native screen * pixel format, we need to convert it */ if( win32_driver->act_format == IMGFMT_NATIVE ) { /* use the software color conversion functions * to rebuild the frame in our native screen * pixel format ... this is slow */ if( win32_driver->req_format == XINE_IMGFMT_YV12 ) { /* convert from yv12 to native * screen pixel format */ #if NEW_YUV win32_driver->yuv2rgb->configure( win32_driver->yuv2rgb, win32_driver->width, win32_driver->height, win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[1], win32_driver->width, win32_driver->height, win32_driver->width * win32_driver->bytespp); #else yuv2rgb_setup( win32_driver->yuv2rgb, win32_driver->width, win32_driver->height, win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[1], win32_driver->width, win32_driver->height, win32_driver->width * win32_driver->bytespp ); #endif win32_driver->yuv2rgb->yuv2rgb_fun( win32_driver->yuv2rgb, win32_driver->contents, win32_frame->vo_frame.base[0], win32_frame->vo_frame.base[1], win32_frame->vo_frame.base[2] ); } if( win32_driver->req_format == XINE_IMGFMT_YUY2 ) { /* convert from yuy2 to native * screen pixel format */ #if NEW_YUV win32_driver->yuv2rgb->configure( win32_driver->yuv2rgb, win32_driver->width, win32_driver->height, win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[0] / 2, win32_driver->width, win32_driver->height, win32_driver->width * win32_driver->bytespp ); #else yuv2rgb_setup( win32_driver->yuv2rgb, win32_driver->width, win32_driver->height, win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[0] / 2, win32_driver->width, win32_driver->height, win32_driver->width * win32_driver->bytespp ); #endif win32_driver->yuv2rgb->yuy22rgb_fun( win32_driver->yuv2rgb, win32_driver->contents, win32_frame->vo_frame.base[0] ); } #if RGB_SUPPORT if( win32_driver->req_format == IMGFMT_RGB ) { /* convert from 24 bit rgb to native * screen pixel format */ /* TODO : rgb2rgb conversion */ } #endif } else { /* the actual format is identical to our * stream format. we just need to copy it */ int line; uint8_t * src; vo_frame_t * frame = vo_frame; uint8_t * dst = (uint8_t *)win32_driver->contents; switch(win32_frame->format) { case XINE_IMGFMT_YV12: src = frame->base[0]; for (line = 0; line < frame->height ; line++){ xine_fast_memcpy( dst, src, frame->width); src += vo_frame->pitches[0]; dst += win32_driver->ddsd.lPitch; } src = frame->base[2]; for (line = 0; line < frame->height/2 ; line++){ xine_fast_memcpy( dst, src, frame->width/2); src += vo_frame->pitches[2]; dst += win32_driver->ddsd.lPitch/2; } src = frame->base[1]; for (line = 0; line < frame->height/2 ; line++){ xine_fast_memcpy( dst, src, frame->width/2); src += vo_frame->pitches[1]; dst += win32_driver->ddsd.lPitch/2; } break; case XINE_IMGFMT_YUY2: default: src = frame->base[0]; for (line = 0; line < frame->height ; line++){ xine_fast_memcpy( dst, src, frame->width*2); src += vo_frame->pitches[0]; dst += win32_driver->ddsd.lPitch; } break; } } /* unlock the surface */ Unlock( win32_driver->secondary ); /* scale, clip and display our frame */ DisplayFrame( win32_driver ); /* tag our frame as displayed */ if((win32_driver->current != NULL) && ((vo_frame_t *)win32_driver->current != vo_frame)) { vo_frame->free(&win32_driver->current->vo_frame); } win32_driver->current = (win32_frame_t *)vo_frame; }
void *xine_memdup0 (const void *src, size_t length) { char *dst = xine_xmalloc (length + 1); dst[length] = 0; return xine_fast_memcpy (dst, src, length); }
void *xine_memdup (const void *src, size_t length) { void *dst = malloc (length); return xine_fast_memcpy (dst, src, length); }
static void fooaudio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { fooaudio_decoder_t *this = (fooaudio_decoder_t *) this_gen; audio_buffer_t *audio_buffer; int i; int64_t samples_to_generate; int samples_to_send; if (buf->decoder_flags & BUF_FLAG_STDHEADER) { /* When the engine sends a BUF_FLAG_HEADER flag, it is time to initialize * the decoder. The buffer element type has 4 decoder_info fields, * 0..3. Field 1 is the sample rate. Field 2 is the bits/sample. Field * 3 is the number of channels. */ this->sample_rate = buf->decoder_info[1]; this->bits_per_sample = buf->decoder_info[2]; this->channels = buf->decoder_info[3]; /* initialize the data accumulation buffer */ this->buf = calloc(1, AUDIOBUFSIZE); this->bufsize = AUDIOBUFSIZE; this->size = 0; /* take this opportunity to initialize stream/meta information */ _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "fooaudio"); /* perform any other required initialization */ this->last_pts = -1; this->iteration = 0; return; } /* if the audio output is not open yet, open the audio output */ #warning: Audio output is hardcoded to mono 16-bit PCM if (!this->output_open) { this->output_open = (this->stream->audio_out->open) ( this->stream->audio_out, this->stream, /* this->bits_per_sample, */ 16, this->sample_rate, /* _x_ao_channels2mode(this->channels));*/ AO_CAP_MODE_MONO); } /* if the audio still isn't open, do not go any further with the decode */ if (!this->output_open) return; /* accumulate the data passed through the buffer element type; increase * the accumulator buffer size as necessary */ if( this->size + buf->size > this->bufsize ) { this->bufsize = this->size + 2 * buf->size; xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "fooaudio: increasing source buffer to %d to avoid overflow.\n", this->bufsize); this->buf = realloc( this->buf, this->bufsize ); } xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size); this->size += buf->size; /* When a buffer element type has the BUF_FLAG_FRAME_END flag set, it is * time to decode the data in the buffer. */ if (buf->decoder_flags & BUF_FLAG_FRAME_END) { /* This is where the real meat of the audio decoder is implemented. * The general strategy is to decode the data in the accumulation buffer * into raw PCM data and then dispatch the PCM to the engine in smaller * buffers. What follows in the inside of this scope is the meat of * this particular audio decoder. */ /* Operation of the fooaudio decoder: * This decoder generates a continuous sine pattern based on the pts * values sent by the xine engine. Two pts values are needed to know * how long to make the audio. Thus, If this is the first frame or * a seek has occurred (indicated by this->last_pts = -1), * log the pts but do not create any audio. * * When a valid pts delta is generated, create n audio samples, where * n is given as: * * n pts delta * ----------- = --------- => n = (pts delta * sample rate) / 90000 * sample rate 90000 * */ if (this->last_pts != -1) { /* no real reason to set this variable to 0 first; I just wanted the * novelty of using all 4 basic arithmetic ops in a row (+ - * /) */ samples_to_generate = 0; samples_to_generate += buf->pts; samples_to_generate -= this->last_pts; samples_to_generate *= this->sample_rate; samples_to_generate /= 90000; /* save the pts now since it will likely be trashed later */ this->last_pts = buf->pts; while (samples_to_generate) { /* get an audio buffer */ audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); if (audio_buffer->mem_size == 0) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "fooaudio: Help! Allocated audio buffer with nothing in it!\n"); return; } /* samples_to_generate is a sample count; mem_size is a byte count */ if (samples_to_generate > audio_buffer->mem_size / 2) samples_to_send = audio_buffer->mem_size / 2; else samples_to_send = samples_to_generate; samples_to_generate -= samples_to_send; #define WAVE_HZ 300 /* fill up the samples in the buffer */ for (i = 0; i < samples_to_send; i++) audio_buffer->mem[i] = (short)(sin(2 * M_PI * this->iteration++ / WAVE_HZ) * 32767); /* final prep for audio buffer dispatch */ audio_buffer->num_frames = samples_to_send; audio_buffer->vpts = buf->pts; buf->pts = 0; /* only first buffer gets the real pts */ this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); } } else { /* log the pts for the next time */ this->last_pts = buf->pts; } /* reset data accumulation buffer */ this->size = 0; } }