Diffstat (limited to 'core/multimedia/opieplayer/libmpeg3/video') (more/less context) (ignore whitespace changes)
23 files changed, 7920 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/libmpeg3/video/Makefile b/core/multimedia/opieplayer/libmpeg3/video/Makefile new file mode 100644 index 0000000..46d8407 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/Makefile @@ -0,0 +1,32 @@ +include ../global_config +export CFLAGS +export CFLAGS_lessopt + +OBJS = \ + getpicture.o \ + headers.o \ + idct.o \ + macroblocks.o \ + mmxtest.o \ + motion.o \ + mpeg3video.o \ + output.o \ + reconstruct.o \ + seek.o \ + slice.o \ + vlc.o + + +all: $(OBJS) $(MMXOBJS2) + +.c.o: + $(CC) -c `./c_flags` -o $@ $< + +.s.o: + $(NASM) -f elf $*.s + +.S.o: + $(CC) -S `./c_flags` $*.S + +clean: + rm -f *.o diff --git a/core/multimedia/opieplayer/libmpeg3/video/c_flags b/core/multimedia/opieplayer/libmpeg3/video/c_flags new file mode 100755 index 0000000..d7943d0 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/c_flags @@ -0,0 +1 @@ +echo $CFLAGS diff --git a/core/multimedia/opieplayer/libmpeg3/video/getpicture.c b/core/multimedia/opieplayer/libmpeg3/video/getpicture.c new file mode 100644 index 0000000..4f67484 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/getpicture.c @@ -0,0 +1,767 @@ +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" +#include "vlc.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int mpeg3video_get_cbp(mpeg3_slice_t *slice) +{ + int code; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + + if((code = mpeg3slice_showbits9(slice_buffer)) >= 128) + { + code >>= 4; + mpeg3slice_flushbits(slice_buffer, mpeg3_CBPtab0[code].len); + return mpeg3_CBPtab0[code].val; + } + + if(code >= 8) + { + code >>= 1; + mpeg3slice_flushbits(slice_buffer, mpeg3_CBPtab1[code].len); + return mpeg3_CBPtab1[code].val; + } + + if(code < 1) + { +/* fprintf(stderr,"mpeg3video_get_cbp: invalid coded_block_pattern code\n"); */ + slice->fault = 1; + return 0; + } + + mpeg3slice_flushbits(slice_buffer, mpeg3_CBPtab2[code].len); + return mpeg3_CBPtab2[code].val; +} + + +/* set block to zero */ +int mpeg3video_clearblock(mpeg3_slice_t *slice, int comp, int size) +{ + slice->sparse[comp] = 1; + +/* Compiler error */ +/* + * for(i = 0; i < size; i++) + * { + * bzero(slice->block[comp] + sizeof(short) * 64 * i, sizeof(short) * 64); + * } + */ + + if(size == 6) + { + bzero(slice->block[comp], sizeof(short) * 64 * 6); + } + else + { +printf("mpeg3video_clearblock size = %d\n", size); + memset(slice->block[comp], 0, sizeof(short) * 64 * size); + } + return 0; +} + +static inline int mpeg3video_getdclum(mpeg3_slice_buffer_t *slice_buffer) +{ + int code, size, val; +/* decode length */ + code = mpeg3slice_showbits5(slice_buffer); + + if(code < 31) + { + size = mpeg3_DClumtab0[code].val; + mpeg3slice_flushbits(slice_buffer, mpeg3_DClumtab0[code].len); + } + else + { + code = mpeg3slice_showbits9(slice_buffer) - 0x1f0; + size = mpeg3_DClumtab1[code].val; + mpeg3slice_flushbits(slice_buffer, mpeg3_DClumtab1[code].len); + } + + if(size == 0) val = 0; + else + { + val = mpeg3slice_getbits(slice_buffer, size); + if((val & (1 << (size - 1))) == 0) val -= (1 << size) - 1; + } + + return val; +} + + +int mpeg3video_getdcchrom(mpeg3_slice_buffer_t *slice_buffer) +{ + int code, size, val; + +/* decode length */ + code = mpeg3slice_showbits5(slice_buffer); + + if(code < 31) + { + size = mpeg3_DCchromtab0[code].val; + mpeg3slice_flushbits(slice_buffer, mpeg3_DCchromtab0[code].len); + } + else + { + code = mpeg3slice_showbits(slice_buffer, 10) - 0x3e0; + size = mpeg3_DCchromtab1[code].val; + mpeg3slice_flushbits(slice_buffer, mpeg3_DCchromtab1[code].len); + } + + if(size == 0) val = 0; + else + { + val = mpeg3slice_getbits(slice_buffer, size); + if((val & (1 << (size - 1))) == 0) val -= (1 << size) - 1; + } + + return val; +} + + +/* decode one intra coded MPEG-1 block */ + +int mpeg3video_getintrablock(mpeg3_slice_t *slice, + mpeg3video_t *video, + int comp, + int dc_dct_pred[]) +{ + int val, i, j, sign; + unsigned int code; + mpeg3_DCTtab_t *tab = 0; + short *bp = slice->block[comp]; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + +/* decode DC coefficients */ + if(comp < 4) + bp[0] = (dc_dct_pred[0] += mpeg3video_getdclum(slice_buffer)) << 3; + else + if(comp == 4) + bp[0] = (dc_dct_pred[1] += mpeg3video_getdcchrom(slice_buffer)) << 3; + else + bp[0] = (dc_dct_pred[2] += mpeg3video_getdcchrom(slice_buffer)) << 3; + +#ifdef HAVE_MMX + if(video->have_mmx) + bp[0] <<= 4; +#endif + + if(slice->fault) return 1; + +/* decode AC coefficients */ + for(i = 1; ; i++) + { + code = mpeg3slice_showbits16(slice_buffer); + if(code >= 16384) + tab = &mpeg3_DCTtabnext[(code >> 12) - 4]; + else + if(code >= 1024) tab = &mpeg3_DCTtab0[(code >> 8) - 4]; + else + if(code >= 512) tab = &mpeg3_DCTtab1[(code >> 6) - 8]; + else + if(code >= 256) tab = &mpeg3_DCTtab2[(code >> 4) - 16]; + else + if(code >= 128) tab = &mpeg3_DCTtab3[(code >> 3) - 16]; + else + if(code >= 64) tab = &mpeg3_DCTtab4[(code >> 2) - 16]; + else + if(code >= 32) tab = &mpeg3_DCTtab5[(code >> 1) - 16]; + else + if(code >= 16) tab = &mpeg3_DCTtab6[code - 16]; + else + { +/* fprintf(stderr, "mpeg3video_getintrablock: invalid Huffman code\n"); */ + slice->fault = 1; + return 1; + } + + mpeg3slice_flushbits(slice_buffer, tab->len); + + if(tab->run == 64) break; /* end_of_block */ + + if(tab->run == 65) + { +/* escape */ + i += mpeg3slice_getbits(slice_buffer, 6); + + if((val = mpeg3slice_getbits(slice_buffer, 8)) == 0) + val = mpeg3slice_getbits(slice_buffer, 8); + else + if(val == 128) + val = mpeg3slice_getbits(slice_buffer, 8) - 256; + else + if(val > 128) + val -= 256; + + if((sign = (val < 0)) != 0) val= -val; + } + else + { + i += tab->run; + val = tab->level; + sign = mpeg3slice_getbit(slice_buffer); + } + + if(i < 64) + j = video->mpeg3_zigzag_scan_table[i]; + else + { + slice->fault = 1; + return 1; + } + + +#ifdef HAVE_MMX + if(video->have_mmx) + { + val = (val * slice->quant_scale * video->intra_quantizer_matrix[j]) << 1; + val = (val - 16) | 16; + } + else +#endif + { + val = (val * slice->quant_scale * video->intra_quantizer_matrix[j]) >> 3; + val = (val - 1) | 1; + } + + bp[j] = sign ? -val : val; + } + + if(j != 0) + { +/* not a sparse matrix ! */ + slice->sparse[comp] = 0; + } + return 0; +} + + +/* decode one non-intra coded MPEG-1 block */ + +int mpeg3video_getinterblock(mpeg3_slice_t *slice, + mpeg3video_t *video, + int comp) +{ + int val, i, j, sign; + unsigned int code; + mpeg3_DCTtab_t *tab; + short *bp = slice->block[comp]; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + +/* decode AC coefficients */ + for(i = 0; ; i++) + { + code = mpeg3slice_showbits16(slice_buffer); + if(code >= 16384) + { + if(i == 0) + tab = &mpeg3_DCTtabfirst[(code >> 12) - 4]; + else + tab = &mpeg3_DCTtabnext[(code >> 12) - 4]; + } + else + if(code >= 1024) tab = &mpeg3_DCTtab0[(code >> 8) - 4]; + else + if(code >= 512) tab = &mpeg3_DCTtab1[(code >> 6) - 8]; + else + if(code >= 256) tab = &mpeg3_DCTtab2[(code >> 4) - 16]; + else + if(code >= 128) tab = &mpeg3_DCTtab3[(code >> 3) - 16]; + else + if(code >= 64) tab = &mpeg3_DCTtab4[(code >> 2) - 16]; + else + if(code >= 32) tab = &mpeg3_DCTtab5[(code >> 1) - 16]; + else + if(code >= 16) tab = &mpeg3_DCTtab6[code - 16]; + else + { +// invalid Huffman code + slice->fault = 1; + return 1; + } + + mpeg3slice_flushbits(slice_buffer, tab->len); + +/* end of block */ + if(tab->run == 64) + break; + + if(tab->run == 65) + { +/* escape */ + i += mpeg3slice_getbits(slice_buffer, 6); + if((val = mpeg3slice_getbits(slice_buffer, 8)) == 0) + val = mpeg3slice_getbits(slice_buffer, 8); + else + if(val == 128) + val = mpeg3slice_getbits(slice_buffer, 8) - 256; + else + if(val > 128) + val -= 256; + + if((sign = (val < 0)) != 0) val = -val; + } + else + { + i += tab->run; + val = tab->level; + sign = mpeg3slice_getbit(slice_buffer); + } + + j = video->mpeg3_zigzag_scan_table[i]; + +#ifdef HAVE_MMX + if(video->have_mmx) + { + val = (((val << 1)+1) * slice->quant_scale * video->non_intra_quantizer_matrix[j]); + val = (val - 16) | 16; + } + else +#endif + { + val = (((val << 1)+1) * slice->quant_scale * video->non_intra_quantizer_matrix[j]) >> 4; + val = (val - 1) | 1; + } + + bp[j] = sign ? -val : val; + } + + if(j != 0) + { +/* not a sparse matrix ! */ + slice->sparse[comp] = 0; + } + return 0; +} + + +/* decode one intra coded MPEG-2 block */ +int mpeg3video_getmpg2intrablock(mpeg3_slice_t *slice, + mpeg3video_t *video, + int comp, + int dc_dct_pred[]) +{ + int val, i, j, sign, nc; + unsigned int code; + mpeg3_DCTtab_t *tab; + short *bp; + int *qmat; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + +/* with data partitioning, data always goes to base layer */ + bp = slice->block[comp]; + + qmat = (comp < 4 || video->chroma_format == CHROMA420) + ? video->intra_quantizer_matrix + : video->chroma_intra_quantizer_matrix; + +/* decode DC coefficients */ + if(comp < 4) + val = (dc_dct_pred[0] += mpeg3video_getdclum(slice_buffer)); + else + if((comp & 1) == 0) + val = (dc_dct_pred[1] += mpeg3video_getdcchrom(slice_buffer)); + else + val = (dc_dct_pred[2] += mpeg3video_getdcchrom(slice_buffer)); + + if(slice->fault) return 1; +#ifdef HAVE_MMX + if(video->have_mmx) + bp[0] = val << (7 - video->dc_prec); + else +#endif + bp[0] = val << (3 - video->dc_prec); + + nc = 0; + +/* decode AC coefficients */ + for(i = 1; ; i++) + { + code = mpeg3slice_showbits16(slice_buffer); + + if(code >= 16384 && !video->intravlc) + tab = &mpeg3_DCTtabnext[(code >> 12) - 4]; + else + if(code >= 1024) + { + if(video->intravlc) + tab = &mpeg3_DCTtab0a[(code >> 8) - 4]; + else + tab = &mpeg3_DCTtab0[(code >> 8) - 4]; + } + else + if(code >= 512) + { + if(video->intravlc) + tab = &mpeg3_DCTtab1a[(code >> 6) - 8]; + else + tab = &mpeg3_DCTtab1[(code >> 6) - 8]; + } + else + if(code >= 256) tab = &mpeg3_DCTtab2[(code >> 4) - 16]; + else + if(code >= 128) tab = &mpeg3_DCTtab3[(code >> 3) - 16]; + else + if(code >= 64) tab = &mpeg3_DCTtab4[(code >> 2) - 16]; + else + if(code >= 32) tab = &mpeg3_DCTtab5[(code >> 1) - 16]; + else + if(code >= 16) tab = &mpeg3_DCTtab6[code - 16]; + else + { +/* fprintf(stderr,"mpeg3video_getmpg2intrablock: invalid Huffman code\n"); */ + slice->fault = 1; + return 1; + } + + mpeg3slice_flushbits(slice_buffer, tab->len); + +/* end_of_block */ + if(tab->run == 64) + break; + + if(tab->run == 65) + { +/* escape */ + i += mpeg3slice_getbits(slice_buffer, 6); + + val = mpeg3slice_getbits(slice_buffer, 12); + if((val & 2047) == 0) + { +// invalid signed_level (escape) + slice->fault = 1; + return 1; + } + if((sign = (val >= 2048)) != 0) val = 4096 - val; + } + else + { + i += tab->run; + val = tab->level; + sign = mpeg3slice_getbit(slice_buffer); + } + + j = (video->altscan ? video->mpeg3_alternate_scan_table : video->mpeg3_zigzag_scan_table)[i]; + +#ifdef HAVE_MMX + if(video->have_mmx) + val = (val * slice->quant_scale * qmat[j]); + else +#endif + val = (val * slice->quant_scale * qmat[j]) >> 4; + + bp[j] = sign ? -val : val; + nc++; + } + + if(j != 0) + { +/* not a sparse matrix ! */ + slice->sparse[comp] = 0; + } + return 1; +} + + +/* decode one non-intra coded MPEG-2 block */ + +int mpeg3video_getmpg2interblock(mpeg3_slice_t *slice, + mpeg3video_t *video, + int comp) +{ + int val, i, j, sign, nc; + unsigned int code; + mpeg3_DCTtab_t *tab; + short *bp; + int *qmat; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + +/* with data partitioning, data always goes to base layer */ + bp = slice->block[comp]; + + qmat = (comp < 4 || video->chroma_format == CHROMA420) + ? video->non_intra_quantizer_matrix + : video->chroma_non_intra_quantizer_matrix; + + nc = 0; + +/* decode AC coefficients */ + for(i = 0; ; i++) + { + code = mpeg3slice_showbits16(slice_buffer); + if(code >= 16384) + { + if(i == 0) tab = &mpeg3_DCTtabfirst[(code >> 12) - 4]; + else tab = &mpeg3_DCTtabnext[(code >> 12) - 4]; + } + else + if(code >= 1024) tab = &mpeg3_DCTtab0[(code >> 8) - 4]; + else + if(code >= 512) tab = &mpeg3_DCTtab1[(code >> 6) - 8]; + else + if(code >= 256) tab = &mpeg3_DCTtab2[(code >> 4) - 16]; + else + if(code >= 128) tab = &mpeg3_DCTtab3[(code >> 3) - 16]; + else + if(code >= 64) tab = &mpeg3_DCTtab4[(code >> 2) - 16]; + else + if(code >= 32) tab = &mpeg3_DCTtab5[(code >> 1) - 16]; + else + if(code >= 16) tab = &mpeg3_DCTtab6[code - 16]; + else + { +// invalid Huffman code + slice->fault = 1; + return 1; + } + + mpeg3slice_flushbits(slice_buffer, tab->len); + +/* end_of_block */ + if(tab->run == 64) + break; + + if(tab->run == 65) + { +/* escape */ + i += mpeg3slice_getbits(slice_buffer, 6); + val = mpeg3slice_getbits(slice_buffer, 12); + if((val & 2047) == 0) + { +/* fprintf(stderr, "mpeg3video_getmpg2interblock: invalid signed_level (escape)\n"); */ + slice->fault = 1; + return 1; + } + if((sign = (val >= 2048)) != 0) val = 4096 - val; + } + else + { + i += tab->run; + val = tab->level; + sign = mpeg3slice_getbit(slice_buffer); + } + + j = (video->altscan ? video->mpeg3_alternate_scan_table : video->mpeg3_zigzag_scan_table)[i]; + +#ifdef HAVE_MMX + if(video->have_mmx) + val = (((val << 1)+1) * slice->quant_scale * qmat[j]) >> 1; + else +#endif + val = (((val << 1)+1) * slice->quant_scale * qmat[j]) >> 5; + + bp[j] = sign ? (-val) : val ; + nc++; + } + + if(j != 0) + { + slice->sparse[comp] = 0; + } + return 0; +} + + +/* decode all macroblocks of the current picture */ +int mpeg3video_get_macroblocks(mpeg3video_t *video, int framenum) +{ + unsigned int code; + mpeg3_slice_buffer_t *slice_buffer; /* Buffer being loaded */ + int i; + int current_buffer; + mpeg3_bits_t *vstream = video->vstream; + +/* Load every slice into a buffer array */ + video->total_slice_buffers = 0; + current_buffer = 0; + while(!mpeg3bits_eof(vstream) && + mpeg3bits_showbits32_noptr(vstream) >= MPEG3_SLICE_MIN_START && + mpeg3bits_showbits32_noptr(vstream) <= MPEG3_SLICE_MAX_START) + { +/* Initialize the buffer */ + if(current_buffer >= video->slice_buffers_initialized) + mpeg3_new_slice_buffer(&(video->slice_buffers[video->slice_buffers_initialized++])); + slice_buffer = &(video->slice_buffers[current_buffer]); + slice_buffer->buffer_size = 0; + slice_buffer->current_position = 0; + slice_buffer->bits_size = 0; + slice_buffer->done = 0; + +/* Read the slice into the buffer including the slice start code */ + do + { +/* Expand buffer */ + if(slice_buffer->buffer_allocation <= slice_buffer->buffer_size) + mpeg3_expand_slice_buffer(slice_buffer); + +/* Load 1 char into buffer */ + slice_buffer->data[slice_buffer->buffer_size++] = mpeg3bits_getbyte_noptr(vstream); + }while(!mpeg3bits_eof(vstream) && + mpeg3bits_showbits24_noptr(vstream) != MPEG3_PACKET_START_CODE_PREFIX); + +/* Pad the buffer to get the last macroblock */ + if(slice_buffer->buffer_allocation <= slice_buffer->buffer_size + 4) + mpeg3_expand_slice_buffer(slice_buffer); + + slice_buffer->data[slice_buffer->buffer_size++] = 0; + slice_buffer->data[slice_buffer->buffer_size++] = 0; + slice_buffer->data[slice_buffer->buffer_size++] = 1; + slice_buffer->data[slice_buffer->buffer_size++] = 0; + slice_buffer->bits_size = 0; + + pthread_mutex_lock(&(slice_buffer->completion_lock)); fflush(stdout); + current_buffer++; + video->total_slice_buffers++; + } + +/* Run the slice decoders */ + if(video->total_slice_buffers > 0) + { + for(i = 0; i < video->total_slice_decoders; i++) + { + if(i == 0 && video->total_slice_decoders > 1) + { + video->slice_decoders[i].current_buffer = 0; + video->slice_decoders[i].buffer_step = 1; + video->slice_decoders[i].last_buffer = (video->total_slice_buffers - 1); + } + else + if(i == 1) + { + video->slice_decoders[i].current_buffer = video->total_slice_buffers - 1; + video->slice_decoders[i].buffer_step = -1; + video->slice_decoders[i].last_buffer = 0; + } + else + { + video->slice_decoders[i].current_buffer = i; + video->slice_decoders[i].buffer_step = 1; + video->slice_decoders[i].last_buffer = video->total_slice_buffers - 1; + } + pthread_mutex_unlock(&(video->slice_decoders[i].input_lock)); + } + } + +/* Wait for the slice decoders to finish */ + if(video->total_slice_buffers > 0) + { + for(i = 0; i < video->total_slice_buffers; i++) + { + pthread_mutex_lock(&(video->slice_buffers[i].completion_lock)); + pthread_mutex_unlock(&(video->slice_buffers[i].completion_lock)); + } + } + return 0; +} + +int mpeg3video_allocate_decoders(mpeg3video_t *video, int decoder_count) +{ + int i; + mpeg3_t *file = video->file; +/* Get the slice decoders */ + if(video->total_slice_decoders != file->cpus) + { + for(i = 0; i < video->total_slice_decoders; i++) + { + mpeg3_delete_slice_decoder(&video->slice_decoders[i]); + } + + for(i = 0; i < file->cpus && i < MPEG3_MAX_CPUS; i++) + { + mpeg3_new_slice_decoder(video, &(video->slice_decoders[i])); + video->slice_decoders[i].thread_number = i; + } + + video->total_slice_decoders = file->cpus; + } + return 0; +} + +/* decode one frame or field picture */ + +int mpeg3video_getpicture(mpeg3video_t *video, int framenum) +{ + int i, result = 0; + mpeg3_t *file = video->file; + + if(video->pict_struct == FRAME_PICTURE && video->secondfield) + { +/* recover from illegal number of field pictures */ + video->secondfield = 0; + } + + if(!video->mpeg2) + { + video->current_repeat = video->repeat_count = 0; + } + + mpeg3video_allocate_decoders(video, file->cpus); + + for(i = 0; i < 3; i++) + { + if(video->pict_type == B_TYPE) + { + video->newframe[i] = video->auxframe[i]; + } + else + { + if(!video->secondfield && !video->current_repeat) + { +/* Swap refframes for I frames */ + unsigned char* tmp = video->oldrefframe[i]; + video->oldrefframe[i] = video->refframe[i]; + video->refframe[i] = tmp; + } + + video->newframe[i] = video->refframe[i]; + } + + if(video->pict_struct == BOTTOM_FIELD) + { +/* Only used if fields are in different pictures */ + video->newframe[i] += (i == 0) ? video->coded_picture_width : video->chrom_width; + } + } + +/* The problem is when a B frame lands on the first repeat and is skipped, */ +/* the second repeat goes for the same bitmap as the skipped repeat, */ +/* so it picks up a frame from 3 frames back. */ +/* The first repeat must consititutively read a B frame if its B frame is going to be */ +/* used in a later repeat. */ + if(!video->current_repeat) + if(!(video->skip_bframes && video->pict_type == B_TYPE) || + (video->repeat_count >= 100 + 100 * video->skip_bframes)) + result = mpeg3video_get_macroblocks(video, framenum); + +/* Set the frame to display */ + video->output_src = 0; + if(framenum > -1 && !result) + { + if(video->pict_struct == FRAME_PICTURE || video->secondfield) + { + if(video->pict_type == B_TYPE) + { + video->output_src = video->auxframe; + } + else + { + video->output_src = video->oldrefframe; + } + } + else + { + mpeg3video_display_second_field(video); + } + } + + if(video->mpeg2) + { + video->current_repeat += 100; + } + + if(video->pict_struct != FRAME_PICTURE) video->secondfield = !video->secondfield; + return result; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/headers.c b/core/multimedia/opieplayer/libmpeg3/video/headers.c new file mode 100644 index 0000000..5274530 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/headers.c @@ -0,0 +1,492 @@ +#include "../mpeg3demux.h" +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" + +#include <stdio.h> +#include <stdlib.h> + +int mpeg3video_getseqhdr(mpeg3video_t *video) +{ + int i; + mpeg3_t *file = video->file; + + int aspect_ratio, picture_rate, vbv_buffer_size; + int constrained_parameters_flag; + int load_intra_quantizer_matrix, load_non_intra_quantizer_matrix; + + video->horizontal_size = mpeg3bits_getbits(video->vstream, 12); + video->vertical_size = mpeg3bits_getbits(video->vstream, 12); + aspect_ratio = mpeg3bits_getbits(video->vstream, 4); + video->framerate_code = mpeg3bits_getbits(video->vstream, 4); + video->bitrate = mpeg3bits_getbits(video->vstream, 18); + mpeg3bits_getbit_noptr(video->vstream); /* marker bit (=1) */ + vbv_buffer_size = mpeg3bits_getbits(video->vstream, 10); + constrained_parameters_flag = mpeg3bits_getbit_noptr(video->vstream); + video->frame_rate = mpeg3_frame_rate_table[video->framerate_code]; + + load_intra_quantizer_matrix = mpeg3bits_getbit_noptr(video->vstream); + if(load_intra_quantizer_matrix) + { + for(i = 0; i < 64; i++) + video->intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = mpeg3bits_getbyte_noptr(video->vstream); + } + else + { + for(i = 0; i < 64; i++) + video->intra_quantizer_matrix[i] = mpeg3_default_intra_quantizer_matrix[i]; + } + + load_non_intra_quantizer_matrix = mpeg3bits_getbit_noptr(video->vstream); + if(load_non_intra_quantizer_matrix) + { + for(i = 0; i < 64; i++) + video->non_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = mpeg3bits_getbyte_noptr(video->vstream); + } + else + { + for(i = 0; i < 64; i++) + video->non_intra_quantizer_matrix[i] = 16; + } + +/* copy luminance to chrominance matrices */ + for(i = 0; i < 64; i++) + { + video->chroma_intra_quantizer_matrix[i] = video->intra_quantizer_matrix[i]; + video->chroma_non_intra_quantizer_matrix[i] = video->non_intra_quantizer_matrix[i]; + } + + return 0; +} + + +/* decode sequence extension */ + +int mpeg3video_sequence_extension(mpeg3video_t *video) +{ + int prof_lev; + int horizontal_size_extension, vertical_size_extension; + int bit_rate_extension, vbv_buffer_size_extension, low_delay; + int frame_rate_extension_n, frame_rate_extension_d; + int pos = 0; + + video->mpeg2 = 1; + video->scalable_mode = SC_NONE; /* unless overwritten by seq. scal. ext. */ + prof_lev = mpeg3bits_getbyte_noptr(video->vstream); + video->prog_seq = mpeg3bits_getbit_noptr(video->vstream); + video->chroma_format = mpeg3bits_getbits(video->vstream, 2); + horizontal_size_extension = mpeg3bits_getbits(video->vstream, 2); + vertical_size_extension = mpeg3bits_getbits(video->vstream, 2); + bit_rate_extension = mpeg3bits_getbits(video->vstream, 12); + mpeg3bits_getbit_noptr(video->vstream); + vbv_buffer_size_extension = mpeg3bits_getbyte_noptr(video->vstream); + low_delay = mpeg3bits_getbit_noptr(video->vstream); + frame_rate_extension_n = mpeg3bits_getbits(video->vstream, 2); + frame_rate_extension_d = mpeg3bits_getbits(video->vstream, 5); + video->horizontal_size = (horizontal_size_extension << 12) | (video->horizontal_size & 0x0fff); + video->vertical_size = (vertical_size_extension << 12) | (video->vertical_size & 0x0fff); +} + + +/* decode sequence display extension */ + +int mpeg3video_sequence_display_extension(mpeg3video_t *video) +{ + int colour_primaries = 0, transfer_characteristics = 0; + int display_horizontal_size, display_vertical_size; + int pos = 0; + int video_format = mpeg3bits_getbits(video->vstream, 3); + int colour_description = mpeg3bits_getbit_noptr(video->vstream); + + if(colour_description) + { + colour_primaries = mpeg3bits_getbyte_noptr(video->vstream); + transfer_characteristics = mpeg3bits_getbyte_noptr(video->vstream); + video->matrix_coefficients = mpeg3bits_getbyte_noptr(video->vstream); + } + + display_horizontal_size = mpeg3bits_getbits(video->vstream, 14); + mpeg3bits_getbit_noptr(video->vstream); + display_vertical_size = mpeg3bits_getbits(video->vstream, 14); +} + + +/* decode quant matrix entension */ + +int mpeg3video_quant_matrix_extension(mpeg3video_t *video) +{ + int i; + int load_intra_quantiser_matrix, load_non_intra_quantiser_matrix; + int load_chroma_intra_quantiser_matrix; + int load_chroma_non_intra_quantiser_matrix; + int pos = 0; + + if((load_intra_quantiser_matrix = mpeg3bits_getbit_noptr(video->vstream)) != 0) + { + for(i = 0; i < 64; i++) + { + video->chroma_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] + = video->intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] + = mpeg3bits_getbyte_noptr(video->vstream); + } + } + + if((load_non_intra_quantiser_matrix = mpeg3bits_getbit_noptr(video->vstream)) != 0) + { + for (i = 0; i < 64; i++) + { + video->chroma_non_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] + = video->non_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] + = mpeg3bits_getbyte_noptr(video->vstream); + } + } + + if((load_chroma_intra_quantiser_matrix = mpeg3bits_getbit_noptr(video->vstream)) != 0) + { + for(i = 0; i < 64; i++) + video->chroma_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = mpeg3bits_getbyte_noptr(video->vstream); + } + + if((load_chroma_non_intra_quantiser_matrix = mpeg3bits_getbit_noptr(video->vstream)) != 0) + { + for(i = 0; i < 64; i++) + video->chroma_non_intra_quantizer_matrix[video->mpeg3_zigzag_scan_table[i]] = mpeg3bits_getbyte_noptr(video->vstream); + } +} + + +/* decode sequence scalable extension */ + +int mpeg3video_sequence_scalable_extension(mpeg3video_t *video) +{ + int layer_id; + + video->scalable_mode = mpeg3bits_getbits(video->vstream, 2) + 1; /* add 1 to make SC_DP != SC_NONE */ + layer_id = mpeg3bits_getbits(video->vstream, 4); + + if(video->scalable_mode == SC_SPAT) + { + video->llw = mpeg3bits_getbits(video->vstream, 14); /* lower_layer_prediction_horizontal_size */ + mpeg3bits_getbit_noptr(video->vstream); + video->llh = mpeg3bits_getbits(video->vstream, 14); /* lower_layer_prediction_vertical_size */ + video->hm = mpeg3bits_getbits(video->vstream, 5); + video->hn = mpeg3bits_getbits(video->vstream, 5); + video->vm = mpeg3bits_getbits(video->vstream, 5); + video->vn = mpeg3bits_getbits(video->vstream, 5); + } + + if(video->scalable_mode == SC_TEMP) + fprintf(stderr, "mpeg3video_sequence_scalable_extension: temporal scalability not implemented\n"); +} + + +/* decode picture display extension */ + +int mpeg3video_picture_display_extension(mpeg3video_t *video) +{ + int n, i; + short frame_centre_horizontal_offset[3]; + short frame_centre_vertical_offset[3]; + + if(video->prog_seq || video->pict_struct != FRAME_PICTURE) + n = 1; + else + n = video->repeatfirst ? 3 : 2; + + for(i = 0; i < n; i++) + { + frame_centre_horizontal_offset[i] = (short)mpeg3bits_getbits(video->vstream, 16); + mpeg3bits_getbit_noptr(video->vstream); + frame_centre_vertical_offset[i] = (short)mpeg3bits_getbits(video->vstream, 16); + mpeg3bits_getbit_noptr(video->vstream); + } +} + + +/* decode picture coding extension */ + +int mpeg3video_picture_coding_extension(mpeg3video_t *video) +{ + int chroma_420_type, composite_display_flag; + int v_axis = 0, field_sequence = 0, sub_carrier = 0, burst_amplitude = 0, sub_carrier_phase = 0; + + video->h_forw_r_size = mpeg3bits_getbits(video->vstream, 4) - 1; + video->v_forw_r_size = mpeg3bits_getbits(video->vstream, 4) - 1; + video->h_back_r_size = mpeg3bits_getbits(video->vstream, 4) - 1; + video->v_back_r_size = mpeg3bits_getbits(video->vstream, 4) - 1; + video->dc_prec = mpeg3bits_getbits(video->vstream, 2); + video->pict_struct = mpeg3bits_getbits(video->vstream, 2); + video->topfirst = mpeg3bits_getbit_noptr(video->vstream); + video->frame_pred_dct = mpeg3bits_getbit_noptr(video->vstream); + video->conceal_mv = mpeg3bits_getbit_noptr(video->vstream); + video->qscale_type = mpeg3bits_getbit_noptr(video->vstream); + video->intravlc = mpeg3bits_getbit_noptr(video->vstream); + video->altscan = mpeg3bits_getbit_noptr(video->vstream); + video->repeatfirst = mpeg3bits_getbit_noptr(video->vstream); + chroma_420_type = mpeg3bits_getbit_noptr(video->vstream); + video->prog_frame = mpeg3bits_getbit_noptr(video->vstream); + + if(video->repeat_count > 100) + video->repeat_count = 0; + video->repeat_count += 100; + + video->current_repeat = 0; + + if(video->prog_seq) + { + if(video->repeatfirst) + { + if(video->topfirst) + video->repeat_count += 200; + else + video->repeat_count += 100; + } + } + else + if(video->prog_frame) + { + if(video->repeatfirst) + { + video->repeat_count += 50; + } + } + +/*printf("mpeg3video_picture_coding_extension %d\n", video->repeat_count); */ + composite_display_flag = mpeg3bits_getbit_noptr(video->vstream); + + if(composite_display_flag) + { + v_axis = mpeg3bits_getbit_noptr(video->vstream); + field_sequence = mpeg3bits_getbits(video->vstream, 3); + sub_carrier = mpeg3bits_getbit_noptr(video->vstream); + burst_amplitude = mpeg3bits_getbits(video->vstream, 7); + sub_carrier_phase = mpeg3bits_getbyte_noptr(video->vstream); + } +} + + +/* decode picture spatial scalable extension */ + +int mpeg3video_picture_spatial_scalable_extension(mpeg3video_t *video) +{ + video->pict_scal = 1; /* use spatial scalability in this picture */ + + video->lltempref = mpeg3bits_getbits(video->vstream, 10); + mpeg3bits_getbit_noptr(video->vstream); + video->llx0 = mpeg3bits_getbits(video->vstream, 15); + if(video->llx0 >= 16384) video->llx0 -= 32768; + mpeg3bits_getbit_noptr(video->vstream); + video->lly0 = mpeg3bits_getbits(video->vstream, 15); + if(video->lly0 >= 16384) video->lly0 -= 32768; + video->stwc_table_index = mpeg3bits_getbits(video->vstream, 2); + video->llprog_frame = mpeg3bits_getbit_noptr(video->vstream); + video->llfieldsel = mpeg3bits_getbit_noptr(video->vstream); +} + + +/* decode picture temporal scalable extension + * + * not implemented + * + */ + +int mpeg3video_picture_temporal_scalable_extension(mpeg3video_t *video) +{ + fprintf(stderr, "mpeg3video_picture_temporal_scalable_extension: temporal scalability not supported\n"); +} + + +/* decode extension and user data */ + +int mpeg3video_ext_user_data(mpeg3video_t *video) +{ + int code = mpeg3bits_next_startcode(video->vstream); + + + while(code == MPEG3_EXT_START_CODE || code == MPEG3_USER_START_CODE && + !mpeg3bits_eof(video->vstream)) + { + mpeg3bits_refill(video->vstream); + + if(code == MPEG3_EXT_START_CODE) + { + int ext_id = mpeg3bits_getbits(video->vstream, 4); + switch(ext_id) + { + case SEQ_ID: + mpeg3video_sequence_extension(video); + break; + case DISP_ID: + mpeg3video_sequence_display_extension(video); + break; + case QUANT_ID: + mpeg3video_quant_matrix_extension(video); + break; + case SEQSCAL_ID: + mpeg3video_sequence_scalable_extension(video); + break; + case PANSCAN_ID: + mpeg3video_picture_display_extension(video); + break; + case CODING_ID: + mpeg3video_picture_coding_extension(video); + break; + case SPATSCAL_ID: + mpeg3video_picture_spatial_scalable_extension(video); + break; + case TEMPSCAL_ID: + mpeg3video_picture_temporal_scalable_extension(video); + break; + default: + fprintf(stderr,"mpeg3video_ext_user_data: reserved extension start code ID %d\n", ext_id); + break; + } + } + code = mpeg3bits_next_startcode(video->vstream); + } +} + + +/* decode group of pictures header */ + +int mpeg3video_getgophdr(mpeg3video_t *video) +{ + int drop_flag, closed_gop, broken_link; + + drop_flag = mpeg3bits_getbit_noptr(video->vstream); + video->gop_timecode.hour = mpeg3bits_getbits(video->vstream, 5); + video->gop_timecode.minute = mpeg3bits_getbits(video->vstream, 6); + mpeg3bits_getbit_noptr(video->vstream); + video->gop_timecode.second = mpeg3bits_getbits(video->vstream, 6); + video->gop_timecode.frame = mpeg3bits_getbits(video->vstream, 6); + closed_gop = mpeg3bits_getbit_noptr(video->vstream); + broken_link = mpeg3bits_getbit_noptr(video->vstream); + +/* + * printf("%d:%d:%d:%d %d %d %d\n", video->gop_timecode.hour, video->gop_timecode.minute, video->gop_timecode.second, video->gop_timecode.frame, + * drop_flag, closed_gop, broken_link); + */ + return mpeg3bits_error(video->vstream); +} + +/* decode picture header */ + +int mpeg3video_getpicturehdr(mpeg3video_t *video) +{ + int temp_ref, vbv_delay; + + video->pict_scal = 0; /* unless overwritten by pict. spat. scal. ext. */ + + temp_ref = mpeg3bits_getbits(video->vstream, 10); + video->pict_type = mpeg3bits_getbits(video->vstream, 3); + vbv_delay = mpeg3bits_getbits(video->vstream, 16); + + if(video->pict_type == P_TYPE || video->pict_type == B_TYPE) + { + video->full_forw = mpeg3bits_getbit_noptr(video->vstream); + video->forw_r_size = mpeg3bits_getbits(video->vstream, 3) - 1; + } + + if(video->pict_type == B_TYPE) + { + video->full_back = mpeg3bits_getbit_noptr(video->vstream); + video->back_r_size = mpeg3bits_getbits(video->vstream, 3) - 1; + } + +/* get extra bit picture */ + while(mpeg3bits_getbit_noptr(video->vstream) && + !mpeg3bits_eof(video->vstream)) mpeg3bits_getbyte_noptr(video->vstream); + return 0; +} + + +int mpeg3video_get_header(mpeg3video_t *video, int dont_repeat) +{ + unsigned int code; + +/* a sequence header should be found before returning from `getheader' the */ +/* first time (this is to set horizontal/vertical size properly) */ + +/* Repeat the frame until it's less than 1 count from repeat_count */ + if(video->repeat_count - video->current_repeat >= 100 && !dont_repeat) + { + return 0; + } + + if(dont_repeat) + { + video->repeat_count = 0; + video->current_repeat = 0; + } + else + video->repeat_count -= video->current_repeat; + + while(1) + { +/* look for startcode */ + code = mpeg3bits_next_startcode(video->vstream); + if(mpeg3bits_eof(video->vstream)) return 1; + if(code != MPEG3_SEQUENCE_END_CODE) mpeg3bits_refill(video->vstream); + + switch(code) + { + case MPEG3_SEQUENCE_START_CODE: + video->found_seqhdr = 1; + mpeg3video_getseqhdr(video); + mpeg3video_ext_user_data(video); + break; + + case MPEG3_GOP_START_CODE: + mpeg3video_getgophdr(video); + mpeg3video_ext_user_data(video); + break; + + case MPEG3_PICTURE_START_CODE: + mpeg3video_getpicturehdr(video); + mpeg3video_ext_user_data(video); + if(video->found_seqhdr) return 0; /* Exit here */ + break; + + case MPEG3_SEQUENCE_END_CODE: +// Continue until the end + mpeg3bits_refill(video->vstream); + break; + + default: + break; + } + } + return 1; /* Shouldn't be reached. */ +} + +int mpeg3video_ext_bit_info(mpeg3_slice_buffer_t *slice_buffer) +{ + while(mpeg3slice_getbit(slice_buffer)) mpeg3slice_getbyte(slice_buffer); + return 0; +} + +/* decode slice header */ +int mpeg3video_getslicehdr(mpeg3_slice_t *slice, mpeg3video_t *video) +{ + int slice_vertical_position_extension, intra_slice; + int qs; + + slice_vertical_position_extension = (video->mpeg2 && video->vertical_size > 2800) ? + mpeg3slice_getbits(slice->slice_buffer, 3) : 0; + + if(video->scalable_mode == SC_DP) slice->pri_brk = mpeg3slice_getbits(slice->slice_buffer, 7); + + qs = mpeg3slice_getbits(slice->slice_buffer, 5); + slice->quant_scale = video->mpeg2 ? (video->qscale_type ? mpeg3_non_linear_mquant_table[qs] : (qs << 1)) : qs; + + if(mpeg3slice_getbit(slice->slice_buffer)) + { + intra_slice = mpeg3slice_getbit(slice->slice_buffer); + mpeg3slice_getbits(slice->slice_buffer, 7); + mpeg3video_ext_bit_info(slice->slice_buffer); + } + else + intra_slice = 0; + + return slice_vertical_position_extension; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/idct.c b/core/multimedia/opieplayer/libmpeg3/video/idct.c new file mode 100644 index 0000000..c79f90a --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/idct.c @@ -0,0 +1,160 @@ +#include "idct.h" +#include <stdlib.h> + +/**********************************************************/ +/* inverse two dimensional DCT, Chen-Wang algorithm */ +/* (cf. IEEE ASSP-32, pp. 803-816, Aug. 1984) */ +/* 32-bit integer arithmetic (8 bit coefficients) */ +/* 11 mults, 29 adds per DCT */ +/* sE, 18.8.91 */ +/**********************************************************/ +/* coefficients extended to 12 bit for IEEE1180-1990 */ +/* compliance sE, 2.1.94 */ +/**********************************************************/ + +/* this code assumes >> to be a two's-complement arithmetic */ +/* right shift: (-2)>>1 == -1 , (-3)>>1 == -2 */ + +#define W1 2841 /* 2048*sqrt(2)*cos(1*pi/16) */ +#define W2 2676 /* 2048*sqrt(2)*cos(2*pi/16) */ +#define W3 2408 /* 2048*sqrt(2)*cos(3*pi/16) */ +#define W5 1609 /* 2048*sqrt(2)*cos(5*pi/16) */ +#define W6 1108 /* 2048*sqrt(2)*cos(6*pi/16) */ +#define W7 565 /* 2048*sqrt(2)*cos(7*pi/16) */ + +/* row (horizontal) IDCT + * + * 7 pi 1 + * dst[k] = sum c[l] * src[l] * cos( -- * ( k + - ) * l ) + * l=0 8 2 + * + * where: c[0] = 128 + * c[1..7] = 128*sqrt(2) + */ + +int mpeg3video_idctrow(short *blk) +{ + int x0, x1, x2, x3, x4, x5, x6, x7, x8; + + /* shortcut */ + if (!((x1 = blk[4]<<11) | (x2 = blk[6]) | (x3 = blk[2]) | + (x4 = blk[1]) | (x5 = blk[7]) | (x6 = blk[5]) | (x7 = blk[3]))) + { + blk[0]=blk[1]=blk[2]=blk[3]=blk[4]=blk[5]=blk[6]=blk[7]=blk[0]<<3; + return 0; + } + + x0 = (blk[0]<<11) + 128; /* for proper rounding in the fourth stage */ + + /* first stage */ + x8 = W7*(x4+x5); + x4 = x8 + (W1-W7)*x4; + x5 = x8 - (W1+W7)*x5; + x8 = W3*(x6+x7); + x6 = x8 - (W3-W5)*x6; + x7 = x8 - (W3+W5)*x7; + + /* second stage */ + x8 = x0 + x1; + x0 -= x1; + x1 = W6*(x3+x2); + x2 = x1 - (W2+W6)*x2; + x3 = x1 + (W2-W6)*x3; + x1 = x4 + x6; + x4 -= x6; + x6 = x5 + x7; + x5 -= x7; + + /* third stage */ + x7 = x8 + x3; + x8 -= x3; + x3 = x0 + x2; + x0 -= x2; + x2 = (181*(x4+x5)+128)>>8; + x4 = (181*(x4-x5)+128)>>8; + + /* fourth stage */ + blk[0] = (x7+x1)>>8; + blk[1] = (x3+x2)>>8; + blk[2] = (x0+x4)>>8; + blk[3] = (x8+x6)>>8; + blk[4] = (x8-x6)>>8; + blk[5] = (x0-x4)>>8; + blk[6] = (x3-x2)>>8; + blk[7] = (x7-x1)>>8; + + return 1; +} + +/* column (vertical) IDCT + * + * 7 pi 1 + * dst[8*k] = sum c[l] * src[8*l] * cos( -- * ( k + - ) * l ) + * l=0 8 2 + * + * where: c[0] = 1/1024 + * c[1..7] = (1/1024)*sqrt(2) + */ + +int mpeg3video_idctcol(short *blk) +{ + int x0, x1, x2, x3, x4, x5, x6, x7, x8; + + /* shortcut */ + if (!((x1 = (blk[8 * 4]<<8)) | (x2 = blk[8 * 6]) | (x3 = blk[8 * 2]) | + (x4 = blk[8*1]) | (x5 = blk[8 * 7]) | (x6 = blk[8 * 5]) | (x7 = blk[8 * 3]))){ + blk[8*0]=blk[8*1]=blk[8 * 2]=blk[8 * 3]=blk[8 * 4]=blk[8 * 5]=blk[8 * 6]=blk[8 * 7]= + (blk[8*0]+32)>>6; + return 0; + } + + x0 = (blk[8*0]<<8) + 8192; + + /* first stage */ + x8 = W7*(x4+x5) + 4; + x4 = (x8+(W1-W7)*x4)>>3; + x5 = (x8-(W1+W7)*x5)>>3; + x8 = W3*(x6+x7) + 4; + x6 = (x8-(W3-W5)*x6)>>3; + x7 = (x8-(W3+W5)*x7)>>3; + + /* second stage */ + x8 = x0 + x1; + x0 -= x1; + x1 = W6*(x3+x2) + 4; + x2 = (x1-(W2+W6)*x2)>>3; + x3 = (x1+(W2-W6)*x3)>>3; + x1 = x4 + x6; + x4 -= x6; + x6 = x5 + x7; + x5 -= x7; + + /* third stage */ + x7 = x8 + x3; + x8 -= x3; + x3 = x0 + x2; + x0 -= x2; + x2 = (181 * (x4 + x5) + 128) >> 8; + x4 = (181 * (x4 - x5) + 128) >> 8; + + /* fourth stage */ + blk[8 * 0] = (x7 + x1) >> 14; + blk[8 * 1] = (x3 + x2) >> 14; + blk[8 * 2] = (x0 + x4) >> 14; + blk[8 * 3] = (x8 + x6) >> 14; + blk[8 * 4] = (x8 - x6) >> 14; + blk[8 * 5] = (x0 - x4) >> 14; + blk[8 * 6] = (x3 - x2) >> 14; + blk[8 * 7] = (x7 - x1) >> 14; + + return 1; +} + + +/* two dimensional inverse discrete cosine transform */ +void mpeg3video_idct_conversion(short* block) +{ + int i; + for(i = 0; i < 8; i++) mpeg3video_idctrow(block + 8 * i); + for(i = 0; i < 8; i++) mpeg3video_idctcol(block + i); +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/idct.h b/core/multimedia/opieplayer/libmpeg3/video/idct.h new file mode 100644 index 0000000..f0aa1d8 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/idct.h @@ -0,0 +1,24 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef IDCT_H +#define IDCT_H + + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/video/layerdata.h b/core/multimedia/opieplayer/libmpeg3/video/layerdata.h new file mode 100644 index 0000000..3ef0f90 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/layerdata.h @@ -0,0 +1,35 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef LAYERDATA_H +#define LAYERDATA_H + +typedef struct +{ +/* sequence header */ + int intra_quantizer_matrix[64], non_intra_quantizer_matrix[64]; + int chroma_intra_quantizer_matrix[64], chroma_non_intra_quantizer_matrix[64]; + int mpeg2; + int qscale_type, altscan; /* picture coding extension */ + int pict_scal; /* picture spatial scalable extension */ + int scalable_mode; /* sequence scalable extension */ +} mpeg3_layerdata_t; + + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/video/macroblocks.c b/core/multimedia/opieplayer/libmpeg3/video/macroblocks.c new file mode 100644 index 0000000..11e17c1 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/macroblocks.c @@ -0,0 +1,338 @@ +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" +#include "slice.h" +#include "vlc.h" + +#include <stdio.h> + +int mpeg3video_get_macroblock_address(mpeg3_slice_t *slice) +{ + int code, val = 0; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + + while((code = mpeg3slice_showbits(slice_buffer, 11)) < 24) + { +/* Is not macroblock_stuffing */ + if(code != 15) + { +/* Is macroblock_escape */ + if(code == 8) + { + val += 33; + } + else + { +/* fprintf(stderr, "mpeg3video_get_macroblock_address: invalid macroblock_address_increment code\n"); */ + slice->fault = 1; + return 1; + } + } + + mpeg3slice_flushbits(slice_buffer, 11); + } + + if(code >= 1024) + { + mpeg3slice_flushbit(slice_buffer); + return val + 1; + } + + if(code >= 128) + { + code >>= 6; + mpeg3slice_flushbits(slice_buffer, mpeg3_MBAtab1[code].len); + return val + mpeg3_MBAtab1[code].val; + } + + code -= 24; + mpeg3slice_flushbits(slice_buffer, mpeg3_MBAtab2[code].len); + + return val + mpeg3_MBAtab2[code].val; +} + +/* macroblock_type for pictures with spatial scalability */ + +static inline int mpeg3video_getsp_imb_type(mpeg3_slice_t *slice) +{ +// ### This looks wrong. +// slice_buffer is used without being initialised and slice is not used +// mpeg3_slice_buffer_t *slice_buffer = slice_buffer; +// I think this would make more sense and might be what is intended + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + unsigned int code = mpeg3slice_showbits(slice_buffer, 4); + if(!code) + { +/* fprintf(stderr,"mpeg3video_getsp_imb_type: invalid macroblock_type code\n"); */ + slice->fault = 1; + return 0; + } + + mpeg3slice_flushbits(slice_buffer, mpeg3_spIMBtab[code].len); + return mpeg3_spIMBtab[code].val; +} + +static inline int mpeg3video_getsp_pmb_type(mpeg3_slice_t *slice) +{ + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + int code = mpeg3slice_showbits(slice_buffer, 7); + if(code < 2) + { +/* fprintf(stderr,"mpeg3video_getsp_pmb_type: invalid macroblock_type code\n"); */ + slice->fault = 1; + return 0; + } + + if(code >= 16) + { + code >>= 3; + mpeg3slice_flushbits(slice_buffer, mpeg3_spPMBtab0[code].len); + + return mpeg3_spPMBtab0[code].val; + } + + mpeg3slice_flushbits(slice_buffer, mpeg3_spPMBtab1[code].len); + return mpeg3_spPMBtab1[code].val; +} + +static inline int mpeg3video_getsp_bmb_type(mpeg3_slice_t *slice) +{ + mpeg3_VLCtab_t *p; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + int code = mpeg3slice_showbits9(slice_buffer); + + if(code >= 64) + p = &mpeg3_spBMBtab0[(code >> 5) - 2]; + else + if(code >= 16) + p = &mpeg3_spBMBtab1[(code >> 2) - 4]; + else + if(code >= 8) + p = &mpeg3_spBMBtab2[code - 8]; + else + { +/* fprintf(stderr,"mpeg3video_getsp_bmb_type: invalid macroblock_type code\n"); */ + slice->fault = 1; + return 0; + } + + mpeg3slice_flushbits(slice_buffer, p->len); + return p->val; +} + +static inline int mpeg3video_get_imb_type(mpeg3_slice_t *slice) +{ + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + if(mpeg3slice_getbit(slice_buffer)) + { + return 1; + } + + if(!mpeg3slice_getbit(slice_buffer)) + { +/* fprintf(stderr,"mpeg3video_get_imb_type: invalid macroblock_type code\n"); */ + slice->fault = 1; + } + + return 17; +} + +static inline int mpeg3video_get_pmb_type(mpeg3_slice_t *slice) +{ + int code; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + + if((code = mpeg3slice_showbits(slice_buffer, 6)) >= 8) + { + code >>= 3; + mpeg3slice_flushbits(slice_buffer, mpeg3_PMBtab0[code].len); + return mpeg3_PMBtab0[code].val; + } + + if(code == 0) + { +/* fprintf(stderr,"mpeg3video_get_pmb_type: invalid macroblock_type code\n"); */ + slice->fault = 1; + return 0; + } + + mpeg3slice_flushbits(slice_buffer, mpeg3_PMBtab1[code].len); + return mpeg3_PMBtab1[code].val; +} + +static inline int mpeg3video_get_bmb_type(mpeg3_slice_t *slice) +{ + int code; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + + if((code = mpeg3slice_showbits(slice_buffer, 6)) >= 8) + { + code >>= 2; + mpeg3slice_flushbits(slice_buffer, mpeg3_BMBtab0[code].len); + return mpeg3_BMBtab0[code].val; + } + + if(code == 0) + { +/* fprintf(stderr,"mpeg3video_get_bmb_type: invalid macroblock_type code\n"); */ + slice->fault = 1; + return 0; + } + + mpeg3slice_flushbits(slice_buffer, mpeg3_BMBtab1[code].len); + + return mpeg3_BMBtab1[code].val; +} + +static inline int mpeg3video_get_dmb_type(mpeg3_slice_t *slice) +{ + if(!mpeg3slice_getbit(slice->slice_buffer)) + { +/* fprintf(stderr,"mpeg3video_get_dmb_type: invalid macroblock_type code\n"); */ + slice->fault=1; + } + + return 1; +} + + +static inline int mpeg3video_get_snrmb_type(mpeg3_slice_t *slice) +{ + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + int code = mpeg3slice_showbits(slice_buffer, 3); + + if(code == 0) + { +/* fprintf(stderr,"mpeg3video_get_snrmb_type: invalid macroblock_type code\n"); */ + slice->fault = 1; + return 0; + } + + mpeg3slice_flushbits(slice_buffer, mpeg3_SNRMBtab[code].len); + return mpeg3_SNRMBtab[code].val; +} + +int mpeg3video_get_mb_type(mpeg3_slice_t *slice, mpeg3video_t *video) +{ + if(video->scalable_mode == SC_SNR) + { + return mpeg3video_get_snrmb_type(slice); + } + else + { + switch(video->pict_type) + { + case I_TYPE: return video->pict_scal ? mpeg3video_getsp_imb_type(slice) : mpeg3video_get_imb_type(slice); + case P_TYPE: return video->pict_scal ? mpeg3video_getsp_pmb_type(slice) : mpeg3video_get_pmb_type(slice); + case B_TYPE: return video->pict_scal ? mpeg3video_getsp_bmb_type(slice) : mpeg3video_get_bmb_type(slice); + case D_TYPE: return mpeg3video_get_dmb_type(slice); + default: + /*fprintf(stderr, "mpeg3video_getmbtype: unknown coding type\n"); */ + break; +/* MPEG-1 only, not implemented */ + } + } + + return 0; +} + +int mpeg3video_macroblock_modes(mpeg3_slice_t *slice, + mpeg3video_t *video, + int *pmb_type, + int *pstwtype, + int *pstwclass, + int *pmotion_type, + int *pmv_count, + int *pmv_format, + int *pdmv, + int *pmvscale, + int *pdct_type) +{ + int mb_type; + int stwtype, stwcode, stwclass; + int motion_type = 0, mv_count, mv_format, dmv, mvscale; + int dct_type; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + static unsigned char stwc_table[3][4] + = { {6,3,7,4}, {2,1,5,4}, {2,5,7,4} }; + static unsigned char stwclass_table[9] + = {0, 1, 2, 1, 1, 2, 3, 3, 4}; + +/* get macroblock_type */ + mb_type = mpeg3video_get_mb_type(slice, video); + + if(slice->fault) return 1; + +/* get spatial_temporal_weight_code */ + if(mb_type & MB_WEIGHT) + { + if(video->stwc_table_index == 0) + stwtype = 4; + else + { + stwcode = mpeg3slice_getbits2(slice_buffer); + stwtype = stwc_table[video->stwc_table_index - 1][stwcode]; + } + } + else + stwtype = (mb_type & MB_CLASS4) ? 8 : 0; + +/* derive spatial_temporal_weight_class (Table 7-18) */ + stwclass = stwclass_table[stwtype]; + +/* get frame/field motion type */ + if(mb_type & (MB_FORWARD | MB_BACKWARD)) + { + if(video->pict_struct == FRAME_PICTURE) + { +/* frame_motion_type */ + motion_type = video->frame_pred_dct ? MC_FRAME : mpeg3slice_getbits2(slice_buffer); + } + else + { +/* field_motion_type */ + motion_type = mpeg3slice_getbits2(slice_buffer); + } + } + else + if((mb_type & MB_INTRA) && video->conceal_mv) + { +/* concealment motion vectors */ + motion_type = (video->pict_struct == FRAME_PICTURE) ? MC_FRAME : MC_FIELD; + } + +/* derive mv_count, mv_format and dmv, (table 6-17, 6-18) */ + if(video->pict_struct == FRAME_PICTURE) + { + mv_count = (motion_type == MC_FIELD && stwclass < 2) ? 2 : 1; + mv_format = (motion_type == MC_FRAME) ? MV_FRAME : MV_FIELD; + } + else + { + mv_count = (motion_type == MC_16X8) ? 2 : 1; + mv_format = MV_FIELD; + } + + dmv = (motion_type == MC_DMV); /* dual prime */ + +/* field mv predictions in frame pictures have to be scaled */ + mvscale = ((mv_format == MV_FIELD) && (video->pict_struct == FRAME_PICTURE)); + +/* get dct_type (frame DCT / field DCT) */ + dct_type = (video->pict_struct == FRAME_PICTURE) && + (!video->frame_pred_dct) && + (mb_type & (MB_PATTERN | MB_INTRA)) ? + mpeg3slice_getbit(slice_buffer) : 0; + +/* return values */ + *pmb_type = mb_type; + *pstwtype = stwtype; + *pstwclass = stwclass; + *pmotion_type = motion_type; + *pmv_count = mv_count; + *pmv_format = mv_format; + *pdmv = dmv; + *pmvscale = mvscale; + *pdct_type = dct_type; + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/mmxidct.S b/core/multimedia/opieplayer/libmpeg3/video/mmxidct.S new file mode 100644 index 0000000..9c3bebe --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/mmxidct.S @@ -0,0 +1,675 @@ +/* + * the input data is tranposed and each 16 bit element in the 8x8 matrix + * is left aligned: + * for example in 11...1110000 format + * If the iDCT is of I macroblock then 0.5 needs to be added to the;DC Component + * (element[0][0] of the matrix) + */ + +/* extrn re_matrix */ + +/* constants */ + +.data + .align 16 + .type preSC, @object +preSC: .short 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520 + .short 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270 + .short 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906 + .short 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315 + .short 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520 + .short 12873, 17855, 16819, 15137, 25746, 20228, 13933, 7103 + .short 17734, 24598, 23170, 20853, 17734, 13933, 9597, 4892 + .short 18081, 25080, 23624, 21261, 18081, 14206, 9785, 4988 + .size preSC, 128 + .align 8 + .type x0005000200010001, @object + .size x0005000200010001, 8 +x0005000200010001: + .long 0x00010001, 0x00050002 + .align 8 + .type x0040000000000000, @object + .size x0040000000000000, 8 +x0040000000000000: + .long 0, 0x00400000 + .align 8 + .type x5a825a825a825a82, @object + .size x5a825a825a825a82, 8 +x5a825a825a825a82: + .long 0x5a825a82, 0x5a825a82 + .align 8 + .type x539f539f539f539f, @object + .size x539f539f539f539f, 8 +x539f539f539f539f: + .long 0x539f539f, 0x539f539f + .align 8 + .type x4546454645464546, @object + .size x4546454645464546, 8 +x4546454645464546: + .long 0x45464546, 0x45464546 + .align 8 + .type x61f861f861f861f8, @object + .size x61f861f861f861f8, 8 +x61f861f861f861f8: + .long 0x61f861f8, 0x61f861f8 +/* Static variables */ + .align 8 + .type x0, @object + .size x0, 8 +x0: + .long 0, 0 +/* Procedure */ + + + .align 8 +.text + .align 4 +.globl IDCT_mmx + .type IDCT_mmx, @function +IDCT_mmx: + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %ecx + pushl %edx + pushl %esi + pushl %edi + + pushl $0 /* allocate the temp variables */ + pushl $0 + pushl $0 + pushl $0 + pushl $0 + pushl $0 + pushl $0 + pushl $0 + + movl 8(%ebp), %esi /* source matrix */ + leal preSC, %ecx +/* column 0: even part + * use V4, V12, V0, V8 to produce V22..V25 + */ + movq 8*12(%ecx), %mm0 /* maybe the first mul can be done together */ + /* with the dequantization in iHuff module */ + pmulhw 8*12(%esi), %mm0 /* V12 */ + movq 8*4(%ecx), %mm1 + pmulhw 8*4(%esi), %mm1 /* V4 */ + movq (%ecx), %mm3 + psraw $1, %mm0 /* t64=t66 */ + pmulhw (%esi), %mm3 /* V0 */ + movq 8*8(%ecx), %mm5 /* duplicate V4 */ + movq %mm1, %mm2 /* added 11/1/96 */ + pmulhw 8*8(%esi),%mm5 /* V8 */ + psubsw %mm0, %mm1 /* V16 */ + pmulhw x5a825a825a825a82, %mm1 /* 23170 ->V18 */ + paddsw %mm0, %mm2 /* V17 */ + movq %mm2, %mm0 /* duplicate V17 */ + psraw $1, %mm2 /* t75=t82 */ + psraw $2, %mm0 /* t72 */ + movq %mm3, %mm4 /* duplicate V0 */ + paddsw %mm5, %mm3 /* V19 */ + psubsw %mm5, %mm4 /* V20 ;mm5 free */ +/* moved from the block below */ + movq 8*10(%ecx), %mm7 + psraw $1, %mm3 /* t74=t81 */ + movq %mm3, %mm6 /* duplicate t74=t81 */ + psraw $2, %mm4 /* t77=t79 */ + psubsw %mm0, %mm1 /* V21 ; mm0 free */ + paddsw %mm2, %mm3 /* V22 */ + movq %mm1, %mm5 /* duplicate V21 */ + paddsw %mm4, %mm1 /* V23 */ + movq %mm3, 8*4(%esi) /* V22 */ + psubsw %mm5, %mm4 /* V24; mm5 free */ + movq %mm1, 8*12(%esi) /* V23 */ + psubsw %mm2, %mm6 /* V25; mm2 free */ + movq %mm4, (%esi) /* V24 */ +/* keep mm6 alive all along the next block */ + /* movq %mm6, 8*8(%esi) V25 */ +/* column 0: odd part + * use V2, V6, V10, V14 to produce V31, V39, V40, V41 + */ +/* moved above: movq 8*10(%ecx), %mm7 */ + + pmulhw 8*10(%esi), %mm7 /* V10 */ + movq 8*6(%ecx), %mm0 + pmulhw 8*6(%esi), %mm0 /* V6 */ + movq 8*2(%ecx), %mm5 + movq %mm7, %mm3 /* duplicate V10 */ + pmulhw 8*2(%esi), %mm5 /* V2 */ + movq 8*14(%ecx), %mm4 + psubsw %mm0, %mm7 /* V26 */ + pmulhw 8*14(%esi), %mm4 /* V14 */ + paddsw %mm0, %mm3 /* V29 ; free mm0 */ + movq %mm7, %mm1 /* duplicate V26 */ + psraw $1, %mm3 /* t91=t94 */ + pmulhw x539f539f539f539f,%mm7 /* V33 */ + psraw $1, %mm1 /* t96 */ + movq %mm5, %mm0 /* duplicate V2 */ + psraw $2, %mm4 /* t85=t87 */ + paddsw %mm4,%mm5 /* V27 */ + psubsw %mm4, %mm0 /* V28 ; free mm4 */ + movq %mm0, %mm2 /* duplicate V28 */ + psraw $1, %mm5 /* t90=t93 */ + pmulhw x4546454645464546,%mm0 /* V35 */ + psraw $1, %mm2 /* t97 */ + movq %mm5, %mm4 /* duplicate t90=t93 */ + psubsw %mm2, %mm1 /* V32 ; free mm2 */ + pmulhw x61f861f861f861f8,%mm1 /* V36 */ + psllw $1, %mm7 /* t107 */ + paddsw %mm3, %mm5 /* V31 */ + psubsw %mm3, %mm4 /* V30 ; free mm3 */ + pmulhw x5a825a825a825a82,%mm4 /* V34 */ + nop + psubsw %mm1, %mm0 /* V38 */ + psubsw %mm7, %mm1 /* V37 ; free mm7 */ + psllw $1, %mm1 /* t114 */ +/* move from the next block */ + movq %mm6, %mm3 /* duplicate V25 */ +/* move from the next block */ + movq 8*4(%esi), %mm7 /* V22 */ + psllw $1, %mm0 /* t110 */ + psubsw %mm5, %mm0 /* V39 (mm5 needed for next block) */ + psllw $2, %mm4 /* t112 */ +/* moved from the next block */ + movq 8*12(%esi), %mm2 /* V23 */ + psubsw %mm0, %mm4 /* V40 */ + paddsw %mm4, %mm1 /* V41; free mm0 */ +/* moved from the next block */ + psllw $1, %mm2 /* t117=t125 */ +/* column 0: output butterfly */ +/* moved above: + * movq %mm6, %mm3 duplicate V25 + * movq 8*4(%esi), %mm7 V22 + * movq 8*12(%esi), %mm2 V23 + * psllw $1, %mm2 t117=t125 + */ + psubsw %mm1, %mm6 /* tm6 */ + paddsw %mm1, %mm3 /* tm8; free mm1 */ + movq %mm7, %mm1 /* duplicate V22 */ + paddsw %mm5, %mm7 /* tm0 */ + movq %mm3, 8*8(%esi) /* tm8; free mm3 */ + psubsw %mm5, %mm1 /* tm14; free mm5 */ + movq %mm6, 8*6(%esi) /* tm6; free mm6 */ + movq %mm2, %mm3 /* duplicate t117=t125 */ + movq (%esi), %mm6 /* V24 */ + paddsw %mm0, %mm2 /* tm2 */ + movq %mm7, (%esi) /* tm0; free mm7 */ + psubsw %mm0, %mm3 /* tm12; free mm0 */ + movq %mm1, 8*14(%esi) /* tm14; free mm1 */ + psllw $1, %mm6 /* t119=t123 */ + movq %mm2, 8*2(%esi) /* tm2; free mm2 */ + movq %mm6, %mm0 /* duplicate t119=t123 */ + movq %mm3, 8*12(%esi) /* tm12; free mm3 */ + paddsw %mm4, %mm6 /* tm4 */ +/* moved from next block */ + movq 8*5(%ecx), %mm1 + psubsw %mm4, %mm0 /* tm10; free mm4 */ +/* moved from next block */ + pmulhw 8*5(%esi), %mm1 /* V5 */ + movq %mm6, 8*4(%esi) /* tm4; free mm6 */ + movq %mm0, 8*10(%esi) /* tm10; free mm0 */ +/* column 1: even part + * use V5, V13, V1, V9 to produce V56..V59 + */ +/* moved to prev block: + * movq 8*5(%ecx), %mm1 + * pmulhw 8*5(%esi), %mm1 V5 + */ + movq 8*13(%ecx), %mm7 + psllw $1, %mm1 /* t128=t130 */ + pmulhw 8*13(%esi), %mm7 /* V13 */ + movq %mm1, %mm2 /* duplicate t128=t130 */ + movq 8(%ecx), %mm3 + pmulhw 8(%esi), %mm3 /* V1 */ + movq 8*9(%ecx), %mm5 + psubsw %mm7, %mm1 /* V50 */ + pmulhw 8*9(%esi), %mm5 /* V9 */ + paddsw %mm7, %mm2 /* V51 */ + pmulhw x5a825a825a825a82, %mm1 /* 23170 ->V52 */ + movq %mm2, %mm6 /* duplicate V51 */ + psraw $1, %mm2 /* t138=t144 */ + movq %mm3, %mm4 /* duplicate V1 */ + psraw $2, %mm6 /* t136 */ + paddsw %mm5, %mm3 /* V53 */ + psubsw %mm5, %mm4 /* V54 ;mm5 free */ + movq %mm3, %mm7 /* duplicate V53 */ +/* moved from next block */ + movq 8*11(%ecx), %mm0 + psraw $1, %mm4 /* t140=t142 */ + psubsw %mm6, %mm1 /* V55 ; mm6 free */ + paddsw %mm2, %mm3 /* V56 */ + movq %mm4, %mm5 /* duplicate t140=t142 */ + paddsw %mm1, %mm4 /* V57 */ + movq %mm3, 8*5(%esi) /* V56 */ + psubsw %mm1, %mm5 /* V58; mm1 free */ + movq %mm4, 8*13(%esi) /* V57 */ + psubsw %mm2, %mm7 /* V59; mm2 free */ + movq %mm5, 8*9(%esi) /* V58 */ +/* keep mm7 alive all along the next block + * movq %mm7, 8(%esi) V59 + * moved above + * movq 8*11(%ecx), %mm0 + */ + pmulhw 8*11(%esi), %mm0 /* V11 */ + movq 8*7(%ecx), %mm6 + pmulhw 8*7(%esi), %mm6 /* V7 */ + movq 8*15(%ecx), %mm4 + movq %mm0, %mm3 /* duplicate V11 */ + pmulhw 8*15(%esi), %mm4 /* V15 */ + movq 8*3(%ecx), %mm5 + psllw $1, %mm6 /* t146=t152 */ + pmulhw 8*3(%esi), %mm5 /* V3 */ + paddsw %mm6, %mm0 /* V63 */ +/* note that V15 computation has a correction step: + * this is a 'magic' constant that rebiases the results to be closer to the + * expected result. this magic constant can be refined to reduce the error + * even more by doing the correction step in a later stage when the number + * is actually multiplied by 16 + */ + paddw x0005000200010001, %mm4 + psubsw %mm6, %mm3 /* V60 ; free mm6 */ + psraw $1, %mm0 /* t154=t156 */ + movq %mm3, %mm1 /* duplicate V60 */ + pmulhw x539f539f539f539f, %mm1 /* V67 */ + movq %mm5, %mm6 /* duplicate V3 */ + psraw $2, %mm4 /* t148=t150 */ + paddsw %mm4, %mm5 /* V61 */ + psubsw %mm4, %mm6 /* V62 ; free mm4 */ + movq %mm5, %mm4 /* duplicate V61 */ + psllw $1, %mm1 /* t169 */ + paddsw %mm0, %mm5 /* V65 -> result */ + psubsw %mm0, %mm4 /* V64 ; free mm0 */ + pmulhw x5a825a825a825a82, %mm4 /* V68 */ + psraw $1, %mm3 /* t158 */ + psubsw %mm6, %mm3 /* V66 */ + movq %mm5, %mm2 /* duplicate V65 */ + pmulhw x61f861f861f861f8, %mm3 /* V70 */ + psllw $1, %mm6 /* t165 */ + pmulhw x4546454645464546, %mm6 /* V69 */ + psraw $1, %mm2 /* t172 */ +/* moved from next block */ + movq 8*5(%esi), %mm0 /* V56 */ + psllw $1, %mm4 /* t174 */ +/* moved from next block */ + psraw $1, %mm0 /* t177=t188 */ + nop + psubsw %mm3, %mm6 /* V72 */ + psubsw %mm1, %mm3 /* V71 ; free mm1 */ + psubsw %mm2, %mm6 /* V73 ; free mm2 */ +/* moved from next block */ + psraw $1, %mm5 /* t178=t189 */ + psubsw %mm6, %mm4 /* V74 */ +/* moved from next block */ + movq %mm0, %mm1 /* duplicate t177=t188 */ + paddsw %mm4, %mm3 /* V75 */ +/* moved from next block */ + paddsw %mm5, %mm0 /* tm1 */ +/* location + * 5 - V56 + * 13 - V57 + * 9 - V58 + * X - V59, mm7 + * X - V65, mm5 + * X - V73, mm6 + * X - V74, mm4 + * X - V75, mm3 + * free mm0, mm1 & mm2 + * moved above + * movq 8*5(%esi), %mm0 V56 + * psllw $1, %mm0 t177=t188 ! new !! + * psllw $1, %mm5 t178=t189 ! new !! + * movq %mm0, %mm1 duplicate t177=t188 + * paddsw %mm5, %mm0 tm1 + */ + movq 8*13(%esi), %mm2 /* V57 */ + psubsw %mm5, %mm1 /* tm15; free mm5 */ + movq %mm0, 8(%esi) /* tm1; free mm0 */ + psraw $1, %mm7 /* t182=t184 ! new !! */ +/* save the store as used directly in the transpose + * movq %mm1, 120(%esi) tm15; free mm1 + */ + movq %mm7, %mm5 /* duplicate t182=t184 */ + psubsw %mm3, %mm7 /* tm7 */ + paddsw %mm3, %mm5 /* tm9; free mm3 */ + movq 8*9(%esi), %mm0 /* V58 */ + movq %mm2, %mm3 /* duplicate V57 */ + movq %mm7, 8*7(%esi) /* tm7; free mm7 */ + psubsw %mm6, %mm3 /* tm13 */ + paddsw %mm6, %mm2 /* tm3 ; free mm6 */ +/* moved up from the transpose */ + movq %mm3, %mm7 +/* moved up from the transpose */ + punpcklwd %mm1, %mm3 + movq %mm0, %mm6 /* duplicate V58 */ + movq %mm2, 8*3(%esi) /* tm3; free mm2 */ + paddsw %mm4, %mm0 /* tm5 */ + psubsw %mm4, %mm6 /* tm11; free mm4 */ +/* moved up from the transpose */ + punpckhwd %mm1, %mm7 + movq %mm0, 8*5(%esi) /* tm5; free mm0 */ +/* moved up from the transpose */ + movq %mm5, %mm2 +/* transpose - M4 part + * --------- --------- + * | M1 | M2 | | M1'| M3'| + * --------- --> --------- + * | M3 | M4 | | M2'| M4'| + * --------- --------- + * Two alternatives: use full mmword approach so the following code can be + * scheduled before the transpose is done without stores, or use the faster + * half mmword stores (when possible) + */ + movd %mm3, 8*9+4(%esi) /* MS part of tmt9 */ + punpcklwd %mm6, %mm5 + movd %mm7, 8*13+4(%esi) /* MS part of tmt13 */ + punpckhwd %mm6, %mm2 + movd %mm5, 8*9(%esi) /* LS part of tmt9 */ + punpckhdq %mm3, %mm5 /* free mm3 */ + movd %mm2, 8*13(%esi) /* LS part of tmt13 */ + punpckhdq %mm7, %mm2 /* free mm7 */ +/* moved up from the M3 transpose */ + movq 8*8(%esi), %mm0 +/* moved up from the M3 transpose */ + movq 8*10(%esi), %mm1 +/* moved up from the M3 transpose */ + movq %mm0, %mm3 +/* shuffle the rest of the data, and write it with 2 mmword writes */ + movq %mm5, 8*11(%esi) /* tmt11 */ +/* moved up from the M3 transpose */ + punpcklwd %mm1, %mm0 + movq %mm2, 8*15(%esi) /* tmt15 */ +/* moved up from the M3 transpose */ + punpckhwd %mm1, %mm3 +/* transpose - M3 part + * moved up to previous code section + * movq 8*8(%esi), %mm0 + * movq 8*10(%esi), %mm1 + * movq %mm0, %mm3 + * punpcklwd %mm1, %mm0 + * punpckhwd %mm1, %mm3 + */ + movq 8*12(%esi), %mm6 + movq 8*14(%esi), %mm4 + movq %mm6, %mm2 +/* shuffle the data and write the lower parts of the transposed in 4 dwords */ + punpcklwd %mm4, %mm6 + movq %mm0, %mm1 + punpckhdq %mm6, %mm1 + movq %mm3, %mm7 + punpckhwd %mm4, %mm2 /* free mm4 */ + punpckldq %mm6, %mm0 /* free mm6 */ +/* moved from next block */ + movq 8*13(%esi), %mm4 /* tmt13 */ + punpckldq %mm2, %mm3 + punpckhdq %mm2, %mm7 /* free mm2 */ +/* moved from next block */ + movq %mm3, %mm5 /* duplicate tmt5 */ +/* column 1: even part (after transpose) +* moved above +* movq %mm3, %mm5 duplicate tmt5 +* movq 8*13(%esi), %mm4 tmt13 +*/ + psubsw %mm4, %mm3 /* V134 */ + pmulhw x5a825a825a825a82, %mm3 /* 23170 ->V136 */ + movq 8*9(%esi), %mm6 /* tmt9 */ + paddsw %mm4, %mm5 /* V135 ; mm4 free */ + movq %mm0, %mm4 /* duplicate tmt1 */ + paddsw %mm6, %mm0 /* V137 */ + psubsw %mm6, %mm4 /* V138 ; mm6 free */ + psllw $2, %mm3 /* t290 */ + psubsw %mm5, %mm3 /* V139 */ + movq %mm0, %mm6 /* duplicate V137 */ + paddsw %mm5, %mm0 /* V140 */ + movq %mm4, %mm2 /* duplicate V138 */ + paddsw %mm3, %mm2 /* V141 */ + psubsw %mm3, %mm4 /* V142 ; mm3 free */ + movq %mm0, 8*9(%esi) /* V140 */ + psubsw %mm5, %mm6 /* V143 ; mm5 free */ +/* moved from next block */ + movq 8*11(%esi), %mm0 /* tmt11 */ + movq %mm2, 8*13(%esi) /* V141 */ +/* moved from next block */ + movq %mm0, %mm2 /* duplicate tmt11 */ +/* column 1: odd part (after transpose) */ +/* moved up to the prev block + * movq 8*11(%esi), %mm0 tmt11 + * movq %mm0, %mm2 duplicate tmt11 + */ + movq 8*15(%esi), %mm5 /* tmt15 */ + psubsw %mm7, %mm0 /* V144 */ + movq %mm0, %mm3 /* duplicate V144 */ + paddsw %mm7, %mm2 /* V147 ; free mm7 */ + pmulhw x539f539f539f539f, %mm0 /* 21407-> V151 */ + movq %mm1, %mm7 /* duplicate tmt3 */ + paddsw %mm5, %mm7 /* V145 */ + psubsw %mm5, %mm1 /* V146 ; free mm5 */ + psubsw %mm1, %mm3 /* V150 */ + movq %mm7, %mm5 /* duplicate V145 */ + pmulhw x4546454645464546, %mm1 /* 17734-> V153 */ + psubsw %mm2, %mm5 /* V148 */ + pmulhw x61f861f861f861f8, %mm3 /* 25080-> V154 */ + psllw $2, %mm0 /* t311 */ + pmulhw x5a825a825a825a82, %mm5 /* 23170-> V152 */ + paddsw %mm2, %mm7 /* V149 ; free mm2 */ + psllw $1, %mm1 /* t313 */ + nop /* without the nop - freeze here for one clock */ + movq %mm3, %mm2 /* duplicate V154 */ + psubsw %mm0, %mm3 /* V155 ; free mm0 */ + psubsw %mm2, %mm1 /* V156 ; free mm2 */ +/* moved from the next block */ + movq %mm6, %mm2 /* duplicate V143 */ +/* moved from the next block */ + movq 8*13(%esi), %mm0 /* V141 */ + psllw $1, %mm1 /* t315 */ + psubsw %mm7, %mm1 /* V157 (keep V149) */ + psllw $2, %mm5 /* t317 */ + psubsw %mm1, %mm5 /* V158 */ + psllw $1, %mm3 /* t319 */ + paddsw %mm5, %mm3 /* V159 */ +/* column 1: output butterfly (after transform) + * moved to the prev block + * movq %mm6, %mm2 duplicate V143 + * movq 8*13(%esi), %mm0 V141 + */ + psubsw %mm3, %mm2 /* V163 */ + paddsw %mm3, %mm6 /* V164 ; free mm3 */ + movq %mm4, %mm3 /* duplicate V142 */ + psubsw %mm5, %mm4 /* V165 ; free mm5 */ + movq %mm2, (%esp) /* out7 */ + psraw $4, %mm6 + psraw $4, %mm4 + paddsw %mm5, %mm3 /* V162 */ + movq 8*9(%esi), %mm2 /* V140 */ + movq %mm0, %mm5 /* duplicate V141 */ +/* in order not to perculate this line up, + * we read 72(%esi) very near to this location + */ + movq %mm6, 8*9(%esi) /* out9 */ + paddsw %mm1, %mm0 /* V161 */ + movq %mm3, 8(%esp) /* out5 */ + psubsw %mm1, %mm5 /* V166 ; free mm1 */ + movq %mm4, 8*11(%esi) /* out11 */ + psraw $4, %mm5 + movq %mm0, 16(%esp) /* out3 */ + movq %mm2, %mm4 /* duplicate V140 */ + movq %mm5, 8*13(%esi) /* out13 */ + paddsw %mm7, %mm2 /* V160 */ +/* moved from the next block */ + movq 8(%esi), %mm0 + psubsw %mm7, %mm4 /* V167 ; free mm7 */ +/* moved from the next block */ + movq 8*3(%esi), %mm7 + psraw $4, %mm4 + movq %mm2, 24(%esp) /* out1 */ +/* moved from the next block */ + movq %mm0, %mm1 + movq %mm4, 8*15(%esi) /* out15 */ +/* moved from the next block */ + punpcklwd %mm7, %mm0 +/* transpose - M2 parts + * moved up to the prev block + * movq 8(%esi), %mm0 + * movq 8*3(%esi), %mm7 + * movq %mm0, %mm1 + * punpcklwd %mm7, %mm0 + */ + movq 8*5(%esi), %mm5 + punpckhwd %mm7, %mm1 + movq 8*7(%esi), %mm4 + movq %mm5, %mm3 +/* shuffle the data and write the lower parts of the trasposed in 4 dwords */ + movd %mm0, 8*8(%esi) /* LS part of tmt8 */ + punpcklwd %mm4, %mm5 + movd %mm1, 8*12(%esi) /* LS part of tmt12 */ + punpckhwd %mm4, %mm3 + movd %mm5, 8*8+4(%esi) /* MS part of tmt8 */ + punpckhdq %mm5, %mm0 /* tmt10 */ + movd %mm3, 8*12+4(%esi) /* MS part of tmt12 */ + punpckhdq %mm3, %mm1 /* tmt14 */ +/* transpose - M1 parts */ + movq (%esi), %mm7 + movq 8*2(%esi), %mm2 + movq %mm7, %mm6 + movq 8*4(%esi), %mm5 + punpcklwd %mm2, %mm7 + movq 8*6(%esi), %mm4 + punpckhwd %mm2, %mm6 /* free mm2 */ + movq %mm5, %mm3 + punpcklwd %mm4, %mm5 + punpckhwd %mm4, %mm3 /* free mm4 */ + movq %mm7, %mm2 + movq %mm6, %mm4 + punpckldq %mm5, %mm7 /* tmt0 */ + punpckhdq %mm5, %mm2 /* tmt2 ; free mm5 */ +/* shuffle the rest of the data, and write it with 2 mmword writes */ + punpckldq %mm3, %mm6 /* tmt4 */ +/* moved from next block */ + movq %mm2, %mm5 /* duplicate tmt2 */ + punpckhdq %mm3, %mm4 /* tmt6 ; free mm3 */ +/* moved from next block */ + movq %mm0, %mm3 /* duplicate tmt10 */ +/* column 0: odd part (after transpose) + *moved up to prev block + * movq %mm0, %mm3 duplicate tmt10 + * movq %mm2, %mm5 duplicate tmt2 + */ + psubsw %mm4, %mm0 /* V110 */ + paddsw %mm4, %mm3 /* V113 ; free mm4 */ + movq %mm0, %mm4 /* duplicate V110 */ + paddsw %mm1, %mm2 /* V111 */ + pmulhw x539f539f539f539f, %mm0 /* 21407-> V117 */ + psubsw %mm1, %mm5 /* V112 ; free mm1 */ + psubsw %mm5, %mm4 /* V116 */ + movq %mm2, %mm1 /* duplicate V111 */ + pmulhw x4546454645464546, %mm5 /* 17734-> V119 */ + psubsw %mm3, %mm2 /* V114 */ + pmulhw x61f861f861f861f8, %mm4 /* 25080-> V120 */ + paddsw %mm3, %mm1 /* V115 ; free mm3 */ + pmulhw x5a825a825a825a82, %mm2 /* 23170-> V118 */ + psllw $2, %mm0 /* t266 */ + movq %mm1, (%esi) /* save V115 */ + psllw $1, %mm5 /* t268 */ + psubsw %mm4, %mm5 /* V122 */ + psubsw %mm0, %mm4 /* V121 ; free mm0 */ + psllw $1, %mm5 /* t270 */ + psubsw %mm1, %mm5 /* V123 ; free mm1 */ + psllw $2, %mm2 /* t272 */ + psubsw %mm5, %mm2 /* V124 (keep V123) */ + psllw $1, %mm4 /* t274 */ + movq %mm5, 8*2(%esi) /* save V123 ; free mm5 */ + paddsw %mm2, %mm4 /* V125 (keep V124) */ +/* column 0: even part (after transpose) */ + movq 8*12(%esi), %mm0 /* tmt12 */ + movq %mm6, %mm3 /* duplicate tmt4 */ + psubsw %mm0, %mm6 /* V100 */ + paddsw %mm0, %mm3 /* V101 ; free mm0 */ + pmulhw x5a825a825a825a82, %mm6 /* 23170 ->V102 */ + movq %mm7, %mm5 /* duplicate tmt0 */ + movq 8*8(%esi), %mm1 /* tmt8 */ + paddsw %mm1, %mm7 /* V103 */ + psubsw %mm1, %mm5 /* V104 ; free mm1 */ + movq %mm7, %mm0 /* duplicate V103 */ + psllw $2, %mm6 /* t245 */ + paddsw %mm3, %mm7 /* V106 */ + movq %mm5, %mm1 /* duplicate V104 */ + psubsw %mm3, %mm6 /* V105 */ + psubsw %mm3, %mm0 /* V109; free mm3 */ + paddsw %mm6, %mm5 /* V107 */ + psubsw %mm6, %mm1 /* V108 ; free mm6 */ +/* column 0: output butterfly (after transform) */ + movq %mm1, %mm3 /* duplicate V108 */ + paddsw %mm2, %mm1 /* out4 */ + psraw $4, %mm1 + psubsw %mm2, %mm3 /* out10 ; free mm2 */ + psraw $4, %mm3 + movq %mm0, %mm6 /* duplicate V109 */ + movq %mm1, 8*4(%esi) /* out4 ; free mm1 */ + psubsw %mm4, %mm0 /* out6 */ + movq %mm3, 8*10(%esi) /* out10 ; free mm3 */ + psraw $4, %mm0 + paddsw %mm4, %mm6 /* out8 ; free mm4 */ + movq %mm7, %mm1 /* duplicate V106 */ + movq %mm0, 8*6(%esi) /* out6 ; free mm0 */ + psraw $4, %mm6 + movq (%esi), %mm4 /* V115 */ + movq %mm6, 8*8(%esi) /* out8 ; free mm6 */ + movq %mm5, %mm2 /* duplicate V107 */ + movq 8*2(%esi), %mm3 /* V123 */ + paddsw %mm4, %mm7 /* out0 */ +/* moved up from next block */ + movq 16(%esp), %mm0 + psraw $4, %mm7 +/* moved up from next block */ + movq 8(%esp), %mm6 + psubsw %mm4, %mm1 /* out14 ; free mm4 */ + paddsw %mm3, %mm5 /* out2 */ + psraw $4, %mm1 + movq %mm7, (%esi) /* out0 ; free mm7 */ + psraw $4, %mm5 + movq %mm1, 8*14(%esi) /* out14 ; free mm1 */ + psubsw %mm3, %mm2 /* out12 ; free mm3 */ + movq %mm5, 8*2(%esi) /* out2 ; free mm5 */ + psraw $4, %mm2 +/* moved up to the prev block */ + movq (%esp), %mm4 +/* moved up to the prev block */ + psraw $4, %mm0 + movq %mm2, 8*12(%esi) /* out12 ; free mm2 */ +/* moved up to the prev block */ + psraw $4, %mm6 +/* move back the data to its correct place +* moved up to the prev block + * movq 16(%esp), %mm0 + * movq 8(%esp), %mm6 + * movq (%esp), %mm4 + * psraw $4, %mm0 + * psraw $4, %mm6 +*/ + movq 24(%esp), %mm1 + psraw $4, %mm4 + movq %mm0, 8*3(%esi) /* out3 */ + psraw $4, %mm1 + movq %mm6, 8*5(%esi) /* out5 */ + movq %mm4, 8*7(%esi) /* out7 */ + movq %mm1, 8(%esi) /* out1 */ + + popl %edi /* Pop off the temp variables */ + popl %edi + popl %edi + popl %edi + popl %edi + popl %edi + popl %edi + popl %edi + + popl %edi /* Pop off the old variables */ + popl %esi + popl %edx + popl %ecx + popl %ebx + movl %ebp, %esp + popl %ebp + + ret +.Lfe1: + .size IDCT_mmx,.Lfe1-IDCT_mmx diff --git a/core/multimedia/opieplayer/libmpeg3/video/mmxtest.c b/core/multimedia/opieplayer/libmpeg3/video/mmxtest.c new file mode 100644 index 0000000..567f139 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/mmxtest.c @@ -0,0 +1,35 @@ +#include "../libmpeg3.h" +#include "../mpeg3protos.h" + +#include <stdio.h> +#include <string.h> + +int mpeg3_mmx_test() +{ + int result = 0; + FILE *proc; + char string[MPEG3_STRLEN]; + + +#ifdef HAVE_MMX + if(!(proc = fopen(MPEG3_PROC_CPUINFO, "r"))) + { + return 0; + } + + while(!feof(proc)) + { + fgets(string, MPEG3_STRLEN, proc); +/* Got the flags line */ + if(!strncmp(string, "flags", 5)) + { + char *needle; + needle = strstr(string, "mmx"); + if(!needle) return 0; + if(!strncmp(needle, "mmx", 3)) return 1; + } + } +#endif + + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/motion.c b/core/multimedia/opieplayer/libmpeg3/video/motion.c new file mode 100644 index 0000000..4d2f681 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/motion.c @@ -0,0 +1,230 @@ +#include "mpeg3video.h" +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "vlc.h" + +#include <stdio.h> + + +/* calculate motion vector component */ + +static inline void mpeg3video_calc_mv(int *pred, int r_size, int motion_code, int motion_r, int full_pel_vector) +{ + int lim = 16 << r_size; + int vec = full_pel_vector ? (*pred >> 1) : (*pred); + + if(motion_code > 0) + { + vec += ((motion_code - 1) << r_size) + motion_r + 1; + if(vec >= lim) vec -= lim + lim; + } + else + if(motion_code < 0) + { + vec -= ((-motion_code - 1) << r_size) + motion_r + 1; + if(vec < -lim) vec += lim + lim; + } + *pred = full_pel_vector ? (vec << 1) : vec; +} + + +/* +int *dmvector, * differential motion vector * +int mvx, int mvy * decoded mv components (always in field format) * +*/ +void mpeg3video_calc_dmv(mpeg3video_t *video, + int DMV[][2], + int *dmvector, + int mvx, + int mvy) +{ + if(video->pict_struct == FRAME_PICTURE) + { + if(video->topfirst) + { +/* vector for prediction of top field from bottom field */ + DMV[0][0] = ((mvx + (mvx>0)) >> 1) + dmvector[0]; + DMV[0][1] = ((mvy + (mvy>0)) >> 1) + dmvector[1] - 1; + +/* vector for prediction of bottom field from top field */ + DMV[1][0] = ((3 * mvx + (mvx > 0)) >> 1) + dmvector[0]; + DMV[1][1] = ((3 * mvy + (mvy > 0)) >> 1) + dmvector[1] + 1; + } + else + { +/* vector for prediction of top field from bottom field */ + DMV[0][0] = ((3 * mvx + (mvx>0)) >> 1) + dmvector[0]; + DMV[0][1] = ((3 * mvy + (mvy>0)) >> 1) + dmvector[1] - 1; + +/* vector for prediction of bottom field from top field */ + DMV[1][0] = ((mvx + (mvx>0)) >> 1) + dmvector[0]; + DMV[1][1] = ((mvy + (mvy>0)) >> 1) + dmvector[1] + 1; + } + } + else + { +/* vector for prediction from field of opposite 'parity' */ + DMV[0][0] = ((mvx + (mvx > 0)) >> 1) + dmvector[0]; + DMV[0][1] = ((mvy + (mvy > 0)) >> 1) + dmvector[1]; + +/* correct for vertical field shift */ + if(video->pict_struct == TOP_FIELD) + DMV[0][1]--; + else + DMV[0][1]++; + } +} + +static inline int mpeg3video_get_mv(mpeg3_slice_t *slice) +{ + int code; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + + if(mpeg3slice_getbit(slice_buffer)) + { + return 0; + } + + if((code = mpeg3slice_showbits9(slice_buffer)) >= 64) + { + code >>= 6; + mpeg3slice_flushbits(slice_buffer, mpeg3_MVtab0[code].len); + return mpeg3slice_getbit(slice_buffer) ? -mpeg3_MVtab0[code].val : mpeg3_MVtab0[code].val; + } + + if(code >= 24) + { + code >>= 3; + mpeg3slice_flushbits(slice_buffer, mpeg3_MVtab1[code].len); + return mpeg3slice_getbit(slice_buffer) ? -mpeg3_MVtab1[code].val : mpeg3_MVtab1[code].val; + } + + if((code -= 12) < 0) + { +/* fprintf(stdout,"mpeg3video_get_mv: invalid motion_vector code\n"); */ + slice->fault = 1; + return 1; + } + + mpeg3slice_flushbits(slice_buffer, mpeg3_MVtab2[code].len); + return mpeg3slice_getbit(slice_buffer) ? -mpeg3_MVtab2[code].val : mpeg3_MVtab2[code].val; +} + +/* get differential motion vector (for dual prime prediction) */ + +static inline int mpeg3video_get_dmv(mpeg3_slice_t *slice) +{ + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + if(mpeg3slice_getbit(slice_buffer)) + { + return mpeg3slice_getbit(slice_buffer) ? -1 : 1; + } + else + { + return 0; + } +} + + + +/* get and decode motion vector and differential motion vector */ + +void mpeg3video_motion_vector(mpeg3_slice_t *slice, + mpeg3video_t *video, + int *PMV, + int *dmvector, + int h_r_size, + int v_r_size, + int dmv, + int mvscale, + int full_pel_vector) +{ + int motion_r; + int motion_code = mpeg3video_get_mv(slice); + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + + if(slice->fault) return; + motion_r = (h_r_size != 0 && motion_code != 0) ? mpeg3slice_getbits(slice_buffer, h_r_size) : 0; + + mpeg3video_calc_mv(&PMV[0], h_r_size, motion_code, motion_r, full_pel_vector); + + if(dmv) dmvector[0] = mpeg3video_get_dmv(slice); + + motion_code = mpeg3video_get_mv(slice); + if(slice->fault) return; + motion_r = (v_r_size != 0 && motion_code != 0) ? mpeg3slice_getbits(slice_buffer, v_r_size) : 0; + +/* DIV 2 */ + if(mvscale) PMV[1] >>= 1; + + mpeg3video_calc_mv(&PMV[1], v_r_size, motion_code, motion_r, full_pel_vector); + + if(mvscale) PMV[1] <<= 1; + if(dmv) dmvector[1] = mpeg3video_get_dmv(slice); +} + +int mpeg3video_motion_vectors(mpeg3_slice_t *slice, + mpeg3video_t *video, + int PMV[2][2][2], + int dmvector[2], + int mv_field_sel[2][2], + int s, + int mv_count, + int mv_format, + int h_r_size, + int v_r_size, + int dmv, + int mvscale) +{ + int result = 0; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + if(mv_count == 1) + { + if(mv_format == MV_FIELD && !dmv) + { + mv_field_sel[1][s] = mv_field_sel[0][s] = mpeg3slice_getbit(slice_buffer); + } + + mpeg3video_motion_vector(slice, + video, + PMV[0][s], + dmvector, + h_r_size, + v_r_size, + dmv, + mvscale, + 0); + if(slice->fault) return 1; + +/* update other motion vector predictors */ + PMV[1][s][0] = PMV[0][s][0]; + PMV[1][s][1] = PMV[0][s][1]; + } + else + { + mv_field_sel[0][s] = mpeg3slice_getbit(slice_buffer); + mpeg3video_motion_vector(slice, + video, + PMV[0][s], + dmvector, + h_r_size, + v_r_size, + dmv, + mvscale, + 0); + if(slice->fault) return 1; + + mv_field_sel[1][s] = mpeg3slice_getbit(slice_buffer); + mpeg3video_motion_vector(slice, + video, + PMV[1][s], + dmvector, + h_r_size, + v_r_size, + dmv, + mvscale, + 0); + if(slice->fault) return 1; + } + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.c b/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.c new file mode 100644 index 0000000..a9f113e --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.c @@ -0,0 +1,597 @@ +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" +#include "mpeg3videoprotos.h" +#include <stdlib.h> + +unsigned char mpeg3_zig_zag_scan_mmx[64] = +{ + 0*8+0 /* 0*/, 1*8+0 /* 1*/, 0*8+1 /* 8*/, 0*8+2 /*16*/, 1*8+1 /* 9*/, 2*8+0 /* 2*/, 3*8+0 /* 3*/, 2*8+1 /*10*/, + 1*8+2 /*17*/, 0*8+3 /*24*/, 0*8+4 /*32*/, 1*8+3 /*25*/, 2*8+2 /*18*/, 3*8+1 /*11*/, 4*8+0 /* 4*/, 5*8+0 /* 5*/, + 4*8+1 /*12*/, 5*8+2 /*19*/, 2*8+3 /*26*/, 1*8+4 /*33*/, 0*8+5 /*40*/, 0*8+6 /*48*/, 1*8+5 /*41*/, 2*8+4 /*34*/, + 3*8+3 /*27*/, 4*8+2 /*20*/, 5*8+1 /*13*/, 6*8+0 /* 6*/, 7*8+0 /* 7*/, 6*8+1 /*14*/, 5*8+2 /*21*/, 4*8+3 /*28*/, + 3*8+4 /*35*/, 2*8+5 /*42*/, 1*8+6 /*49*/, 0*8+7 /*56*/, 1*8+7 /*57*/, 2*8+6 /*50*/, 3*8+5 /*43*/, 4*8+4 /*36*/, + 5*8+3 /*29*/, 6*8+2 /*22*/, 7*8+1 /*15*/, 7*8+2 /*23*/, 6*8+3 /*30*/, 5*8+4 /*37*/, 4*8+5 /*44*/, 3*8+6 /*51*/, + 2*8+7 /*58*/, 3*8+7 /*59*/, 4*8+6 /*52*/, 5*8+5 /*45*/, 6*8+4 /*38*/, 7*8+3 /*31*/, 7*8+4 /*39*/, 6*8+5 /*46*/, + 7*8+6 /*53*/, 4*8+7 /*60*/, 5*8+7 /*61*/, 6*8+6 /*54*/, 7*8+5 /*47*/, 7*8+6 /*55*/, 6*8+7 /*62*/, 7*8+7 /*63*/ +}; + +/* alternate scan */ +unsigned char mpeg3_alternate_scan_mmx[64] = +{ + 0*8+0 /*0 */, 0*8+1 /* 8*/, 0*8+2 /*16*/, 0*8+3 /*24*/, 1*8+0 /* 1*/, 1*8+1 /* 9*/, 2*8+0 /* 2*/, 2*8+1 /*10*/, + 1*8+2 /*17*/, 1*8+3 /*25*/, 0*8+4 /*32*/, 0*8+5 /*40*/, 0*8+6 /*48*/, 0*8+7 /*56*/, 1*8+7 /*57*/, 1*8+6 /*49*/, + 1*8+5 /*41*/, 1*8+4 /*33*/, 2*8+3 /*26*/, 2*8+2 /*18*/, 3*8+0 /* 3*/, 3*8+1 /*11*/, 4*8+0 /* 4*/, 4*8+1 /*12*/, + 3*8+2 /*19*/, 3*8+3 /*27*/, 2*8+4 /*34*/, 2*8+5 /*42*/, 2*8+6 /*50*/, 2*8+7 /*58*/, 3*8+4 /*35*/, 3*8+5 /*43*/, + 3*8+6 /*51*/, 3*8+7 /*59*/, 4*8+2 /*20*/, 4*8+3 /*28*/, 5*8+0 /* 5*/, 5*8+1 /*13*/, 6*8+0 /* 6*/, 6*8+1 /*14*/, + 5*8+2 /*21*/, 5*8+3 /*29*/, 4*8+4 /*36*/, 4*8+5 /*44*/, 4*8+6 /*52*/, 4*8+7 /*60*/, 5*8+4 /*37*/, 5*8+5 /*45*/, + 5*8+6 /*53*/, 5*8+7 /*61*/, 6*8+2 /*22*/, 6*8+3 /*30*/, 7*8+0 /* 7*/, 7*8+1 /*15*/, 7*8+2 /*23*/, 7*8+3 /*31*/, + 6*8+4 /*38*/, 6*8+5 /*46*/, 6*8+6 /*54*/, 6*8+7 /*62*/, 7*8+4 /*39*/, 7*8+5 /*47*/, 7*8+6 /*55*/, 7*8+6 /*63*/ +}; + + + +/* zig-zag scan */ +unsigned char mpeg3_zig_zag_scan_nommx[64] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + +/* alternate scan */ +unsigned char mpeg3_alternate_scan_nommx[64] = +{ + 0, 8, 16, 24, 1, 9, 2, 10, 17, 25, 32, 40, 48, 56, 57, 49, + 41, 33, 26, 18, 3, 11, 4, 12, 19, 27, 34, 42, 50, 58, 35, 43, + 51, 59, 20, 28, 5, 13, 6, 14, 21, 29, 36, 44, 52, 60, 37, 45, + 53, 61, 22, 30, 7, 15, 23, 31, 38, 46, 54, 62, 39, 47, 55, 63 +}; + +/* default intra quantization matrix */ +unsigned char mpeg3_default_intra_quantizer_matrix[64] = +{ + 8, 16, 19, 22, 26, 27, 29, 34, + 16, 16, 22, 24, 27, 29, 34, 37, + 19, 22, 26, 27, 29, 34, 34, 38, + 22, 22, 26, 27, 29, 34, 37, 40, + 22, 26, 27, 29, 32, 35, 40, 48, + 26, 27, 29, 32, 35, 40, 48, 58, + 26, 27, 29, 34, 38, 46, 56, 69, + 27, 29, 35, 38, 46, 56, 69, 83 +}; + +unsigned char mpeg3_non_linear_mquant_table[32] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 10, 12, 14, 16, 18, 20, 22, + 24, 28, 32, 36, 40, 44, 48, 52, + 56, 64, 72, 80, 88, 96, 104, 112 +}; + +double mpeg3_frame_rate_table[16] = +{ + 0.0, /* Pad */ + 24000.0/1001.0, /* Official frame rates */ + 24.0, + 25.0, + 30000.0/1001.0, + 30.0, + 50.0, + ((60.0*1000.0)/1001.0), + 60.0, + + 1, /* Unofficial economy rates */ + 5, + 10, + 12, + 15, + 0, + 0, +}; + +int mpeg3video_initdecoder(mpeg3video_t *video) +{ + int blk_cnt_tab[3] = {6, 8, 12}; + int cc; + int i; + long size[4], padding[2]; /* Size of Y, U, and V buffers */ + + if(!video->mpeg2) + { +/* force MPEG-1 parameters */ + video->prog_seq = 1; + video->prog_frame = 1; + video->pict_struct = FRAME_PICTURE; + video->frame_pred_dct = 1; + video->chroma_format = CHROMA420; + video->matrix_coefficients = 5; + } + +/* Get dimensions rounded to nearest multiple of coded macroblocks */ + video->mb_width = (video->horizontal_size + 15) / 16; + video->mb_height = (video->mpeg2 && !video->prog_seq) ? + (2 * ((video->vertical_size + 31) / 32)) : + ((video->vertical_size + 15) / 16); + video->coded_picture_width = 16 * video->mb_width; + video->coded_picture_height = 16 * video->mb_height; + video->chrom_width = (video->chroma_format == CHROMA444) ? + video->coded_picture_width : + (video->coded_picture_width >> 1); + video->chrom_height = (video->chroma_format != CHROMA420) ? + video->coded_picture_height : + (video->coded_picture_height >> 1); + video->blk_cnt = blk_cnt_tab[video->chroma_format - 1]; + +/* Get sizes of YUV buffers */ + padding[0] = 16 * video->coded_picture_width; + size[0] = video->coded_picture_width * video->coded_picture_height + padding[0] * 2; + + padding[1] = 16 * video->chrom_width; + size[1] = video->chrom_width * video->chrom_height + 2 * padding[1]; + + size[2] = (video->llw * video->llh); + size[3] = (video->llw * video->llh) / 4; + +/* Allocate contiguous fragments for YUV buffers for hardware YUV decoding */ + video->yuv_buffer[0] = (unsigned char*)calloc(1, (size[0] + padding[0]) + 2 * (size[1] + padding[1])); + video->yuv_buffer[1] = (unsigned char*)calloc(1, (size[0] + padding[0]) + 2 * (size[1] + padding[1])); + video->yuv_buffer[2] = (unsigned char*)calloc(1, (size[0] + padding[0]) + 2 * (size[1] + padding[1])); + + if(video->scalable_mode == SC_SPAT) + { + video->yuv_buffer[3] = (unsigned char*)calloc(1, size[2] + 2 * size[3]); + video->yuv_buffer[4] = (unsigned char*)calloc(1, size[2] + 2 * size[3]); + } + +/* Direct pointers to areas of contiguous fragments in YVU order per Microsoft */ + for(cc = 0; cc < 3; cc++) + { + video->llframe0[cc] = 0; + video->llframe1[cc] = 0; + video->newframe[cc] = 0; + } + + video->refframe[0] = video->yuv_buffer[0]; + video->oldrefframe[0] = video->yuv_buffer[1]; + video->auxframe[0] = video->yuv_buffer[2]; + video->refframe[2] = video->yuv_buffer[0] + size[0] + padding[0]; + video->oldrefframe[2] = video->yuv_buffer[1] + size[0] + padding[0]; + video->auxframe[2] = video->yuv_buffer[2] + size[0] + padding[0]; + video->refframe[1] = video->yuv_buffer[0] + size[0] + padding[0] + size[1] + padding[1]; + video->oldrefframe[1] = video->yuv_buffer[1] + size[0] + padding[0] + size[1] + padding[1]; + video->auxframe[1] = video->yuv_buffer[2] + size[0] + padding[0] + size[1] + padding[1]; + + if(video->scalable_mode == SC_SPAT) + { +/* this assumes lower layer is 4:2:0 */ + video->llframe0[0] = video->yuv_buffer[3] + padding[0] ; + video->llframe1[0] = video->yuv_buffer[4] + padding[0] ; + video->llframe0[2] = video->yuv_buffer[3] + padding[1] + size[2] ; + video->llframe1[2] = video->yuv_buffer[4] + padding[1] + size[2] ; + video->llframe0[1] = video->yuv_buffer[3] + padding[1] + size[2] + size[3]; + video->llframe1[1] = video->yuv_buffer[4] + padding[1] + size[2] + size[3]; + } + +/* Initialize the YUV tables for software YUV decoding */ + video->cr_to_r = (long*)malloc(sizeof(long) * 256); + video->cr_to_g = (long*)malloc(sizeof(long) * 256); + video->cb_to_g = (long*)malloc(sizeof(long) * 256); + video->cb_to_b = (long*)malloc(sizeof(long) * 256); + video->cr_to_r_ptr = video->cr_to_r + 128; + video->cr_to_g_ptr = video->cr_to_g + 128; + video->cb_to_g_ptr = video->cb_to_g + 128; + video->cb_to_b_ptr = video->cb_to_b + 128; + + for(i = -128; i < 128; i++) + { + video->cr_to_r_ptr[i] = (long)( 1.371 * 65536 * i); + video->cr_to_g_ptr[i] = (long)(-0.698 * 65536 * i); + video->cb_to_g_ptr[i] = (long)(-0.336 * 65536 * i); + video->cb_to_b_ptr[i] = (long)( 1.732 * 65536 * i); + } + + return 0; +} + +int mpeg3video_deletedecoder(mpeg3video_t *video) +{ + int i, padding; + + free(video->yuv_buffer[0]); + free(video->yuv_buffer[1]); + free(video->yuv_buffer[2]); + + if(video->llframe0[0]) + { + free(video->yuv_buffer[3]); + free(video->yuv_buffer[4]); + } + + free(video->cr_to_r); + free(video->cr_to_g); + free(video->cb_to_g); + free(video->cb_to_b); + return 0; +} + +void mpeg3video_init_scantables(mpeg3video_t *video) +{ +#ifdef HAVE_MMX + if(video->have_mmx) + { + video->mpeg3_zigzag_scan_table = mpeg3_zig_zag_scan_mmx; + video->mpeg3_alternate_scan_table = mpeg3_alternate_scan_mmx; + } + else +#endif + { + video->mpeg3_zigzag_scan_table = mpeg3_zig_zag_scan_nommx; + video->mpeg3_alternate_scan_table = mpeg3_alternate_scan_nommx; + } +} + +mpeg3video_t* mpeg3video_allocate_struct(mpeg3_t *file, mpeg3_vtrack_t *track) +{ + int i; + mpeg3video_t *video = (mpeg3video_t*)calloc(1, sizeof(mpeg3video_t)); + pthread_mutexattr_t mutex_attr; + + video->file = file; + video->track = track; + video->vstream = mpeg3bits_new_stream(file, track->demuxer); + video->last_number = -1; + +/* First frame is all green */ + video->framenum = -1; + video->have_mmx = file->have_mmx; + + video->percentage_seek = -1; + video->frame_seek = -1; + + mpeg3video_init_scantables(video); + mpeg3video_init_output(); + + pthread_mutexattr_init(&mutex_attr); + pthread_mutex_init(&(video->test_lock), &mutex_attr); + pthread_mutex_init(&(video->slice_lock), &mutex_attr); + return video; +} + +int mpeg3video_delete_struct(mpeg3video_t *video) +{ + int i; + mpeg3bits_delete_stream(video->vstream); + pthread_mutex_destroy(&(video->test_lock)); + pthread_mutex_destroy(&(video->slice_lock)); + if(video->x_table) + { + free(video->x_table); + free(video->y_table); + } + if(video->total_slice_decoders) + { + for(i = 0; i < video->total_slice_decoders; i++) + mpeg3_delete_slice_decoder(&video->slice_decoders[i]); + } + for(i = 0; i < video->slice_buffers_initialized; i++) + mpeg3_delete_slice_buffer(&(video->slice_buffers[i])); + + free(video); +} + + +int mpeg3video_read_frame_backend(mpeg3video_t *video, int skip_bframes) +{ + int result = 0; + + if(mpeg3bits_eof(video->vstream)) result = 1; + + if(!result) result = mpeg3video_get_header(video, 0); + +//printf("frame type %d\n", video->pict_type); +/* skip_bframes is the number of bframes we can skip successfully. */ +/* This is in case a skipped B-frame is repeated and the second repeat happens */ +/* to be a B frame we need. */ + video->skip_bframes = skip_bframes; + + if(!result) + result = mpeg3video_getpicture(video, video->framenum); + +#ifdef HAVE_MMX + if(video->have_mmx) + __asm__ __volatile__ ("emms"); +#endif + + if(!result) + { + video->last_number = video->framenum; + video->framenum++; + } + return result; +} + +int* mpeg3video_get_scaletable(int input_w, int output_w) +{ + int *result = (int*)malloc(sizeof(int) * output_w); + float i; + float scale = (float)input_w / output_w; + for(i = 0; i < output_w; i++) + { + result[(int)i] = (int)(scale * i); + } + return result; +} + +/* Get the first frame read. */ +int mpeg3video_get_firstframe(mpeg3video_t *video) +{ + int result = 0; + if(video->framenum < 0) + { + video->repeat_count = video->current_repeat = 0; + result = mpeg3video_read_frame_backend(video, 0); + mpeg3bits_seek_byte(video->vstream, 0); + mpeg3video_match_refframes(video); + } + return result; +} + + +/* ======================================================================= */ +/* ENTRY POINTS */ +/* ======================================================================= */ + + + +mpeg3video_t* mpeg3video_new(mpeg3_t *file, mpeg3_vtrack_t *track) +{ + mpeg3video_t *video; + int result = 0; + + video = mpeg3video_allocate_struct(file, track); + result = mpeg3video_get_header(video, 1); + + if(!result) + { + int hour, minute, second, frame; + int gop_found; + + mpeg3video_initdecoder(video); + video->decoder_initted = 1; + track->width = video->horizontal_size; + track->height = video->vertical_size; + track->frame_rate = video->frame_rate; + +/* Get the length of the file from an elementary stream */ + if(file->is_video_stream) + { +/* Load the first GOP */ + mpeg3bits_seek_start(video->vstream); + result = mpeg3video_next_code(video->vstream, MPEG3_GOP_START_CODE); + if(!result) mpeg3bits_getbits(video->vstream, 32); + if(!result) result = mpeg3video_getgophdr(video); + + hour = video->gop_timecode.hour; + minute = video->gop_timecode.minute; + second = video->gop_timecode.second; + frame = video->gop_timecode.frame; + video->first_frame = (long)(hour * 3600 * video->frame_rate + + minute * 60 * video->frame_rate + + second * video->frame_rate + + frame); + +/* GOPs always have 16 frames */ + video->frames_per_gop = 16; + +/* Read the last GOP in the file by seeking backward. */ + mpeg3bits_seek_end(video->vstream); + mpeg3bits_start_reverse(video->vstream); + result = mpeg3video_prev_code(video->vstream, MPEG3_GOP_START_CODE); + mpeg3bits_start_forward(video->vstream); + mpeg3bits_getbits(video->vstream, 8); + if(!result) result = mpeg3video_getgophdr(video); + + hour = video->gop_timecode.hour; + minute = video->gop_timecode.minute; + second = video->gop_timecode.second; + frame = video->gop_timecode.frame; + + video->last_frame = (long)(hour * 3600 * video->frame_rate + + minute * 60 * video->frame_rate + + second * video->frame_rate + + frame); + +/* Count number of frames to end */ + while(!result) + { + result = mpeg3video_next_code(video->vstream, MPEG3_PICTURE_START_CODE); + if(!result) + { + mpeg3bits_getbyte_noptr(video->vstream); + video->last_frame++; + } + } + + track->total_frames = video->last_frame - video->first_frame + 1; + mpeg3bits_seek_start(video->vstream); + } + else + { +/* Gross approximation from a multiplexed file. */ + video->first_frame = 0; + track->total_frames = video->last_frame = + (long)(mpeg3demux_length(video->vstream->demuxer) * + video->frame_rate); + video->first_frame = 0; + } + + video->maxframe = track->total_frames; + mpeg3bits_seek_start(video->vstream); + } + else + { + mpeg3video_delete(video); + video = 0; + } + + return video; +} + +int mpeg3video_delete(mpeg3video_t *video) +{ + if(video->decoder_initted) + { + mpeg3video_deletedecoder(video); + } + mpeg3video_delete_struct(video); + return 0; +} + +int mpeg3video_set_cpus(mpeg3video_t *video, int cpus) +{ + return 0; +} + +int mpeg3video_set_mmx(mpeg3video_t *video, int use_mmx) +{ + video->have_mmx = use_mmx; + mpeg3video_init_scantables(video); + return 0; +} + +int mpeg3video_seek_percentage(mpeg3video_t *video, double percentage) +{ + video->percentage_seek = percentage; + return 0; +} + +int mpeg3video_previous_frame(mpeg3video_t *video) +{ + if(mpeg3bits_tell_percentage(video->vstream) <= 0) return 1; + mpeg3bits_start_reverse(video->vstream); + mpeg3video_prev_code(video->vstream, MPEG3_PICTURE_START_CODE); + mpeg3bits_getbits_reverse(video->vstream, 32); + + if(mpeg3bits_bof(video->vstream)) mpeg3bits_seek_percentage(video->vstream, 0); + mpeg3bits_start_forward(video->vstream); + video->repeat_count = 0; + return 0; +} + +int mpeg3video_seek_frame(mpeg3video_t *video, long frame) +{ + video->frame_seek = frame; + return 0; +} + +/* Read all the way up to and including the next picture start code */ +int mpeg3video_read_raw(mpeg3video_t *video, unsigned char *output, long *size, long max_size) +{ + unsigned MPEG3_INT32 code = 0; + mpeg3_bits_t *vstream = video->vstream; + + *size = 0; + while(code != MPEG3_PICTURE_START_CODE && + code != MPEG3_SEQUENCE_END_CODE && + *size < max_size && + !mpeg3bits_eof(vstream)) + { + code <<= 8; + *output = mpeg3bits_getbyte_noptr(vstream); + code |= *output++; + (*size)++; + } + return mpeg3bits_eof(vstream); +} + +int mpeg3video_read_frame(mpeg3video_t *video, + long frame_number, + unsigned char **output_rows, + int in_x, + int in_y, + int in_w, + int in_h, + int out_w, + int out_h, + int color_model) +{ + int result = 0; + + video->want_yvu = 0; + video->output_rows = output_rows; + video->color_model = color_model; + +/* Get scaling tables */ + if(video->out_w != out_w || video->out_h != out_h || + video->in_w != in_w || video->in_h != in_h || + video->in_x != in_x || video->in_y != in_y) + { + if(video->x_table) + { + free(video->x_table); + free(video->y_table); + video->x_table = 0; + video->y_table = 0; + } + } + + video->out_w = out_w; + video->out_h = out_h; + video->in_w = in_w; + video->in_h = in_h; + video->in_x = in_x; + video->in_y = in_y; + + if(!video->x_table) + { + video->x_table = mpeg3video_get_scaletable(video->in_w, video->out_w); + video->y_table = mpeg3video_get_scaletable(video->in_h, video->out_h); + } + + mpeg3video_get_firstframe(video); + + if(!result) result = mpeg3video_seek(video); + + if(!result) result = mpeg3video_read_frame_backend(video, 0); + + if(video->output_src) mpeg3video_present_frame(video); + + video->percentage_seek = -1; + return result; +} + +int mpeg3video_read_yuvframe(mpeg3video_t *video, + long frame_number, + char *y_output, + char *u_output, + char *v_output, + int in_x, + int in_y, + int in_w, + int in_h) +{ + int result = 0; + + video->want_yvu = 1; + video->y_output = y_output; + video->u_output = u_output; + video->v_output = v_output; + video->in_x = in_x; + video->in_y = in_y; + video->in_w = in_w; + video->in_h = in_h; + + mpeg3video_get_firstframe(video); + + if(!result) result = mpeg3video_seek(video); + + if(!result) result = mpeg3video_read_frame_backend(video, 0); + + if(video->output_src) mpeg3video_present_frame(video); + + video->want_yvu = 0; + video->percentage_seek = -1; + return result; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.h b/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.h new file mode 100644 index 0000000..2db62b0 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/mpeg3video.h @@ -0,0 +1,180 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEGVIDEO_H +#define MPEGVIDEO_H + +#include "../bitstream.h" +#include "../mpeg3private.inc" +#include "idct.h" +#include "slice.h" +#include "../timecode.h" + +/* zig-zag scan */ +extern unsigned char mpeg3_zig_zag_scan_nommx[64]; +extern unsigned char mpeg3_zig_zag_scan_mmx[64]; + +/* alternate scan */ +extern unsigned char mpeg3_alternate_scan_nommx[64]; +extern unsigned char mpeg3_alternate_scan_mmx[64]; + +/* default intra quantization matrix */ +extern unsigned char mpeg3_default_intra_quantizer_matrix[64]; + +/* Frame rate table must agree with the one in the encoder */ +extern double mpeg3_frame_rate_table[16]; + +/* non-linear quantization coefficient table */ +extern unsigned char mpeg3_non_linear_mquant_table[32]; + +#define CHROMA420 1 /* chroma_format */ +#define CHROMA422 2 +#define CHROMA444 3 + +#define TOP_FIELD 1 /* picture structure */ +#define BOTTOM_FIELD 2 +#define FRAME_PICTURE 3 + +#define SEQ_ID 1 /* extension start code IDs */ +#define DISP_ID 2 +#define QUANT_ID 3 +#define SEQSCAL_ID 5 +#define PANSCAN_ID 7 +#define CODING_ID 8 +#define SPATSCAL_ID 9 +#define TEMPSCAL_ID 10 + +#define ERROR (-1) + +#define SC_NONE 0 /* scalable_mode */ +#define SC_DP 1 +#define SC_SPAT 2 +#define SC_SNR 3 +#define SC_TEMP 4 + +#define I_TYPE 1 /* picture coding type */ +#define P_TYPE 2 +#define B_TYPE 3 +#define D_TYPE 4 + +#define MB_INTRA 1 /* macroblock type */ +#define MB_PATTERN 2 +#define MB_BACKWARD 4 +#define MB_FORWARD 8 +#define MB_QUANT 16 +#define MB_WEIGHT 32 +#define MB_CLASS4 64 + +#define MC_FIELD 1 /* motion_type */ +#define MC_FRAME 2 +#define MC_16X8 2 +#define MC_DMV 3 + +#define MV_FIELD 0 /* mv_format */ +#define MV_FRAME 1 + +#define CLIP(x) ((x) >= 0 ? ((x) < 255 ? (x) : 255) : 0) + +/* Statically allocate as little as possible so a fake video struct */ +/* can be used for reading the GOP headers. */ + +struct mpeg3video_rec +{ + struct mpeg3_rec* file; + struct mpeg3_vtrack_rec* track; + +/* ================================= Seeking variables ========================= */ + mpeg3_bits_t *vstream; + int decoder_initted; + unsigned char **output_rows; /* Output frame buffer supplied by user */ + int in_x, in_y, in_w, in_h, out_w, out_h; /* Output dimensions */ + int *x_table, *y_table; /* Location of every output pixel in the input */ + int color_model; + int want_yvu; /* Want to return a YUV frame */ + char *y_output, *u_output, *v_output; /* Output pointers for a YUV frame */ + + mpeg3_slice_t slice_decoders[MPEG3_MAX_CPUS]; /* One slice decoder for every CPU */ + int total_slice_decoders; /* Total slice decoders in use */ + mpeg3_slice_buffer_t slice_buffers[MPEG3_MAX_CPUS]; /* Buffers for holding the slice data */ + int total_slice_buffers; /* Total buffers in the array to be decompressed */ + int slice_buffers_initialized; /* Total buffers initialized in the array */ + pthread_mutex_t slice_lock; /* Lock slice array while getting the next buffer */ + pthread_mutex_t test_lock; + + int blockreadsize; + long maxframe; /* Max value of frame num to read */ + double percentage_seek; /* Perform a percentage seek before the next frame is read */ + int frame_seek; /* Perform a frame seek before the next frame is read */ + long framenum; /* Number of the next frame to be decoded */ + long last_number; /* Last framenum rendered */ + int found_seqhdr; + long bitrate; + mpeg3_timecode_t gop_timecode; /* Timecode for the last GOP header read. */ + +/* These are only available from elementary streams. */ + long frames_per_gop; /* Frames per GOP after the first GOP. */ + long first_gop_frames; /* Frames in the first GOP. */ + long first_frame; /* Number of first frame stored in timecode */ + long last_frame; /* Last frame in file */ + +/* ================================= Compression variables ===================== */ +/* Malloced frame buffers. 2 refframes are swapped in and out. */ +/* while only 1 auxframe is used. */ + unsigned char *yuv_buffer[5]; /* Make YVU buffers contiguous for all frames */ + unsigned char *oldrefframe[3], *refframe[3], *auxframe[3]; + unsigned char *llframe0[3], *llframe1[3]; + unsigned char *mpeg3_zigzag_scan_table; + unsigned char *mpeg3_alternate_scan_table; +// Source for the next frame presentation + unsigned char **output_src; +/* Pointers to frame buffers. */ + unsigned char *newframe[3]; + int horizontal_size, vertical_size, mb_width, mb_height; + int coded_picture_width, coded_picture_height; + int chroma_format, chrom_width, chrom_height, blk_cnt; + int pict_type; + int forw_r_size, back_r_size, full_forw, full_back; + int prog_seq, prog_frame; + int h_forw_r_size, v_forw_r_size, h_back_r_size, v_back_r_size; + int dc_prec, pict_struct, topfirst, frame_pred_dct, conceal_mv; + int intravlc; + int repeatfirst; + int repeat_count; /* Number of times to repeat the current frame * 100 since floating point is impossible in MMX */ + int current_repeat; /* Number of times the current frame has been repeated * 100 */ + int secondfield; + int skip_bframes; + int stwc_table_index, llw, llh, hm, hn, vm, vn; + int lltempref, llx0, lly0, llprog_frame, llfieldsel; + int matrix_coefficients; + int framerate_code; + float frame_rate; + long *cr_to_r, *cr_to_g, *cb_to_g, *cb_to_b; + long *cr_to_r_ptr, *cr_to_g_ptr, *cb_to_g_ptr, *cb_to_b_ptr; + int have_mmx; + int intra_quantizer_matrix[64], non_intra_quantizer_matrix[64]; + int chroma_intra_quantizer_matrix[64], chroma_non_intra_quantizer_matrix[64]; + int mpeg2; + int qscale_type, altscan; /* picture coding extension */ + int pict_scal; /* picture spatial scalable extension */ + int scalable_mode; /* sequence scalable extension */ +}; + +typedef struct mpeg3video_rec mpeg3video_t; + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/video/mpeg3videoprotos.h b/core/multimedia/opieplayer/libmpeg3/video/mpeg3videoprotos.h new file mode 100644 index 0000000..e48d6cd --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/mpeg3videoprotos.h @@ -0,0 +1,26 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MPEG3VIDEOPROTOS_H +#define MPEG3VIDEOPROTOS_H + +void mpeg3video_idct_conversion(short* block); +unsigned int mpeg3slice_showbits(mpeg3_slice_buffer_t *slice_buffer, int bits); + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/video/output.c b/core/multimedia/opieplayer/libmpeg3/video/output.c new file mode 100644 index 0000000..919a0ff --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/output.c @@ -0,0 +1,993 @@ +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" +#include <string.h> + +static LONGLONG mpeg3_MMX_0 = 0L; +static unsigned long mpeg3_MMX_10w[] = {0x00100010, 0x00100010}; /*dd 00010 0010h, 000100010h */ +static unsigned long mpeg3_MMX_80w[] = {0x00800080, 0x00800080}; /*dd 00080 0080h, 000800080h */ + +static unsigned long mpeg3_MMX_00FFw[] = {0x00ff00ff, 0x00ff00ff}; /*dd 000FF 00FFh, 000FF00FFh */ + +static unsigned short mpeg3_MMX_Ublucoeff[] = {0x81, 0x81, 0x81, 0x81}; /*dd 00081 0081h, 000810081h */ +static unsigned short mpeg3_MMX_Vredcoeff[] = {0x66, 0x66, 0x66, 0x66}; /*dd 00066 0066h, 000660066h */ + +static unsigned short mpeg3_MMX_Ugrncoeff[] = {0xffe8, 0xffe8, 0xffe8, 0xffe8}; /*dd 0FFE7 FFE7h, 0FFE7FFE7h */ +static unsigned short mpeg3_MMX_Vgrncoeff[] = {0xffcd, 0xffcd, 0xffcd, 0xffcd}; /*dd 0FFCC FFCCh, 0FFCCFFCCh */ + +static unsigned short mpeg3_MMX_Ycoeff[] = {0x4a, 0x4a, 0x4a, 0x4a}; /*dd 0004A 004Ah, 0004A004Ah */ + +static unsigned short mpeg3_MMX_redmask[] = {0xf800, 0xf800, 0xf800, 0xf800}; /*dd 07c00 7c00h, 07c007c00h */ + +static unsigned short mpeg3_MMX_grnmask[] = {0x7e0, 0x7e0, 0x7e0, 0x7e0}; /*dd 003e0 03e0h, 003e003e0h */ + +static unsigned char mpeg3_601_to_rgb[256]; + +/* Algorithm */ +/* r = (int)(*y + 1.371 * (*cr - 128)); */ +/* g = (int)(*y - 0.698 * (*cr - 128) - 0.336 * (*cb - 128)); */ +/* b = (int)(*y + 1.732 * (*cb - 128)); */ + +#ifdef HAVE_MMX +inline void mpeg3video_rgb16_mmx(unsigned char *lum, + unsigned char *cr, + unsigned char *cb, + unsigned char *out, + int rows, + int cols, + int mod) +{ + unsigned short *row1; + int x; + unsigned char *y; + int col1; + + row1 = (unsigned short *)out; + col1 = cols + mod; + mod += cols + mod; + mod *= 2; + y = lum + cols * rows; + x = 0; + + __asm__ __volatile__( + ".align 8\n" + "1:\n" + "movd (%1), %%mm0\n" /* 4 Cb 0 0 0 0 u3 u2 u1 u0 */ + "pxor %%mm7, %%mm7\n" + "movd (%0), %%mm1\n" /* 4 Cr 0 0 0 0 v3 v2 v1 v0 */ + "punpcklbw %%mm7, %%mm0\n" /* 4 W cb 0 u3 0 u2 0 u1 0 u0 */ + "punpcklbw %%mm7, %%mm1\n" /* 4 W cr 0 v3 0 v2 0 v1 0 v0 */ + + "psubw mpeg3_MMX_80w, %%mm0\n" + "psubw mpeg3_MMX_80w, %%mm1\n" + "movq %%mm0, %%mm2\n" /* Cb 0 u3 0 u2 0 u1 0 u0 */ + "movq %%mm1, %%mm3\n" /* Cr */ + "pmullw mpeg3_MMX_Ugrncoeff, %%mm2\n" /* Cb2green 0 R3 0 R2 0 R1 0 R0 */ + "movq (%2), %%mm6\n" /* L1 l7 L6 L5 L4 L3 L2 L1 L0 */ + "pmullw mpeg3_MMX_Ublucoeff, %%mm0\n" /* Cb2blue */ + "pand mpeg3_MMX_00FFw, %%mm6\n" /* L1 00 L6 00 L4 00 L2 00 L0 */ + "pmullw mpeg3_MMX_Vgrncoeff, %%mm3\n" /* Cr2green */ + "movq (%2), %%mm7\n" /* L2 */ + "pmullw mpeg3_MMX_Vredcoeff, %%mm1\n" /* Cr2red */ + "psrlw $8, %%mm7\n" /* L2 00 L7 00 L5 00 L3 00 L1 */ + "pmullw mpeg3_MMX_Ycoeff, %%mm6\n" /* lum1 */ + "paddw %%mm3, %%mm2\n" /* Cb2green + Cr2green == green */ + "pmullw mpeg3_MMX_Ycoeff, %%mm7\n" /* lum2 */ + + "movq %%mm6, %%mm4\n" /* lum1 */ + "paddw %%mm0, %%mm6\n" /* lum1 +blue 00 B6 00 B4 00 B2 00 B0 */ + "movq %%mm4, %%mm5\n" /* lum1 */ + "paddw %%mm1, %%mm4\n" /* lum1 +red 00 R6 00 R4 00 R2 00 R0 */ + "paddw %%mm2, %%mm5\n" /* lum1 +green 00 G6 00 G4 00 G2 00 G0 */ + "psraw $6, %%mm4\n" /* R1 0 .. 64 */ + "movq %%mm7, %%mm3\n" /* lum2 00 L7 00 L5 00 L3 00 L1 */ + "psraw $6, %%mm5\n" /* G1 - .. + */ + "paddw %%mm0, %%mm7\n" /* Lum2 +blue 00 B7 00 B5 00 B3 00 B1 */ + "psraw $6, %%mm6\n" /* B1 0 .. 64 */ + "packuswb %%mm4, %%mm4\n" /* R1 R1 */ + "packuswb %%mm5, %%mm5\n" /* G1 G1 */ + "packuswb %%mm6, %%mm6\n" /* B1 B1 */ + "punpcklbw %%mm4, %%mm4\n" + "punpcklbw %%mm5, %%mm5\n" + + "pand mpeg3_MMX_redmask, %%mm4\n" + "psllw $3, %%mm5\n" /* GREEN 1 */ + "punpcklbw %%mm6, %%mm6\n" + "pand mpeg3_MMX_grnmask, %%mm5\n" + "pand mpeg3_MMX_redmask, %%mm6\n" + "por %%mm5, %%mm4\n" /* */ + "psrlw $11, %%mm6\n" /* BLUE 1 */ + "movq %%mm3, %%mm5\n" /* lum2 */ + "paddw %%mm1, %%mm3\n" /* lum2 +red 00 R7 00 R5 00 R3 00 R1 */ + "paddw %%mm2, %%mm5\n" /* lum2 +green 00 G7 00 G5 00 G3 00 G1 */ + "psraw $6, %%mm3\n" /* R2 */ + "por %%mm6, %%mm4\n" /* MM4 */ + "psraw $6, %%mm5\n" /* G2 */ + "movq (%2, %3), %%mm6\n" /* L3 */ + "psraw $6, %%mm7\n" + "packuswb %%mm3, %%mm3\n" + "packuswb %%mm5, %%mm5\n" + "packuswb %%mm7, %%mm7\n" + "pand mpeg3_MMX_00FFw, %%mm6\n" /* L3 */ + "punpcklbw %%mm3, %%mm3\n" + "punpcklbw %%mm5, %%mm5\n" + "pmullw mpeg3_MMX_Ycoeff, %%mm6\n" /* lum3 */ + "punpcklbw %%mm7, %%mm7\n" + "psllw $3, %%mm5\n" /* GREEN 2 */ + "pand mpeg3_MMX_redmask, %%mm7\n" + "pand mpeg3_MMX_redmask, %%mm3\n" + "psrlw $11, %%mm7\n" /* BLUE 2 */ + "pand mpeg3_MMX_grnmask, %%mm5\n" + "por %%mm7, %%mm3\n" + "movq (%2,%3), %%mm7\n" /* L4 */ + "por %%mm5, %%mm3\n" /* */ + "psrlw $8, %%mm7\n" /* L4 */ + "movq %%mm4, %%mm5\n" + "punpcklwd %%mm3, %%mm4\n" + "pmullw mpeg3_MMX_Ycoeff, %%mm7\n" /* lum4 */ + "punpckhwd %%mm3, %%mm5\n" + + "movq %%mm4, (%4)\n" + "movq %%mm5, 8(%4)\n" + + "movq %%mm6, %%mm4\n" /* Lum3 */ + "paddw %%mm0, %%mm6\n" /* Lum3 +blue */ + + "movq %%mm4, %%mm5\n" /* Lum3 */ + "paddw %%mm1, %%mm4\n" /* Lum3 +red */ + "paddw %%mm2, %%mm5\n" /* Lum3 +green */ + "psraw $6, %%mm4\n" + "movq %%mm7, %%mm3\n" /* Lum4 */ + "psraw $6, %%mm5\n" + "paddw %%mm0, %%mm7\n" /* Lum4 +blue */ + "psraw $6, %%mm6\n" /* Lum3 +blue */ + "movq %%mm3, %%mm0\n" /* Lum4 */ + "packuswb %%mm4, %%mm4\n" + "paddw %%mm1, %%mm3\n" /* Lum4 +red */ + "packuswb %%mm5, %%mm5\n" + "paddw %%mm2, %%mm0\n" /* Lum4 +green */ + "packuswb %%mm6, %%mm6\n" + "punpcklbw %%mm4, %%mm4\n" + "punpcklbw %%mm5, %%mm5\n" + "punpcklbw %%mm6, %%mm6\n" + "psllw $3, %%mm5\n" /* GREEN 3 */ + "pand mpeg3_MMX_redmask, %%mm4\n" + "psraw $6, %%mm3\n" /* psr 6 */ + "psraw $6, %%mm0\n" + "pand mpeg3_MMX_redmask, %%mm6\n" /* BLUE */ + "pand mpeg3_MMX_grnmask, %%mm5\n" + "psrlw $11, %%mm6\n" /* BLUE 3 */ + "por %%mm5, %%mm4\n" + "psraw $6, %%mm7\n" + "por %%mm6, %%mm4\n" + "packuswb %%mm3, %%mm3\n" + "packuswb %%mm0, %%mm0\n" + "packuswb %%mm7, %%mm7\n" + "punpcklbw %%mm3, %%mm3\n" + "punpcklbw %%mm0, %%mm0\n" + "punpcklbw %%mm7, %%mm7\n" + "pand mpeg3_MMX_redmask, %%mm3\n" + "pand mpeg3_MMX_redmask, %%mm7\n" /* BLUE */ + "psllw $3, %%mm0\n" /* GREEN 4 */ + "psrlw $11, %%mm7\n" + "pand mpeg3_MMX_grnmask, %%mm0\n" + "por %%mm7, %%mm3\n" + "addl $8, %6\n" + "por %%mm0, %%mm3\n" + + "movq %%mm4, %%mm5\n" + + "punpcklwd %%mm3, %%mm4\n" + "punpckhwd %%mm3, %%mm5\n" + + "movq %%mm4, (%4,%5,2)\n" + "movq %%mm5, 8(%4,%5,2)\n" + + "addl $8, %2\n" + "addl $4, %0\n" + "addl $4, %1\n" + "cmpl %3, %6\n" + "leal 16(%4), %4\n" + "jl 1b\n" + "addl %3, %2\n" /* lum += cols */ + "addl %7, %4\n" /* row1 += mod */ + "movl $0, %6\n" + "cmpl %8, %2\n" + "jl 1b\n" + : : "r" (cr), + "r" (cb), + "r" (lum), + "r" (cols), + "r" (row1) , + "r" (col1), + "m" (x), + "m" (mod), + "m" (y) + ); +} + +static unsigned LONGLONG mpeg3_MMX_U_80 = 0x0000008000800000LL; +static unsigned LONGLONG mpeg3_MMX_V_80 = 0x0000000000800080LL; +static LONGLONG mpeg3_MMX_U_COEF = 0x00000058ffd30000LL; +static LONGLONG mpeg3_MMX_V_COEF = 0x00000000ffea006fLL; +static LONGLONG mpeg3_MMX_601_Y_COEF = 0x0000004800480048LL; +static LONGLONG mpeg3_MMX_601_Y_DIFF = 0x0000000000000010LL; + +inline void mpeg3_bgra32_mmx(unsigned long y, + unsigned long u, + unsigned long v, + unsigned long *output) +{ +asm(" +/* Output will be 0x00rrggbb with the 00 trailing so this can also be used */ +/* for bgr24. */ + movd (%0), %%mm0; /* Load y 0x00000000000000yy */ + movd (%1), %%mm1; /* Load u 0x00000000000000cr */ + movq %%mm0, %%mm3; /* Copy y to temp */ + psllq $16, %%mm1; /* Shift u 0x0000000000cr0000 */ + movd (%2), %%mm2; /* Load v 0x00000000000000cb */ + psllq $16, %%mm3; /* Shift y */ + movq %%mm1, %%mm4; /* Copy u to temp */ + por %%mm3, %%mm0; /* Overlay new y byte 0x0000000000yy00yy */ + psllq $16, %%mm4; /* Shift u */ + movq %%mm2, %%mm5; /* Copy v to temp */ + psllq $16, %%mm3; /* Shift y */ + por %%mm4, %%mm1; /* Overlay new u byte 0x000000cr00cr0000 */ + psllq $16, %%mm5; /* Shift v */ + por %%mm3, %%mm0; /* Overlay new y byte 0x000000yy00yy00yy */ + por %%mm5, %%mm2; /* Overlay new v byte 0x0000000000cb00cb */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x000000uu00uu0000 mm2: 0x0000000000vv00vv */ + psubw mpeg3_MMX_U_80, %%mm1; /* Subtract 128 from u 0x000000uu00uu0000 */ + pmullw mpeg3_MMX_U_COEF, %%mm1; /* Multiply u coeffs 0x0000uuuuuuuu0000 */ + psllw $6, %%mm0; /* Shift y coeffs 0x0000yyy0yyy0yyy0 */ + psubw mpeg3_MMX_V_80, %%mm2; /* Subtract 128 from v 0x0000000000cb00cb */ + pmullw mpeg3_MMX_V_COEF, %%mm2; /* Multiply v coeffs 0x0000crcrcrcrcrcr */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x0000uuuuuuuu0000 mm2: 0x00000000vvvvvvvv */ + paddsw %%mm1, %%mm0; /* Add u to result */ + paddsw %%mm2, %%mm0; /* Add v to result 0x0000rrrrggggbbbb */ + psraw $6, %%mm0; /* Demote precision */ + packuswb %%mm0, %%mm0; /* Pack into ARGB 0x0000000000rrggbb */ + movd %%mm0, (%3); /* Store output */ + " +: +: "r" (&y), "r" (&u), "r" (&v), "r" (output)); +} + +inline void mpeg3_601_bgra32_mmx(unsigned long y, + unsigned long u, + unsigned long v, + unsigned long *output) +{ +asm(" +/* Output will be 0x00rrggbb with the 00 trailing so this can also be used */ +/* for bgr24. */ + movd (%0), %%mm0; /* Load y 0x00000000000000yy */ + psubsw mpeg3_MMX_601_Y_DIFF, %%mm0; /* Subtract 16 from y */ + movd (%1), %%mm1; /* Load u 0x00000000000000cr */ + movq %%mm0, %%mm3; /* Copy y to temp */ + psllq $16, %%mm1; /* Shift u 0x0000000000cr0000 */ + movd (%2), %%mm2; /* Load v 0x00000000000000cb */ + psllq $16, %%mm3; /* Shift y */ + movq %%mm1, %%mm4; /* Copy u to temp */ + por %%mm3, %%mm0; /* Overlay new y byte 0x0000000000yy00yy */ + psllq $16, %%mm4; /* Shift u */ + movq %%mm2, %%mm5; /* Copy v to temp */ + psllq $16, %%mm3; /* Shift y */ + por %%mm4, %%mm1; /* Overlay new u byte 0x000000cr00cr0000 */ + psllq $16, %%mm5; /* Shift v */ + por %%mm3, %%mm0; /* Overlay new y byte 0x000000yy00yy00yy */ + por %%mm5, %%mm2; /* Overlay new v byte 0x0000000000cb00cb */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x000000uu00uu0000 mm2: 0x0000000000vv00vv */ + pmullw mpeg3_MMX_601_Y_COEF, %%mm0; /* Scale and shift y coeffs */ + psubw mpeg3_MMX_U_80, %%mm1; /* Subtract 128 from u 0x000000uu00uu0000 */ + pmullw mpeg3_MMX_U_COEF, %%mm1; /* Multiply u coeffs 0x0000uuuuuuuu0000 */ + psubw mpeg3_MMX_V_80, %%mm2; /* Subtract 128 from v 0x0000000000cb00cb */ + pmullw mpeg3_MMX_V_COEF, %%mm2; /* Multiply v coeffs 0x0000crcrcrcrcrcr */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x0000uuuuuuuu0000 mm2: 0x00000000vvvvvvvv */ + paddsw %%mm1, %%mm0; /* Add u to result */ + paddsw %%mm2, %%mm0; /* Add v to result 0x0000rrrrggggbbbb */ + psraw $6, %%mm0; /* Demote precision */ + packuswb %%mm0, %%mm0; /* Pack into ARGB 0x0000000000rrggbb */ + movd %%mm0, (%3); /* Store output */ + " +: +: "r" (&y), "r" (&u), "r" (&v), "r" (output)); +} + +static unsigned LONGLONG mpeg3_MMX_U_80_RGB = 0x0000000000800080LL; +static unsigned LONGLONG mpeg3_MMX_V_80_RGB = 0x0000008000800000LL; +static LONGLONG mpeg3_MMX_U_COEF_RGB = 0x00000000ffd30058LL; +static LONGLONG mpeg3_MMX_V_COEF_RGB = 0x0000006fffea0000LL; + +inline void mpeg3_rgba32_mmx(unsigned long y, + unsigned long u, + unsigned long v, + unsigned long *output) +{ +asm(" +/* Output will be 0x00bbggrr with the 00 trailing so this can also be used */ +/* for rgb24. */ + movd (%0), %%mm0; /* Load y 0x00000000000000yy */ + movd (%1), %%mm1; /* Load v 0x00000000000000vv */ + movq %%mm0, %%mm3; /* Copy y to temp */ + psllq $16, %%mm1; /* Shift v 0x0000000000vv0000 */ + movd (%2), %%mm2; /* Load u 0x00000000000000uu */ + psllq $16, %%mm3; /* Shift y */ + movq %%mm1, %%mm4; /* Copy v to temp */ + por %%mm3, %%mm0; /* Overlay new y byte 0x0000000000yy00yy */ + psllq $16, %%mm4; /* Shift v */ + movq %%mm2, %%mm5; /* Copy u to temp */ + psllq $16, %%mm3; /* Shift y */ + por %%mm4, %%mm1; /* Overlay new v byte 0x000000vv00vv0000 */ + psllq $16, %%mm5; /* Shift u */ + por %%mm3, %%mm0; /* Overlay new y byte 0x000000yy00yy00yy */ + por %%mm5, %%mm2; /* Overlay new u byte 0x0000000000uu00uu */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x000000vv00vv0000 mm2: 0x0000000000uu00uu */ + psubw mpeg3_MMX_V_80_RGB, %%mm1; /* Subtract 128 from v 0x000000vv00vv0000 */ + pmullw mpeg3_MMX_V_COEF_RGB, %%mm1; /* Multiply v coeffs 0x0000vvvvvvvv0000 */ + psllw $6, %%mm0; /* Shift y coeffs 0x0000yyy0yyy0yyy0 */ + psubw mpeg3_MMX_U_80_RGB, %%mm2; /* Subtract 128 from u 0x0000000000uu00uu */ + pmullw mpeg3_MMX_U_COEF_RGB, %%mm2; /* Multiply u coeffs 0x0000uuuuuuuuuuuu */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x0000vvvvvvvv0000 mm2: 0x00000000uuuuuuuu */ + paddsw %%mm1, %%mm0; /* Add v to result */ + paddsw %%mm2, %%mm0; /* Add u to result 0x0000bbbbggggrrrr */ + psraw $6, %%mm0; /* Demote precision */ + packuswb %%mm0, %%mm0; /* Pack into RGBA 0x0000000000bbggrr */ + movd %%mm0, (%3); /* Store output */ + " +: +: "r" (&y), "r" (&v), "r" (&u), "r" (output)); +} + +inline void mpeg3_601_rgba32_mmx(unsigned long y, + unsigned long u, + unsigned long v, + unsigned long *output) +{ +asm(" +/* Output will be 0x00bbggrr with the 00 trailing so this can also be used */ +/* for rgb24. */ + movd (%0), %%mm0; /* Load y 0x00000000000000yy */ + psubsw mpeg3_MMX_601_Y_DIFF, %%mm0; /* Subtract 16 from y */ + movd (%1), %%mm1; /* Load v 0x00000000000000vv */ + movq %%mm0, %%mm3; /* Copy y to temp */ + psllq $16, %%mm1; /* Shift v 0x0000000000vv0000 */ + movd (%2), %%mm2; /* Load u 0x00000000000000uu */ + psllq $16, %%mm3; /* Shift y */ + movq %%mm1, %%mm4; /* Copy v to temp */ + por %%mm3, %%mm0; /* Overlay new y byte 0x0000000000yy00yy */ + psllq $16, %%mm4; /* Shift v */ + movq %%mm2, %%mm5; /* Copy u to temp */ + psllq $16, %%mm3; /* Shift y */ + por %%mm4, %%mm1; /* Overlay new v byte 0x000000vv00vv0000 */ + psllq $16, %%mm5; /* Shift u */ + por %%mm3, %%mm0; /* Overlay new y byte 0x000000yy00yy00yy */ + por %%mm5, %%mm2; /* Overlay new u byte 0x0000000000uu00uu */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x000000vv00vv0000 mm2: 0x0000000000uu00uu */ + pmullw mpeg3_MMX_601_Y_COEF, %%mm0; /* Scale y coeffs */ + psubw mpeg3_MMX_V_80_RGB, %%mm1; /* Subtract 128 from v 0x000000vv00vv0000 */ + pmullw mpeg3_MMX_V_COEF_RGB, %%mm1; /* Multiply v coeffs 0x0000vvvvvvvv0000 */ + psubw mpeg3_MMX_U_80_RGB, %%mm2; /* Subtract 128 from u 0x0000000000uu00uu */ + pmullw mpeg3_MMX_U_COEF_RGB, %%mm2; /* Multiply u coeffs 0x0000uuuuuuuuuuuu */ + +/* mm0: 0x000000yy00yy00yy mm1: 0x0000vvvvvvvv0000 mm2: 0x00000000uuuuuuuu */ + paddsw %%mm1, %%mm0; /* Add v to result */ + paddsw %%mm2, %%mm0; /* Add u to result 0x0000bbbbggggrrrr */ + psraw $6, %%mm0; /* Demote precision */ + packuswb %%mm0, %%mm0; /* Pack into RGBA 0x0000000000bbggrr */ + movd %%mm0, (%3); /* Store output */ + " +: +: "r" (&y), "r" (&v), "r" (&u), "r" (output)); +} + +#endif + +#define DITHER_ROW_HEAD \ + for(h = 0; h < video->out_h; h++) \ + { \ + y_in = &src[0][(video->y_table[h] + video->in_y) * video->coded_picture_width] + video->in_x; \ + cb_in = &src[1][((video->y_table[h] + video->in_y) >> 1) * video->chrom_width] + (video->in_x >> 2); \ + cr_in = &src[2][((video->y_table[h] + video->in_y) >> 1) * video->chrom_width] + (video->in_x >> 1); \ + data = output_rows[h]; + +#define DITHER_ROW_TAIL \ + } + +#define DITHER_SCALE_HEAD \ + for(w = 0; w < video->out_w; w++) \ + { \ + uv_subscript = video->x_table[w] / 2; \ + y_l = y_in[video->x_table[w]]; \ + y_l <<= 16; \ + r_l = (y_l + video->cr_to_r[cr_in[uv_subscript]]) >> 16; \ + g_l = (y_l + video->cr_to_g[cr_in[uv_subscript]] + video->cb_to_g[cb_in[uv_subscript]]) >> 16; \ + b_l = (y_l + video->cb_to_b[cb_in[uv_subscript]]) >> 16; + +#define DITHER_SCALE_601_HEAD \ + for(w = 0; w < video->out_w; w++) \ + { \ + uv_subscript = video->x_table[w] / 2; \ + y_l = mpeg3_601_to_rgb[y_in[video->x_table[w]]]; \ + y_l <<= 16; \ + r_l = (y_l + video->cr_to_r[cr_in[uv_subscript]]) >> 16; \ + g_l = (y_l + video->cr_to_g[cr_in[uv_subscript]] + video->cb_to_g[cb_in[uv_subscript]]) >> 16; \ + b_l = (y_l + video->cb_to_b[cb_in[uv_subscript]]) >> 16; + +#define DITHER_SCALE_TAIL \ + } + +#define DITHER_MMX_SCALE_HEAD \ + for(w = 0; w < video->out_w; w++) \ + { \ + uv_subscript = video->x_table[w] / 2; + +#define DITHER_MMX_SCALE_TAIL \ + data += step; \ + } + +#define DITHER_MMX_HEAD \ + for(w = 0; w < video->out_w; w += 2) \ + { + +#define DITHER_MMX_TAIL \ + data += step; \ + cr_in++; \ + cb_in++; \ + } + +#define DITHER_HEAD \ + for(w = 0; w < video->horizontal_size; w++) \ + { \ + y_l = *y_in++; \ + y_l <<= 16; \ + r_l = (y_l + video->cr_to_r[*cr_in]) >> 16; \ + g_l = (y_l + video->cr_to_g[*cr_in] + video->cb_to_g[*cb_in]) >> 16; \ + b_l = (y_l + video->cb_to_b[*cb_in]) >> 16; + +#define DITHER_601_HEAD \ + for(w = 0; w < video->horizontal_size; w++) \ + { \ + y_l = mpeg3_601_to_rgb[*y_in++]; \ + y_l <<= 16; \ + r_l = (y_l + video->cr_to_r[*cr_in]) >> 16; \ + g_l = (y_l + video->cr_to_g[*cr_in] + video->cb_to_g[*cb_in]) >> 16; \ + b_l = (y_l + video->cb_to_b[*cb_in]) >> 16; + +#define DITHER_TAIL \ + if(w & 1) \ + { \ + cr_in++; \ + cb_in++; \ + } \ + } + + +#define STORE_PIXEL_BGR888 \ + *data++ = CLIP(b_l); \ + *data++ = CLIP(g_l); \ + *data++ = CLIP(r_l); + +#define STORE_PIXEL_BGRA8888 \ + *data++ = CLIP(b_l); \ + *data++ = CLIP(g_l); \ + *data++ = CLIP(r_l); \ + *data++ = 0; + +#define STORE_PIXEL_RGB565 \ + *((unsigned short*)data)++ = \ + ((CLIP(r_l) & 0xf8) << 8) | \ + ((CLIP(g_l) & 0xfc) << 3) | \ + ((CLIP(b_l) & 0xf8) >> 3); + +#define STORE_PIXEL_RGB888 \ + *data++ = CLIP(r_l); \ + *data++ = CLIP(g_l); \ + *data++ = CLIP(b_l); + +#define STORE_PIXEL_RGBA8888 \ + *data++ = CLIP(r_l); \ + *data++ = CLIP(g_l); \ + *data++ = CLIP(b_l); \ + *data++ = 0; + +#define STORE_PIXEL_RGBA16161616 \ + *data_s++ = CLIP(r_l); \ + *data_s++ = CLIP(g_l); \ + *data_s++ = CLIP(b_l); \ + *data_s++ = 0; + + + +/* Only good for YUV 4:2:0 */ +int mpeg3video_ditherframe(mpeg3video_t *video, unsigned char **src, unsigned char **output_rows) +{ + int h = 0; + register unsigned char *y_in, *cb_in, *cr_in; + long y_l, r_l, b_l, g_l; + register unsigned char *data; + register int uv_subscript, step, w = -1; + +#ifdef HAVE_MMX +/* =================================== MMX ===================================== */ + if(video->have_mmx && + video->out_w == video->horizontal_size && + video->out_h == video->vertical_size && + video->in_w == video->out_w && + video->in_h == video->out_h && + video->in_x == 0 && + video->in_y == 0 && + (video->color_model == MPEG3_RGB565 || video->color_model == MPEG3_601_RGB565)) + { +/* Unscaled 16 bit */ + mpeg3video_rgb16_mmx(src[0], + src[2], + src[1], + output_rows[0], + video->out_h, + video->out_w, + (output_rows[1] - output_rows[0]) / 2 - video->out_w); + } + else + if(video->have_mmx && + (video->color_model == MPEG3_BGRA8888 || + video->color_model == MPEG3_BGR888 || +/* video->color_model == MPEG3_RGB888 || */ + video->color_model == MPEG3_RGBA8888 || + video->color_model == MPEG3_601_BGR888 || + video->color_model == MPEG3_601_BGRA8888 || + video->color_model == MPEG3_601_RGB888 || + video->color_model == MPEG3_601_RGBA8888)) + { +/* Original MMX */ + if(video->color_model == MPEG3_BGRA8888 || + video->color_model == MPEG3_RGBA8888 || + video->color_model == MPEG3_601_BGRA8888 || + video->color_model == MPEG3_601_RGBA8888) step = 4; + else + if(video->color_model == MPEG3_BGR888 || + video->color_model == MPEG3_RGB888 || + video->color_model == MPEG3_601_BGR888 || + video->color_model == MPEG3_601_RGB888) step = 3; + + DITHER_ROW_HEAD +/* Transfer row with scaling */ + if(video->out_w != video->horizontal_size) + { + switch(video->color_model) + { + case MPEG3_BGRA8888: + case MPEG3_BGR888: + DITHER_MMX_SCALE_HEAD + mpeg3_bgra32_mmx(y_in[video->x_table[w]], + cr_in[uv_subscript], + cb_in[uv_subscript], + (unsigned long*)data); + DITHER_MMX_SCALE_TAIL + break; + + case MPEG3_601_BGRA8888: + case MPEG3_601_BGR888: + DITHER_MMX_SCALE_HEAD + mpeg3_601_bgra32_mmx(y_in[video->x_table[w]], + cr_in[uv_subscript], + cb_in[uv_subscript], + (unsigned long*)data); + DITHER_MMX_SCALE_TAIL + break; + + case MPEG3_RGBA8888: + case MPEG3_RGB888: + DITHER_MMX_SCALE_HEAD + mpeg3_rgba32_mmx(y_in[video->x_table[w]], + cr_in[uv_subscript], + cb_in[uv_subscript], + (unsigned long*)data); + DITHER_MMX_SCALE_TAIL + break; + + case MPEG3_601_RGBA8888: + case MPEG3_601_RGB888: + DITHER_MMX_SCALE_HEAD + mpeg3_601_rgba32_mmx(y_in[video->x_table[w]], + cr_in[uv_subscript], + cb_in[uv_subscript], + (unsigned long*)data); + DITHER_MMX_SCALE_TAIL + break; + } + } + else +/* Transfer row unscaled */ + { + switch(video->color_model) + { +/* MMX byte swap 24 and 32 bit */ + case MPEG3_BGRA8888: + case MPEG3_BGR888: + DITHER_MMX_HEAD + mpeg3_bgra32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + data += step; + mpeg3_bgra32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + DITHER_MMX_TAIL + break; + +/* MMX 601 byte swap 24 and 32 bit */ + case MPEG3_601_BGRA8888: + case MPEG3_601_BGR888: + DITHER_MMX_HEAD + mpeg3_601_bgra32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + data += step; + mpeg3_601_bgra32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + DITHER_MMX_TAIL + break; + +/* MMX 24 and 32 bit no byte swap */ + case MPEG3_RGBA8888: + case MPEG3_RGB888: + DITHER_MMX_HEAD + mpeg3_rgba32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + data += step; + mpeg3_rgba32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + DITHER_MMX_TAIL + break; + +/* MMX 601 24 and 32 bit no byte swap */ + case MPEG3_601_RGBA8888: + case MPEG3_601_RGB888: + DITHER_MMX_HEAD + mpeg3_601_rgba32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + data += step; + mpeg3_601_rgba32_mmx(*y_in++, + *cr_in, + *cb_in, + (unsigned long*)data); + DITHER_MMX_TAIL + break; + } + } + DITHER_ROW_TAIL + } + else +#endif +/* ================================== NO MMX ==================================== */ + { + DITHER_ROW_HEAD +/* Transfer row with scaling */ + if(video->out_w != video->horizontal_size) + { + switch(video->color_model) + { + case MPEG3_BGR888: + DITHER_SCALE_HEAD + STORE_PIXEL_BGR888 + DITHER_SCALE_TAIL + break; + case MPEG3_BGRA8888: + DITHER_SCALE_HEAD + STORE_PIXEL_BGRA8888 + DITHER_SCALE_TAIL + break; + case MPEG3_RGB565: + DITHER_SCALE_HEAD + STORE_PIXEL_RGB565 + DITHER_SCALE_TAIL + break; + case MPEG3_RGB888: + DITHER_SCALE_HEAD + STORE_PIXEL_RGB888 + DITHER_SCALE_TAIL + break; + case MPEG3_RGBA8888: + DITHER_SCALE_HEAD + STORE_PIXEL_RGBA8888 + DITHER_SCALE_TAIL + break; + case MPEG3_601_BGR888: + DITHER_SCALE_601_HEAD + STORE_PIXEL_BGR888 + DITHER_SCALE_TAIL + break; + case MPEG3_601_BGRA8888: + DITHER_SCALE_601_HEAD + STORE_PIXEL_BGRA8888 + DITHER_SCALE_TAIL + break; + case MPEG3_601_RGB565: + DITHER_SCALE_601_HEAD + STORE_PIXEL_RGB565 + DITHER_SCALE_TAIL + break; + case MPEG3_601_RGB888: + DITHER_SCALE_601_HEAD + STORE_PIXEL_RGB888 + DITHER_SCALE_TAIL + break; + case MPEG3_601_RGBA8888: + DITHER_SCALE_601_HEAD + STORE_PIXEL_RGBA8888 + DITHER_SCALE_TAIL + break; + case MPEG3_RGBA16161616: + { + register unsigned short *data_s = (unsigned short*)data; + DITHER_SCALE_HEAD + STORE_PIXEL_RGBA16161616 + DITHER_SCALE_TAIL + } + break; + } + } + else + { +/* Transfer row unscaled */ + switch(video->color_model) + { + case MPEG3_BGR888: + DITHER_HEAD + STORE_PIXEL_BGR888 + DITHER_TAIL + break; + case MPEG3_BGRA8888: + DITHER_HEAD + STORE_PIXEL_BGRA8888 + DITHER_TAIL + break; + case MPEG3_RGB565: + DITHER_HEAD + STORE_PIXEL_RGB565 + DITHER_TAIL + break; + case MPEG3_RGB888: + DITHER_HEAD + STORE_PIXEL_RGB888 + DITHER_TAIL + break; + case MPEG3_RGBA8888: + DITHER_HEAD + STORE_PIXEL_RGBA8888 + DITHER_TAIL + break; + case MPEG3_601_BGR888: + DITHER_601_HEAD + STORE_PIXEL_BGR888 + DITHER_TAIL + break; + case MPEG3_601_BGRA8888: + DITHER_601_HEAD + STORE_PIXEL_RGB565 + DITHER_TAIL + break; + case MPEG3_601_RGB565: + DITHER_601_HEAD + STORE_PIXEL_RGB565 + DITHER_TAIL + break; + case MPEG3_601_RGB888: + DITHER_601_HEAD + STORE_PIXEL_RGB888 + DITHER_TAIL + break; + case MPEG3_601_RGBA8888: + DITHER_601_HEAD + STORE_PIXEL_RGBA8888 + DITHER_TAIL + break; + case MPEG3_RGBA16161616: + { + register unsigned short *data_s = (unsigned short*)data; + DITHER_HEAD + STORE_PIXEL_RGBA16161616 + DITHER_TAIL + } + break; + } + } + DITHER_ROW_TAIL + } /* End of non-MMX */ + +#ifdef HAVE_MMX + if(video->have_mmx) + __asm__ __volatile__ ("emms"); +#endif + return 0; +} + +int mpeg3video_ditherframe444(mpeg3video_t *video, unsigned char *src[]) +{ + return 0; +} + +int mpeg3video_dithertop(mpeg3video_t *video, unsigned char *src[]) +{ + return mpeg3video_ditherframe(video, src, video->output_rows); +} + +int mpeg3video_dithertop444(mpeg3video_t *video, unsigned char *src[]) +{ + return 0; +} + +int mpeg3video_ditherbot(mpeg3video_t *video, unsigned char *src[]) +{ + return 0; +} + +int mpeg3video_ditherbot444(mpeg3video_t *video, unsigned char *src[]) +{ + return 0; +} + +void memcpy_fast(unsigned char *output, unsigned char *input, long len) +{ + int i, len2; +/* 8 byte alignment */ +/* + * if(!((long)input & 0x7)) + * { + * len2 = len >> 4; + * for(i = 0; i < len2; ) + * { + * ((MPEG3_INT64*)output)[i] = ((MPEG3_INT64*)input)[i]; + * i++; + * ((MPEG3_INT64*)output)[i] = ((MPEG3_INT64*)input)[i]; + * i++; + * } + * + * for(i *= 16; i < len; i++) + * { + * output[i] = input[i]; + * } + * } + * else + */ + memcpy(output, input, len); +} + +int mpeg3video_init_output() +{ + int i, value; + for(i = 0; i < 256; i++) + { + value = (int)(1.1644 * i - 255 * 0.0627 + 0.5); + if(value < 0) value = 0; + else + if(value > 255) value = 255; + mpeg3_601_to_rgb[i] = value; + } + return 0; +} + +int mpeg3video_present_frame(mpeg3video_t *video) +{ + int i, j, k, l; + unsigned char **src = video->output_src; + +/* Copy YUV buffers */ + if(video->want_yvu) + { + long size[2]; + long offset[2]; + +/* Drop a frame */ + if(!video->y_output) return 0; + +/* Copy a frame */ + if(video->in_x == 0 && + video->in_w >= video->coded_picture_width) + { + size[0] = video->coded_picture_width * video->in_h; + size[1] = video->chrom_width * (int)((float)video->in_h / 2 + 0.5); + offset[0] = video->coded_picture_width * video->in_y; + offset[1] = video->chrom_width * (int)((float)video->in_y / 2 + 0.5); + +/* + * if(video->in_y > 0) + * { + * offset[1] += video->chrom_width / 2; + * size[1] += video->chrom_width / 2; + * } + */ + + memcpy(video->y_output, src[0] + offset[0], size[0]); + memcpy(video->u_output, src[1] + offset[1], size[1]); + memcpy(video->v_output, src[2] + offset[1], size[1]); + } + else + { + for(i = 0, j = video->in_y; i < video->in_h; i++, j++) + { + memcpy(video->y_output + i * video->in_w, + src[0] + j * video->coded_picture_width + video->in_x, + video->in_w); + memcpy(video->u_output + i * video->in_w / 4, + src[1] + j * video->chrom_width / 2 + video->in_x / 4, + video->in_w / 4); + memcpy(video->v_output + i * video->in_w / 4, + src[2] + j * video->chrom_width / 2 + video->in_x / 4, + video->in_w / 4); + } + } + + return 0; + } + +/* Want RGB buffer */ +/* Copy the frame to the output with YUV to RGB conversion */ + if(video->prog_seq) + { + if(video->chroma_format != CHROMA444) + { + mpeg3video_ditherframe(video, src, video->output_rows); + } + else + mpeg3video_ditherframe444(video, src); + } + else + { + if((video->pict_struct == FRAME_PICTURE && video->topfirst) || + video->pict_struct == BOTTOM_FIELD) + { +/* top field first */ + if(video->chroma_format != CHROMA444) + { + mpeg3video_dithertop(video, src); + mpeg3video_ditherbot(video, src); + } + else + { + mpeg3video_dithertop444(video, src); + mpeg3video_ditherbot444(video, src); + } + } + else + { +/* bottom field first */ + if(video->chroma_format != CHROMA444) + { + mpeg3video_ditherbot(video, src); + mpeg3video_dithertop(video, src); + } + else + { + mpeg3video_ditherbot444(video, src); + mpeg3video_dithertop444(video, src); + } + } + } + return 0; +} + +int mpeg3video_display_second_field(mpeg3video_t *video) +{ +/* Not used */ + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/reconmmx.s b/core/multimedia/opieplayer/libmpeg3/video/reconmmx.s new file mode 100644 index 0000000..1bb98ef --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/reconmmx.s @@ -0,0 +1,301 @@ +ADD_1: dd 01010101h, 01010101h +MASK_AND: dd 7f7f7f7fh, 7f7f7f7fh +PLUS_384: dd 01800180h, 01800180h +PLUS_128: dd 00800080h, 00800080h + +%assign LocalFrameSize 0 +%assign RegisterStorageSize 16 + +; Arguments: +%assign source LocalFrameSize + RegisterStorageSize + 4 +%assign dest LocalFrameSize + RegisterStorageSize + 8 +%assign lx2 LocalFrameSize + RegisterStorageSize + 12 +%assign h LocalFrameSize + RegisterStorageSize + 16 + +; Locals (on local stack frame) + + +; extern void C rec_mmx ( +; unsigned char *source, +; unsigned char *dest, +; int lx2, +; int h +; +; The local variables are on the stack, +; + +global recva_mmx +global recvac_mmx +global rech_mmx +global rechc_mmx +global add_block_mmx +global set_block_mmx + + + align 16 +rech_mmx: + push esi + push edi + push ecx + push ebx + mov esi, [esp+source] + mov edi, [esp+dest] + mov ecx, [esp+h] + mov ebx, [esp+lx2] + movq mm5, [MASK_AND] + movq mm6, [ADD_1] +.rech1: + movq mm0,[esi] + movq mm1,[esi+1] + movq mm2,[esi+8] + movq mm3,[esi+9] + psrlw mm0,1 + psrlw mm1,1 + psrlw mm2,1 + psrlw mm3,1 + pand mm0,mm5 + pand mm1,mm5 + pand mm2,mm5 + pand mm3,mm5 + paddusb mm0,mm1 + paddusb mm2,mm3 + paddusb mm0,mm6 + paddusb mm2,mm6 + movq [edi],mm0 + add esi,ebx + movq [edi+8],mm2 + add edi,ebx + dec ecx + jnz .rech1 + emms + pop ebx + pop ecx + pop edi + pop esi + ret + + align 16 +rechc_mmx: + push esi + push edi + push ecx + push ebx +; sub esp, LocalFrameSize + mov esi, [esp+source] + mov edi, [esp+dest] + mov ecx, [esp+h] + mov ebx, [esp+lx2] + movq mm5, [MASK_AND] + movq mm6, [ADD_1] +.rechc1: + movq mm0,[esi] + movq mm1,[esi+1] + psrlw mm0,1 + psrlw mm1,1 + pand mm0,mm5 + pand mm1,mm5 + paddusb mm0,mm1 + paddusb mm0,mm6 + movq [edi],mm0 + add edi,ebx + add esi,ebx + dec ecx + jnz .rechc1 + emms +; add esp, LocalFrameSize + pop ebx + pop ecx + pop edi + pop esi + ret + + + +%assign RegisterStorageSize 20 +%assign source LocalFrameSize + RegisterStorageSize + 4 +%assign dest LocalFrameSize + RegisterStorageSize + 8 +%assign lx LocalFrameSize + RegisterStorageSize + 12 +%assign lx2 LocalFrameSize + RegisterStorageSize + 16 +%assign h LocalFrameSize + RegisterStorageSize + 20 + + align 16 +recva_mmx: + push esi + push edi + push ecx + push ebx + push edx + mov esi, [esp+source] + mov edi, [esp+dest] + mov ecx, [esp+h] + mov ebx, [esp+lx2] + mov edx, [esp+lx] + movq mm7, [MASK_AND] + movq mm6, [ADD_1] +.recva1: + movq mm0,[esi] + movq mm1,[esi+edx] + movq mm2,[esi+8] + movq mm3,[esi+edx+8] + movq mm4,[edi] + movq mm5,[edi+8] + psrlw mm0,1 + psrlw mm1,1 + psrlw mm2,1 + psrlw mm3,1 + psrlw mm4,1 + psrlw mm5,1 + pand mm0,mm7 + pand mm1,mm7 + pand mm2,mm7 + pand mm3,mm7 + pand mm4,mm7 + pand mm5,mm7 + paddusb mm0,mm1 + paddusb mm2,mm3 + paddusb mm0,mm6 + paddusb mm2,mm6 + psrlw mm0,1 + psrlw mm2,1 + pand mm0,mm7 + pand mm2,mm7 + paddusb mm4,mm0 + paddusb mm5,mm2 + paddusb mm4,mm6 + paddusb mm5,mm6 + movq [edi],mm4 + movq [edi+8],mm5 + add edi,ebx + add esi,ebx + dec ecx + jnz near .recva1 + emms + pop edx + pop ebx + pop ecx + pop edi + pop esi + ret + + align 16 +recvac_mmx: + push esi + push edi + push ecx + push ebx + push edx + mov esi, [esp+source] + mov edi, [esp+dest] + mov ecx, [esp+h] + mov ebx, [esp+lx2] + mov edx, [esp+lx] + movq mm5, [MASK_AND] + movq mm6, [ADD_1] +.recvac1: + movq mm0,[esi] + movq mm1,[esi+edx] + movq mm4,[edi] + psrlw mm0,1 + psrlw mm1,1 + psrlw mm4,1 + pand mm0,mm5 + pand mm1,mm5 + pand mm4,mm5 + paddusb mm0,mm1 + paddusb mm0,mm6 + psrlw mm0,1 + pand mm0,mm5 + paddusb mm4,mm0 + paddusb mm4,mm6 + movq [edi],mm4 + add edi,ebx + add esi,ebx + dec ecx + jnz .recvac1 + emms + pop edx + pop ebx + pop ecx + pop edi + pop esi + ret + +%assign RegisterStorageSize 20 +%assign rfp LocalFrameSize + RegisterStorageSize + 4 +%assign bp LocalFrameSize + RegisterStorageSize + 8 +%assign iincr LocalFrameSize + RegisterStorageSize + 12 + +; FIXME clipping needs to be done + + align 16 +add_block_mmx: + push esi + push edi + push ecx + push ebx + push edx + mov esi, [esp+bp] + mov edi, [esp+rfp] + mov ebx, [esp+iincr] +; movq mm7, [PLUS_384] + mov ecx,8 + pxor mm2,mm2 ; clear +%rep 8 + movq mm0, [edi] ; get dest + movq mm1,mm0 + punpcklbw mm0,mm2 + punpckhbw mm1,mm2 + paddsw mm0, [esi] + paddsw mm1, [esi+8] +; paddsw mm0, mm7 +; paddsw mm1, mm7 + packuswb mm0,mm1 + movq [edi], mm0 + add edi,ebx + add esi,16 +%endrep + emms + pop edx + pop ebx + pop ecx + pop edi + pop esi + ret + + align 16 +set_block_mmx: + push esi + push edi + push ecx + push ebx + push edx + mov esi, [esp+bp] + mov edi, [esp+rfp] + mov ebx, [esp+iincr] + movq mm7, [PLUS_128] +%rep 4 + movq mm0, [esi] + movq mm1, [esi+8] + paddsw mm0, mm7 + movq mm2, [esi+16] + paddsw mm1, mm7 + movq mm3, [esi+24] + paddsw mm2, mm7 + packuswb mm0, mm1 + paddsw mm3, mm7 + movq [edi], mm0 + packuswb mm2, mm3 + add edi, ebx + add esi, 32 + movq [edi], mm2 + add edi, ebx +%endrep + emms + pop edx + pop ebx + pop ecx + pop edi + pop esi + ret + + diff --git a/core/multimedia/opieplayer/libmpeg3/video/reconstruct.c b/core/multimedia/opieplayer/libmpeg3/video/reconstruct.c new file mode 100644 index 0000000..531f9c0 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/reconstruct.c @@ -0,0 +1,1290 @@ +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" +#include <stdio.h> + +#ifdef HAVE_MMX + +#ifdef HAVE_3Dnow +static inline void recva_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + __asm__( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq 8(%1), %%mm1\n" /* 8 s */ + "movq (%4), %%mm2\n" /* 8 s +lx */ + "movq 8(%4), %%mm3\n" /* 8 s +lx **/ + + "pavgusb %%mm2, %%mm0\n" + "addl %3, %1\n" + "pavgusb %%mm3, %%mm1\n" + + "movq (%2), %%mm2\n" /* 8 d */ + "movq 8(%2), %%mm3\n" /* 8 d */ + "pavgusb %%mm2, %%mm0\n" + "addl %3, %4\n" + "pavgusb %%mm3, %%mm1\n" + + "movq %%mm0, (%2)\n" + "movq %%mm1, 8(%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +} + +static inline void recvac_mmx(unsigned char *s, unsigned char *d, int lx,int lx2, int h) +{ + __asm__( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq (%4), %%mm2\n" /* 8 s +lx */ + "addl %3, %1\n" + "pavgusb %%mm2, %%mm0\n" + "movq (%2), %%mm3\n" /* 8 d */ + "addl %3, %4\n" + "pavgusb %%mm3, %%mm0\n" + "movq %%mm0, (%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +} + +static inline void rech_mmx(unsigned char *s, unsigned char *d, int lx2, int h) +{ + __asm__ ( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq 8(%1), %%mm1\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s */ + "movq 9(%1), %%mm3\n" /* 8 s */ + + "pavgusb %%mm2, %%mm0\n" + "addl %3, %1\n" + "pavgusb %%mm3, %%mm1\n" + + "movq %%mm0, (%2)\n" + "movq %%mm1, 8(%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +} + +static inline void rechc_mmx(unsigned char *s, unsigned char *d, int lx2, int h) +{ + __asm__ ( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s +1 */ + "addl %3, %1\n" + "pavgusb %%mm2, %%mm0\n" + "movq %%mm0, (%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +} + +static inline void recha_mmx(unsigned char *s, unsigned char *d,int lx2, int h) +{ + __asm__ ( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq 8(%1), %%mm1\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s */ + "movq 9(%1), %%mm3\n" /* 8 s */ + + "pavgusb %%mm2, %%mm0\n" + "addl %3, %1\n" + "pavgusb %%mm3, %%mm1\n" + + "movq (%2), %%mm2\n" /* 8 d */ + "movq 8(%2), %%mm3\n" /* 8 d */ + "pavgusb %%mm2, %%mm0\n" + "pavgusb %%mm3, %%mm1\n" + + "movq %%mm0, (%2)\n" + "movq %%mm1, 8(%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +} + +static inline void rechac_mmx(unsigned char *s,unsigned char *d, int lx2, int h) +{ + __asm__ ( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s */ + + "addl %3, %1\n" + "pavgusb %%mm2, %%mm0\n" + + "movq (%2), %%mm1\n" /* 8 d */ + "pavgusb %%mm1, %%mm0\n" + + "movq %%mm0, (%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +} + +static inline void rec4_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + __asm__ __volatile__( + "movq (%1), %%mm0\n" /* 8 s */ + "movq 8(%1), %%mm1\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s +1*/ + "movq 9(%1), %%mm3\n" /* 8 s +1*/ + ".align 8\n" + "1:" + "movq (%4), %%mm4\n" /* 8 s+lx */ + "pavgusb %%mm2, %%mm0\n" + "movq 8(%4), %%mm5\n" /* 8 s+lx */ + "pavgusb %%mm3, %%mm1\n" + + "movq 1(%4), %%mm6\n" /* 8 s+lx +1*/ + "pavgusb %%mm4, %%mm0\n" + "movq 9(%4), %%mm7\n" /* 8 s+lx +1*/ + "pavgusb %%mm5, %%mm1\n" + + "pavgusb %%mm6, %%mm0\n" + "addl %3, %4\n" + "pavgusb %%mm7, %%mm1\n" + "movq %%mm0, (%2)\n" + "movq %%mm6, %%mm2\n" + "movq %%mm7, %%mm3\n" + "movq %%mm1, 8(%2)\n" + "movq %%mm4, %%mm0\n" + "movq %%mm5, %%mm1\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +} + +static inline void rec4c_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + __asm__ __volatile__( + "movq (%1), %%mm0\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s +1*/ + ".align 8\n" + "1:" + "movq (%4), %%mm4\n" /* 8 s+lx */ + "pavgusb %%mm2, %%mm0\n" + + "movq 1(%4), %%mm6\n" /* 8 s+lx +1*/ + "pavgusb %%mm4, %%mm0\n" + + "addl %3, %4\n" + "pavgusb %%mm6, %%mm0\n" + "movq %%mm0, (%2)\n" + "movq %%mm6, %%mm2\n" + "movq %%mm4, %%mm0\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +} + +static inline void rec4a_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + __asm__ __volatile__( + "movq (%1), %%mm0\n" /* 8 s */ + "movq 8(%1), %%mm1\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s +1*/ + "movq 9(%1), %%mm3\n" /* 8 s +1*/ + ".align 8\n" + "1:" + "movq (%4), %%mm4\n" /* 8 s+lx */ + "pavgusb %%mm2, %%mm0\n" + "movq 8(%4), %%mm5\n" /* 8 s+lx */ + "pavgusb %%mm3, %%mm1\n" + + "movq 1(%4), %%mm6\n" /* 8 s+lx +1*/ + "pavgusb %%mm4, %%mm0\n" + "movq 9(%4), %%mm7\n" /* 8 s+lx +1*/ + "pavgusb %%mm5, %%mm1\n" + "movq (%2), %%mm2\n" + "pavgusb %%mm6, %%mm0\n" + "movq 8(%2), %%mm3\n" + + "pavgusb %%mm2, %%mm0\n" + "addl %3, %4\n" + "pavgusb %%mm3, %%mm1\n" + "movq %%mm0, (%2)\n" + + "pavgusb %%mm7, %%mm1\n" + "movq %%mm6, %%mm2\n" + "movq %%mm7, %%mm3\n" + "movq %%mm1, 8(%2)\n" + "movq %%mm4, %%mm0\n" + "movq %%mm5, %%mm1\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +} + +static inline void rec4ac_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + __asm__ __volatile__( + "movq (%1), %%mm0\n" /* 8 s */ + "movq 1(%1), %%mm2\n" /* 8 s +1*/ + ".align 8\n" + "1:" + "movq (%4), %%mm4\n" /* 8 s+lx */ + "pavgusb %%mm2, %%mm0\n" + + "movq 1(%4), %%mm6\n" /* 8 s+lx +1*/ + "pavgusb %%mm4, %%mm0\n" + "movq (%2), %%mm1\n" /* 8 d */ + "pavgusb %%mm6, %%mm0\n" + "addl %3, %4\n" + "pavgusb %%mm1, %%mm0\n" + "movq %%mm6, %%mm2\n" + "movq %%mm0, (%2)\n" + "movq %%mm4, %%mm0\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +} + +#else // HAVE_3DNOW + static LONGLONG ADD_1 = 0x0101010101010101LL; + static LONGLONG MASK_AND = 0x7f7f7f7f7f7f7f7fLL; +#endif + +static inline void rec_mmx(unsigned char *s, unsigned char *d, int lx2, int h) +{ + __asm__ __volatile__( + ".align 8\n" + "1:\t" + "movq ( %1 ), %%mm0\n" /* 8 s */ + "movq 8( %1 ), %%mm2\n" /* 16 s */ + "movq %%mm0, ( %2 )\n" + "addl %3, %1\n" + "movq %%mm2, 8( %2 )\n" + "decl %0\n" + "leal (%2, %3), %2\n" + "jnz 1b" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +} + + +static inline void recc_mmx(unsigned char *s, unsigned char *d, int lx2, int h) +{ + __asm__ __volatile__( + ".align 8\n" + "1:\t" + "movq ( %1 ), %%mm0\n" + "addl %3, %1\n" + "movq %%mm0, ( %2 )\n" + "decl %0\n" + "leal (%2, %3), %2\n" + "jnz 1b" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +} + + +static inline void reca_mmx(unsigned char *s, unsigned char *d, int lx2, int h) +{ +#ifdef HAVE_3Dnow + __asm__ ( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq (%2), %%mm2\n" /* 8 d */ + "movq 8(%1), %%mm1\n" /* 8 s */ + "movq 8(%2), %%mm3\n" /* 8 d */ + "pavgusb %%mm2, %%mm0\n" + "addl %3, %1\n" + "pavgusb %%mm3, %%mm1\n" + + "movq %%mm0, (%2)\n" + "movq %%mm1, 8(%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +#else /* No 3dnow */ + __asm__ ( + "movq MASK_AND, %%mm5\n" + "movq ADD_1, %%mm6\n" + "1:\t" + "movq (%1),%%mm0\n" /* Load 16 pixels from each row */ + "movq (%2),%%mm1\n" + "movq 8(%1),%%mm2\n" + "movq 8(%2),%%mm3\n" + "psrlw $1,%%mm0\n" /* Shift pixels down */ + "psrlw $1,%%mm1\n" + "pand %%mm5,%%mm0\n" /* Zero out significant bit */ + "psrlw $1,%%mm2\n" + "pand %%mm5,%%mm1\n" + "psrlw $1,%%mm3\n" + "pand %%mm5,%%mm2\n" + "paddusb %%mm1,%%mm0\n" /* Add pixels */ + "pand %%mm5,%%mm3\n" + "paddusb %%mm3,%%mm2\n" + "paddusb %%mm6,%%mm0\n" /* Add 1 to results */ + "paddusb %%mm6,%%mm2\n" + "movq %%mm0,(%2)\n" + "addl %3,%1\n" + "movq %%mm2, 8(%2)\n" + "decl %0\n" + "leal (%2, %3), %2\n" + "jnz 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +#endif +} + + +static inline void recac_mmx(unsigned char *s, unsigned char *d, int lx2, int h) +{ +#ifdef HAVE_3Dnow + __asm__ ( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq (%2), %%mm2\n" /* 8 d */ + "pavgusb %%mm2, %%mm0\n" + "addl %3, %1\n" + "movq %%mm0, (%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +#else /* No 3dnow */ + __asm__ ( + "movq MASK_AND, %%mm5\n" + "movq ADD_1, %%mm6\n" + "1:\t" + "movq (%1),%%mm0\n" + "movq (%2),%%mm1\n" + "psrlw $1,%%mm0\n" + "psrlw $1,%%mm1\n" + "pand %%mm5,%%mm0\n" + "pand %%mm5,%%mm1\n" + "paddusb %%mm1,%%mm0\n" + "paddusb %%mm6,%%mm0\n" + "addl %3,%1\n" + "movq %%mm0,(%2)\n" + "decl %0\n" + "leal (%2, %3), %2\n" + "jnz 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2) + ); +#endif +} + + +static inline void recv_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ +#ifdef HAVE_3Dnow + __asm__( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq (%4), %%mm2\n" /* 8 s +lx */ + "movq 8(%1), %%mm1\n" /* 8 s */ + "movq 8(%4), %%mm3\n" /* 8 s +lx **/ + + "pavgusb %%mm2, %%mm0\n" + "addl %3, %1\n" + "pavgusb %%mm3, %%mm1\n" + + "movq %%mm0, (%2)\n" + "addl %3, %4\n" + "movq %%mm1, 8(%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +#else + __asm__ ( + "movq MASK_AND, %%mm5\n" + "movq ADD_1, %%mm6\n" + "1:\t" + "movq (%1), %%mm0\n" /* 8 s */ + "movq (%4), %%mm1\n" /* 8 s +lx */ + "movq 8(%1), %%mm2\n" /* 8 s */ + "movq 8(%4), %%mm3\n" /* 8 s +lx **/ + "psrlw $1,%%mm0\n" + "psrlw $1,%%mm1\n" + "pand %%mm5,%%mm0\n" + "psrlw $1,%%mm2\n" + "pand %%mm5,%%mm1\n" + "psrlw $1,%%mm3\n" + "pand %%mm5,%%mm2\n" + "paddusb %%mm1,%%mm0\n" + "pand %%mm5,%%mm3\n" + "paddusb %%mm3,%%mm2\n" + "paddusb %%mm6,%%mm0\n" + "paddusb %%mm6,%%mm2\n" + "movq %%mm0,(%2)\n" + "addl %3,%1\n" + "movq %%mm2, 8(%2)\n" + "addl %3,%4\n" + "decl %0\n" + "leal (%2, %3), %2\n" + "jnz 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +#endif +} + + +static inline void recvc_mmx(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ +#ifdef HAVE_3Dnow + __asm__( + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 s */ + "movq (%4), %%mm2\n" /* 8 s +lx */ + "addl %3, %1\n" + "pavgusb %%mm2, %%mm0\n" + "addl %3, %4\n" + "movq %%mm0, (%2)\n" + "addl %3, %2\n" + "loop 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +#else + __asm__ ( + "movq MASK_AND, %%mm5\n" + "movq ADD_1, %%mm6\n" + "1:\t" + "movq (%1), %%mm0\n" /* 8 s */ + "movq (%4), %%mm1\n" /* 8 s +lx */ + "psrlw $1,%%mm0\n" + "psrlw $1,%%mm1\n" + "pand %%mm5,%%mm0\n" + "pand %%mm5,%%mm1\n" + "paddusb %%mm1,%%mm0\n" + "addl %3,%1\n" + "paddusb %%mm6,%%mm0\n" + "addl %3,%4\n" + "movq %%mm0,(%2)\n" + "decl %0\n" + "leal (%2, %3), %2\n" + "jnz 1b\n" + : + : "c" (h), "r" (s), "r" (d), "r" (lx2), "r" (s +lx) + ); +#endif +} + +#endif // HAVE_MMX + +static inline void rec(unsigned char *s, unsigned char *d, int lx2, int h) +{ + int j; + for(j = 0; j < h; j++, s += lx2, d += lx2) + { + d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; d[3] = s[3]; + d[4] = s[4]; d[5] = s[5]; d[6] = s[6]; d[7] = s[7]; + d[8] = s[8]; d[9] = s[9]; d[10] = s[10]; d[11] = s[11]; + d[12] = s[12]; d[13] = s[13]; d[14] = s[14]; d[15] = s[15]; + } +} + + + +static inline void recc(unsigned char *s, unsigned char *d, int lx2, int h) +{ + int j; + for(j = 0; j < h; j++, s += lx2, d += lx2) + { + d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; d[3] = s[3]; + d[4] = s[4]; d[5] = s[5]; d[6] = s[6]; d[7] = s[7]; + } +} + +static inline void reca(unsigned char *s, unsigned char *d, int lx2, int h) +{ + int j; + for(j = 0; j < h; j++, s +=lx2, d +=lx2) + { + d[0] = (unsigned int)(d[0] + s[0] + 1) >> 1; + d[1] = (unsigned int)(d[1] + s[1] + 1) >> 1; + d[2] = (unsigned int)(d[2] + s[2] + 1) >> 1; + d[3] = (unsigned int)(d[3] + s[3] + 1) >> 1; + d[4] = (unsigned int)(d[4] + s[4] + 1) >> 1; + d[5] = (unsigned int)(d[5] + s[5] + 1) >> 1; + d[6] = (unsigned int)(d[6] + s[6] + 1) >> 1; + d[7] = (unsigned int)(d[7] + s[7] + 1) >> 1; + d[8] = (unsigned int)(d[8] + s[8] + 1) >> 1; + d[9] = (unsigned int)(d[9] + s[9] + 1) >> 1; + d[10] = (unsigned int)(d[10] + s[10] + 1) >> 1; + d[11] = (unsigned int)(d[11] + s[11] + 1) >> 1; + d[12] = (unsigned int)(d[12] + s[12] + 1) >> 1; + d[13] = (unsigned int)(d[13] + s[13] + 1) >> 1; + d[14] = (unsigned int)(d[14] + s[14] + 1) >> 1; + d[15] = (unsigned int)(d[15] + s[15] + 1) >> 1; + } +} + +static inline void recac(unsigned char *s, unsigned char *d, int lx2, int h) +{ + int j; + for(j = 0; j < h; j++, s += lx2, d += lx2) + { + d[0] = (unsigned int)(d[0] + s[0] + 1)>>1; + d[1] = (unsigned int)(d[1] + s[1] + 1)>>1; + d[2] = (unsigned int)(d[2] + s[2] + 1)>>1; + d[3] = (unsigned int)(d[3] + s[3] + 1)>>1; + d[4] = (unsigned int)(d[4] + s[4] + 1)>>1; + d[5] = (unsigned int)(d[5] + s[5] + 1)>>1; + d[6] = (unsigned int)(d[6] + s[6] + 1)>>1; + d[7] = (unsigned int)(d[7] + s[7] + 1)>>1; + } +} + +static inline void recv_(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + unsigned char *dp,*sp,*sp2; + int j; + sp = s; + sp2 = s + lx; + dp = d; + for(j = 0; j < h; j++) + { + dp[0] = (unsigned int)(sp[0] + sp2[0] + 1) >> 1; + dp[1] = (unsigned int)(sp[1] + sp2[1] + 1) >> 1; + dp[2] = (unsigned int)(sp[2] + sp2[2] + 1) >> 1; + dp[3] = (unsigned int)(sp[3] + sp2[3] + 1) >> 1; + dp[4] = (unsigned int)(sp[4] + sp2[4] + 1) >> 1; + dp[5] = (unsigned int)(sp[5] + sp2[5] + 1) >> 1; + dp[6] = (unsigned int)(sp[6] + sp2[6] + 1) >> 1; + dp[7] = (unsigned int)(sp[7] + sp2[7] + 1) >> 1; + dp[8] = (unsigned int)(sp[8] + sp2[8] + 1) >> 1; + dp[9] = (unsigned int)(sp[9] + sp2[9] + 1) >> 1; + dp[10] = (unsigned int)(sp[10] + sp2[10] + 1) >> 1; + dp[11] = (unsigned int)(sp[11] + sp2[11] + 1) >> 1; + dp[12] = (unsigned int)(sp[12] + sp2[12] + 1) >> 1; + dp[13] = (unsigned int)(sp[13] + sp2[13] + 1) >> 1; + dp[14] = (unsigned int)(sp[14] + sp2[14] + 1) >> 1; + dp[15] = (unsigned int)(sp[15] + sp2[15] + 1) >> 1; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + +static inline void recvc(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + unsigned char *dp,*sp,*sp2; + int j; + + sp = s; + sp2 = s+lx; + dp = d; + for(j = 0; j < h; j++) + { + dp[0] = (unsigned int)(sp[0]+sp2[0]+1)>>1; + dp[1] = (unsigned int)(sp[1]+sp2[1]+1)>>1; + dp[2] = (unsigned int)(sp[2]+sp2[2]+1)>>1; + dp[3] = (unsigned int)(sp[3]+sp2[3]+1)>>1; + dp[4] = (unsigned int)(sp[4]+sp2[4]+1)>>1; + dp[5] = (unsigned int)(sp[5]+sp2[5]+1)>>1; + dp[6] = (unsigned int)(sp[6]+sp2[6]+1)>>1; + dp[7] = (unsigned int)(sp[7]+sp2[7]+1)>>1; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + + +static inline void recva(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + unsigned char *dp,*sp,*sp2; + int j; + + sp = s; + sp2 = s+lx; + dp = d; + for (j=0; j<h; j++){ + dp[0] = (dp[0] + ((unsigned int)(sp[0]+sp2[0]+1)>>1) + 1)>>1; + dp[1] = (dp[1] + ((unsigned int)(sp[1]+sp2[1]+1)>>1) + 1)>>1; + dp[2] = (dp[2] + ((unsigned int)(sp[2]+sp2[2]+1)>>1) + 1)>>1; + dp[3] = (dp[3] + ((unsigned int)(sp[3]+sp2[3]+1)>>1) + 1)>>1; + dp[4] = (dp[4] + ((unsigned int)(sp[4]+sp2[4]+1)>>1) + 1)>>1; + dp[5] = (dp[5] + ((unsigned int)(sp[5]+sp2[5]+1)>>1) + 1)>>1; + dp[6] = (dp[6] + ((unsigned int)(sp[6]+sp2[6]+1)>>1) + 1)>>1; + dp[7] = (dp[7] + ((unsigned int)(sp[7]+sp2[7]+1)>>1) + 1)>>1; + dp[8] = (dp[8] + ((unsigned int)(sp[8]+sp2[8]+1)>>1) + 1)>>1; + dp[9] = (dp[9] + ((unsigned int)(sp[9]+sp2[9]+1)>>1) + 1)>>1; + dp[10] = (dp[10] + ((unsigned int)(sp[10]+sp2[10]+1)>>1) + 1)>>1; + dp[11] = (dp[11] + ((unsigned int)(sp[11]+sp2[11]+1)>>1) + 1)>>1; + dp[12] = (dp[12] + ((unsigned int)(sp[12]+sp2[12]+1)>>1) + 1)>>1; + dp[13] = (dp[13] + ((unsigned int)(sp[13]+sp2[13]+1)>>1) + 1)>>1; + dp[14] = (dp[14] + ((unsigned int)(sp[14]+sp2[14]+1)>>1) + 1)>>1; + dp[15] = (dp[15] + ((unsigned int)(sp[15]+sp2[15]+1)>>1) + 1)>>1; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + + +static inline void recvac(unsigned char *s, unsigned char *d, int lx,int lx2, int h){ + unsigned char *dp,*sp,*sp2; + int j; + + sp = s; + sp2 = s+lx; + dp = d; + for (j=0; j<h; j++){ + dp[0] = (dp[0] + ((unsigned int)(sp[0]+sp2[0]+1)>>1) + 1)>>1; + dp[1] = (dp[1] + ((unsigned int)(sp[1]+sp2[1]+1)>>1) + 1)>>1; + dp[2] = (dp[2] + ((unsigned int)(sp[2]+sp2[2]+1)>>1) + 1)>>1; + dp[3] = (dp[3] + ((unsigned int)(sp[3]+sp2[3]+1)>>1) + 1)>>1; + dp[4] = (dp[4] + ((unsigned int)(sp[4]+sp2[4]+1)>>1) + 1)>>1; + dp[5] = (dp[5] + ((unsigned int)(sp[5]+sp2[5]+1)>>1) + 1)>>1; + dp[6] = (dp[6] + ((unsigned int)(sp[6]+sp2[6]+1)>>1) + 1)>>1; + dp[7] = (dp[7] + ((unsigned int)(sp[7]+sp2[7]+1)>>1) + 1)>>1; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + + +static inline void rech(unsigned char *s, unsigned char *d, int lx2, int h){ + unsigned char *dp,*sp; + unsigned int s1,s2; + int j; + + sp = s; + dp = d; + for (j=0; j<h; j++){ + s1=sp[0]; + dp[0] = (unsigned int)(s1+(s2=sp[1])+1)>>1; + dp[1] = (unsigned int)(s2+(s1=sp[2])+1)>>1; + dp[2] = (unsigned int)(s1+(s2=sp[3])+1)>>1; + dp[3] = (unsigned int)(s2+(s1=sp[4])+1)>>1; + dp[4] = (unsigned int)(s1+(s2=sp[5])+1)>>1; + dp[5] = (unsigned int)(s2+(s1=sp[6])+1)>>1; + dp[6] = (unsigned int)(s1+(s2=sp[7])+1)>>1; + dp[7] = (unsigned int)(s2+(s1=sp[8])+1)>>1; + dp[8] = (unsigned int)(s1+(s2=sp[9])+1)>>1; + dp[9] = (unsigned int)(s2+(s1=sp[10])+1)>>1; + dp[10] = (unsigned int)(s1+(s2=sp[11])+1)>>1; + dp[11] = (unsigned int)(s2+(s1=sp[12])+1)>>1; + dp[12] = (unsigned int)(s1+(s2=sp[13])+1)>>1; + dp[13] = (unsigned int)(s2+(s1=sp[14])+1)>>1; + dp[14] = (unsigned int)(s1+(s2=sp[15])+1)>>1; + dp[15] = (unsigned int)(s2+sp[16]+1)>>1; + sp+= lx2; + dp+= lx2; + } +} + + +static inline void rechc(unsigned char *s,unsigned char *d, int lx2, int h){ + unsigned char *dp,*sp; + unsigned int s1,s2; + int j; + + sp = s; + dp = d; + for (j=0; j<h; j++){ + s1=sp[0]; + dp[0] = (unsigned int)(s1+(s2=sp[1])+1)>>1; + dp[1] = (unsigned int)(s2+(s1=sp[2])+1)>>1; + dp[2] = (unsigned int)(s1+(s2=sp[3])+1)>>1; + dp[3] = (unsigned int)(s2+(s1=sp[4])+1)>>1; + dp[4] = (unsigned int)(s1+(s2=sp[5])+1)>>1; + dp[5] = (unsigned int)(s2+(s1=sp[6])+1)>>1; + dp[6] = (unsigned int)(s1+(s2=sp[7])+1)>>1; + dp[7] = (unsigned int)(s2+sp[8]+1)>>1; + sp+= lx2; + dp+= lx2; + } +} + +static inline void recha(unsigned char *s, unsigned char *d,int lx2, int h) +{ + unsigned char *dp,*sp; + unsigned int s1,s2; + int j; + + sp = s; + dp = d; + for (j = 0; j < h; j++) + { + s1 = sp[0]; + dp[0] = (dp[0] + ((unsigned int)(s1 + (s2 = sp[1]) + 1) >> 1) + 1) >> 1; + dp[1] = (dp[1] + ((unsigned int)(s2 + (s1 = sp[2]) + 1) >> 1) + 1) >> 1; + dp[2] = (dp[2] + ((unsigned int)(s1 + (s2 = sp[3]) + 1) >> 1) + 1) >> 1; + dp[3] = (dp[3] + ((unsigned int)(s2 + (s1 = sp[4]) + 1) >> 1) + 1) >> 1; + dp[4] = (dp[4] + ((unsigned int)(s1 + (s2 = sp[5]) + 1) >> 1) + 1) >> 1; + dp[5] = (dp[5] + ((unsigned int)(s2 + (s1 = sp[6]) + 1) >> 1) + 1) >> 1; + dp[6] = (dp[6] + ((unsigned int)(s1 + (s2 = sp[7]) + 1) >> 1) + 1) >> 1; + dp[7] = (dp[7] + ((unsigned int)(s2 + (s1 = sp[8]) + 1) >> 1) + 1) >> 1; + dp[8] = (dp[8] + ((unsigned int)(s1 + (s2 = sp[9]) + 1) >> 1) + 1) >> 1; + dp[9] = (dp[9] + ((unsigned int)(s2 + (s1 = sp[10]) + 1) >> 1) + 1) >> 1; + dp[10] = (dp[10] + ((unsigned int)(s1 + (s2 = sp[11]) + 1) >> 1) + 1) >> 1; + dp[11] = (dp[11] + ((unsigned int)(s2 + (s1 = sp[12]) + 1) >> 1) + 1) >> 1; + dp[12] = (dp[12] + ((unsigned int)(s1 + (s2 = sp[13]) + 1) >> 1) + 1) >> 1; + dp[13] = (dp[13] + ((unsigned int)(s2 + (s1 = sp[14]) + 1) >> 1) + 1) >> 1; + dp[14] = (dp[14] + ((unsigned int)(s1 + (s2 = sp[15]) + 1) >> 1) + 1) >> 1; + dp[15] = (dp[15] + ((unsigned int)(s2 + sp[16] + 1) >> 1) + 1) >> 1; + sp += lx2; + dp += lx2; + } +} + + +static inline void rechac(unsigned char *s,unsigned char *d, int lx2, int h) +{ + unsigned char *dp,*sp; + unsigned int s1,s2; + int j; + + sp = s; + dp = d; + for(j = 0; j < h; j++) + { + s1 = sp[0]; + dp[0] = (dp[0] + ((unsigned int)(s1 + (s2 = sp[1]) + 1) >> 1) + 1) >> 1; + dp[1] = (dp[1] + ((unsigned int)(s2 + (s1 = sp[2]) + 1) >> 1) + 1) >> 1; + dp[2] = (dp[2] + ((unsigned int)(s1 + (s2 = sp[3]) + 1) >> 1) + 1) >> 1; + dp[3] = (dp[3] + ((unsigned int)(s2 + (s1 = sp[4]) + 1) >> 1) + 1) >> 1; + dp[4] = (dp[4] + ((unsigned int)(s1 + (s2 = sp[5]) + 1) >> 1) + 1) >> 1; + dp[5] = (dp[5] + ((unsigned int)(s2 + (s1 = sp[6]) + 1) >> 1) + 1) >> 1; + dp[6] = (dp[6] + ((unsigned int)(s1 + (s2 = sp[7]) + 1) >> 1) + 1) >> 1; + dp[7] = (dp[7] + ((unsigned int)(s2 + sp[8] + 1) >> 1) + 1) >> 1; + sp += lx2; + dp += lx2; + } +} + + +static inline void rec4(unsigned char *s, unsigned char *d, int lx, int lx2, int h) +{ + unsigned char *dp,*sp,*sp2; + unsigned int s1,s2,s3,s4; + int j; + + sp = s; + sp2 = s+lx; + dp = d; + for (j=0; j<h; j++){ + s1=sp[0]; s3=sp2[0]; + dp[0] = (unsigned int)(s1+(s2=sp[1])+s3+(s4=sp2[1])+2)>>2; + dp[1] = (unsigned int)(s2+(s1=sp[2])+s4+(s3=sp2[2])+2)>>2; + dp[2] = (unsigned int)(s1+(s2=sp[3])+s3+(s4=sp2[3])+2)>>2; + dp[3] = (unsigned int)(s2+(s1=sp[4])+s4+(s3=sp2[4])+2)>>2; + dp[4] = (unsigned int)(s1+(s2=sp[5])+s3+(s4=sp2[5])+2)>>2; + dp[5] = (unsigned int)(s2+(s1=sp[6])+s4+(s3=sp2[6])+2)>>2; + dp[6] = (unsigned int)(s1+(s2=sp[7])+s3+(s4=sp2[7])+2)>>2; + dp[7] = (unsigned int)(s2+(s1=sp[8])+s4+(s3=sp2[8])+2)>>2; + dp[8] = (unsigned int)(s1+(s2=sp[9])+s3+(s4=sp2[9])+2)>>2; + dp[9] = (unsigned int)(s2+(s1=sp[10])+s4+(s3=sp2[10])+2)>>2; + dp[10] = (unsigned int)(s1+(s2=sp[11])+s3+(s4=sp2[11])+2)>>2; + dp[11] = (unsigned int)(s2+(s1=sp[12])+s4+(s3=sp2[12])+2)>>2; + dp[12] = (unsigned int)(s1+(s2=sp[13])+s3+(s4=sp2[13])+2)>>2; + dp[13] = (unsigned int)(s2+(s1=sp[14])+s4+(s3=sp2[14])+2)>>2; + dp[14] = (unsigned int)(s1+(s2=sp[15])+s3+(s4=sp2[15])+2)>>2; + dp[15] = (unsigned int)(s2+sp[16]+s4+sp2[16]+2)>>2; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + + +static inline void rec4c(unsigned char *s,unsigned char *d, int lx, int lx2, int h) +{ + unsigned char *dp,*sp,*sp2; + unsigned int s1,s2,s3,s4; + int j; + + sp = s; + sp2 = s+lx; + dp = d; + for (j=0; j<h; j++){ + s1=sp[0]; s3=sp2[0]; + dp[0] = (unsigned int)(s1+(s2=sp[1])+s3+(s4=sp2[1])+2)>>2; + dp[1] = (unsigned int)(s2+(s1=sp[2])+s4+(s3=sp2[2])+2)>>2; + dp[2] = (unsigned int)(s1+(s2=sp[3])+s3+(s4=sp2[3])+2)>>2; + dp[3] = (unsigned int)(s2+(s1=sp[4])+s4+(s3=sp2[4])+2)>>2; + dp[4] = (unsigned int)(s1+(s2=sp[5])+s3+(s4=sp2[5])+2)>>2; + dp[5] = (unsigned int)(s2+(s1=sp[6])+s4+(s3=sp2[6])+2)>>2; + dp[6] = (unsigned int)(s1+(s2=sp[7])+s3+(s4=sp2[7])+2)>>2; + dp[7] = (unsigned int)(s2+sp[8]+s4+sp2[8]+2)>>2; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + + +static inline void rec4a(unsigned char *s,unsigned char *d, int lx, int lx2, int h) +{ + unsigned char *dp=d, *sp=s, *sp2=s+lx; + unsigned int s1, s2, s3, s4; + int j; + +/* + sp = s; + sp2 = s+lx; + dp = d; +*/ + for (j=0; j<h; j++){ + s1=sp[0]; s3=sp2[0]; + dp[0] = (dp[0] + ((unsigned int)(s1+(s2=sp[1])+s3+(s4=sp2[1])+2)>>2) + 1)>>1; + dp[1] = (dp[1] + ((unsigned int)(s2+(s1=sp[2])+s4+(s3=sp2[2])+2)>>2) + 1)>>1; + dp[2] = (dp[2] + ((unsigned int)(s1+(s2=sp[3])+s3+(s4=sp2[3])+2)>>2) + 1)>>1; + dp[3] = (dp[3] + ((unsigned int)(s2+(s1=sp[4])+s4+(s3=sp2[4])+2)>>2) + 1)>>1; + dp[4] = (dp[4] + ((unsigned int)(s1+(s2=sp[5])+s3+(s4=sp2[5])+2)>>2) + 1)>>1; + dp[5] = (dp[5] + ((unsigned int)(s2+(s1=sp[6])+s4+(s3=sp2[6])+2)>>2) + 1)>>1; + dp[6] = (dp[6] + ((unsigned int)(s1+(s2=sp[7])+s3+(s4=sp2[7])+2)>>2) + 1)>>1; + dp[7] = (dp[7] + ((unsigned int)(s2+(s1=sp[8])+s4+(s3=sp2[8])+2)>>2) + 1)>>1; + dp[8] = (dp[8] + ((unsigned int)(s1+(s2=sp[9])+s3+(s4=sp2[9])+2)>>2) + 1)>>1; + dp[9] = (dp[9] + ((unsigned int)(s2+(s1=sp[10])+s4+(s3=sp2[10])+2)>>2) + 1)>>1; + dp[10] = (dp[10] + ((unsigned int)(s1+(s2=sp[11])+s3+(s4=sp2[11])+2)>>2) + 1)>>1; + dp[11] = (dp[11] + ((unsigned int)(s2+(s1=sp[12])+s4+(s3=sp2[12])+2)>>2) + 1)>>1; + dp[12] = (dp[12] + ((unsigned int)(s1+(s2=sp[13])+s3+(s4=sp2[13])+2)>>2) + 1)>>1; + dp[13] = (dp[13] + ((unsigned int)(s2+(s1=sp[14])+s4+(s3=sp2[14])+2)>>2) + 1)>>1; + dp[14] = (dp[14] + ((unsigned int)(s1+(s2=sp[15])+s3+(s4=sp2[15])+2)>>2) + 1)>>1; + dp[15] = (dp[15] + ((unsigned int)(s2+sp[16]+s4+sp2[16]+2)>>2) + 1)>>1; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + + +static inline void rec4ac(unsigned char *s,unsigned char *d, int lx, int lx2, int h) +{ + unsigned char *dp=d, *sp=s, *sp2=s+lx; + unsigned int s1,s2,s3,s4; + int j; + +/* + sp = s; + sp2 = s+lx; + dp = d; +*/ + for (j=0; j<h; j++) + { + s1=sp[0]; s3=sp2[0]; + dp[0] = (dp[0] + ((unsigned int)(s1+(s2=sp[1])+s3+(s4=sp2[1])+2)>>2) + 1)>>1; + dp[1] = (dp[1] + ((unsigned int)(s2+(s1=sp[2])+s4+(s3=sp2[2])+2)>>2) + 1)>>1; + dp[2] = (dp[2] + ((unsigned int)(s1+(s2=sp[3])+s3+(s4=sp2[3])+2)>>2) + 1)>>1; + dp[3] = (dp[3] + ((unsigned int)(s2+(s1=sp[4])+s4+(s3=sp2[4])+2)>>2) + 1)>>1; + dp[4] = (dp[4] + ((unsigned int)(s1+(s2=sp[5])+s3+(s4=sp2[5])+2)>>2) + 1)>>1; + dp[5] = (dp[5] + ((unsigned int)(s2+(s1=sp[6])+s4+(s3=sp2[6])+2)>>2) + 1)>>1; + dp[6] = (dp[6] + ((unsigned int)(s1+(s2=sp[7])+s3+(s4=sp2[7])+2)>>2) + 1)>>1; + dp[7] = (dp[7] + ((unsigned int)(s2+sp[8]+s4+sp2[8]+2)>>2) + 1)>>1; + sp+= lx2; + sp2+= lx2; + dp+= lx2; + } +} + +static inline +void recon_comp(mpeg3video_t *video, + unsigned char *src, + unsigned char *dst, + int lx, + int lx2, + int w, + int h, + int x, + int y, + int dx, + int dy, + int addflag) +{ + int switcher; + unsigned char *s, *d; + +/* half pel scaling */ + switcher = (dx & 1) << 3 | (dy & 1) << 2 | w; + if(addflag) switcher |= 2; +/* origins */ + s = src + lx * (y + (dy >> 1)) + x + (dx >> 1); + d = dst + lx * y + x; + +// Accelerated functions +#ifdef HAVE_3Dnow + if(video->have_mmx) + { + switch(switcher) + { + case 0x3: reca_mmx(s, d, lx2, h); break; + case 0x2: recac_mmx(s, d, lx2, h); break; + case 0x1: rec_mmx(s, d, lx2, h); break; + case 0x0: recc_mmx(s, d, lx2, h); break; + case 0x7: recva_mmx(s, d, lx, lx2, h); break; + case 0x6: recvac_mmx(s, d, lx, lx2, h); break; + case 0x5: recv_mmx(s, d, lx, lx2, h); break; + case 0x4: recvc_mmx(s, d, lx, lx2, h); break; + case 0x9: rech_mmx(s, d, lx2, h); break; + case 0x8: rechc_mmx(s, d, lx2, h); break; + } + } + else +#endif + { + switch(switcher) + { + case 0x3: reca(s, d, lx2, h); break; + case 0x2: recac(s, d, lx2, h); break; + case 0x1: rec(s, d, lx2, h); break; + case 0x0: recc(s, d, lx2, h); break; + case 0x7: recva(s, d, lx, lx2, h); break; + case 0x6: recvac(s, d, lx, lx2, h); break; + case 0x5: recv_(s, d, lx, lx2, h); break; + case 0x4: recvc(s, d, lx, lx2, h); break; + case 0x9: rech(s, d, lx2, h); break; + case 0x8: rechc(s, d, lx2, h); break; + } + } + +// Unaccelerated functions + switch(switcher) + { + case 0xb: recha(s, d, lx2, h); break; + case 0xa: rechac(s, d, lx2, h); break; + case 0xf: rec4a(s, d, lx, lx2, h); break; + case 0xe: rec4ac(s, d, lx, lx2, h); break; + case 0xd: rec4(s, d, lx, lx2, h); break; + case 0xc: rec4c(s, d, lx, lx2, h); break; + } +} + +/* + unsigned char *src[]; * prediction source buffer * + int sfield; * prediction source field number (0 or 1) * + unsigned char *dst[]; * prediction destination buffer * + int dfield; * prediction destination field number (0 or 1)* + int lx,lx2; * horizontal offsets * + int w,h; * prediction block/sub-block width, height * + int x,y; * pixel co-ordinates of top-left sample in current MB * + int dx,dy; * horizontal, vertical motion vector * + int addflag; * add prediction error to prediction ? * +*/ +static void recon(mpeg3video_t *video, + unsigned char *src[], + int sfield, + unsigned char *dst[], + int dfield, + int lx, + int lx2, + int w, + int h, + int x, + int y, + int dx, + int dy, + int addflag) +{ + +/* Y */ + recon_comp(video, (src[0] + (sfield ? (lx2 >> 1) : 0)), + dst[0] + (dfield ? (lx2 >> 1) : 0), + lx, lx2, w, h, x, y, dx, dy, addflag); + + if(video->chroma_format != CHROMA444) + { + lx >>= 1; + dx /= 2; + lx2 >>= 1; + w = 0; + x >>= 1; + } + + if(video->chroma_format == CHROMA420) + { + h >>= 1; + dy /= 2; + y >>= 1; + } + +/* Cb */ + recon_comp(video, (src[1] + (sfield ? (lx2 >> 1) : 0)), + dst[1] + (dfield ? (lx2 >> 1) : 0), + lx, lx2, w, h, x, y, dx, dy, addflag); + +/* Cr */ + recon_comp(video, (src[2] + (sfield ? (lx2 >> 1) : 0)), + dst[2] + (dfield ? (lx2 >> 1) : 0), + lx, lx2, w, h, x, y, dx, dy, addflag); +} + +#define WIDTH 1 + +int mpeg3video_reconstruct(mpeg3video_t *video, + int bx, + int by, + int mb_type, + int motion_type, + int PMV[2][2][2], + int mv_field_sel[2][2], + int dmvector[2], + int stwtype) +{ + int currentfield; + unsigned char **predframe; + int DMV[2][2]; + int stwtop, stwbot; + + stwtop = stwtype % 3; /* 0:temporal, 1 : (spat+temp) / 2, 2 : spatial */ + stwbot = stwtype / 3; + + if((mb_type & MB_FORWARD) || (video->pict_type == P_TYPE)) + { + if(video->pict_struct == FRAME_PICTURE) + { + if((motion_type == MC_FRAME) || !(mb_type & MB_FORWARD)) + { +/* frame-based prediction */ + { + if(stwtop < 2) + recon(video, video->oldrefframe, 0, video->newframe, 0, + video->coded_picture_width, video->coded_picture_width << 1, WIDTH, 8, bx, by, + PMV[0][0][0], PMV[0][0][1], stwtop); + + if(stwbot < 2) + recon(video, video->oldrefframe, 1, video->newframe, 1, + video->coded_picture_width, video->coded_picture_width << 1, WIDTH, 8, bx, by, + PMV[0][0][0], PMV[0][0][1], stwbot); + } + } + else if(motion_type == MC_FIELD) /* field-based prediction */ + { +/* top field prediction */ + if(stwtop < 2) + recon(video, video->oldrefframe, mv_field_sel[0][0], video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by >> 1, + PMV[0][0][0], PMV[0][0][1] >> 1, stwtop); + +/* bottom field prediction */ + if(stwbot < 2) + recon(video, video->oldrefframe, mv_field_sel[1][0], video->newframe, 1, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by >> 1, + PMV[1][0][0], PMV[1][0][1] >> 1, stwbot); + } + else if(motion_type == MC_DMV) + { +/* dual prime prediction */ +/* calculate derived motion vectors */ + mpeg3video_calc_dmv(video, + DMV, + dmvector, + PMV[0][0][0], + PMV[0][0][1] >> 1); + + if(stwtop < 2) + { +/* predict top field from top field */ + recon(video, video->oldrefframe, 0, video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by>>1, + PMV[0][0][0], PMV[0][0][1] >> 1, 0); + +/* predict and add to top field from bottom field */ + recon(video, video->oldrefframe, 1, video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by>>1, + DMV[0][0], DMV[0][1], 1); + } + + if(stwbot < 2) + { +/* predict bottom field from bottom field */ + recon(video, video->oldrefframe, 1, video->newframe, 1, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by>>1, + PMV[0][0][0], PMV[0][0][1]>>1, 0); + +/* predict and add to bottom field from top field */ + recon(video, video->oldrefframe, 0, video->newframe, 1, + video->coded_picture_width << 1, video->coded_picture_width<<1, WIDTH, 8, bx, by>>1, + DMV[1][0], DMV[1][1], 1); + } + } + else +/* invalid motion_type */ +/* fprintf(stderr, "reconstruct: invalid motion_type\n"); */ + ; + } + else + { +/* TOP_FIELD or BOTTOM_FIELD */ +/* field picture */ + currentfield = (video->pict_struct == BOTTOM_FIELD); + +/* determine which frame to use for prediction */ + if((video->pict_type == P_TYPE) && video->secondfield + && (currentfield != mv_field_sel[0][0])) + predframe = video->refframe; /* same frame */ + else + predframe = video->oldrefframe; /* previous frame */ + + if((motion_type == MC_FIELD) || !(mb_type & MB_FORWARD)) + { +/* field-based prediction */ + if(stwtop < 2) + recon(video, predframe,mv_field_sel[0][0],video->newframe,0, + video->coded_picture_width << 1,video->coded_picture_width << 1,WIDTH,16,bx,by, + PMV[0][0][0],PMV[0][0][1],stwtop); + } + else + if(motion_type == MC_16X8) + { + if(stwtop < 2) + { + recon(video, predframe, mv_field_sel[0][0], video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by, + PMV[0][0][0], PMV[0][0][1], stwtop); + + /* determine which frame to use for lower half prediction */ + if((video->pict_type==P_TYPE) && video->secondfield + && (currentfield!=mv_field_sel[1][0])) + predframe = video->refframe; /* same frame */ + else + predframe = video->oldrefframe; /* previous frame */ + + recon(video, predframe, mv_field_sel[1][0], video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by+8, + PMV[1][0][0], PMV[1][0][1], stwtop); + } + } + else + if(motion_type == MC_DMV) /* dual prime prediction */ + { + if(video->secondfield) + predframe = video->refframe; /* same frame */ + else + predframe = video->oldrefframe; /* previous frame */ + +/* calculate derived motion vectors */ + mpeg3video_calc_dmv(video, + DMV, + dmvector, + PMV[0][0][0], + PMV[0][0][1]); + +/* predict from field of same parity */ + recon(video, video->oldrefframe, currentfield, video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 16, bx, by, + PMV[0][0][0], PMV[0][0][1], 0); + +/* predict from field of opposite parity */ + recon(video, predframe, !currentfield, video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 16, bx, by, + DMV[0][0], DMV[0][1], 1); + } + else +/* invalid motion_type */ +/* fprintf(stderr, "reconstruct: invalid motion_type\n"); */ + ; + } + stwtop = stwbot = 1; + } + + if(mb_type & MB_BACKWARD) + { + if(video->pict_struct == FRAME_PICTURE) + { + if(motion_type == MC_FRAME) + { +/* frame-based prediction */ + if(stwtop < 2) + recon(video, video->refframe, 0, video->newframe, 0, + video->coded_picture_width, video->coded_picture_width << 1, WIDTH, 8, bx, by, + PMV[0][1][0], PMV[0][1][1], stwtop); + + if(stwbot < 2) + recon(video, video->refframe, 1, video->newframe, 1, + video->coded_picture_width, video->coded_picture_width << 1, WIDTH, 8, bx, by, + PMV[0][1][0], PMV[0][1][1], stwbot); + } + else + { +/* field-based prediction */ +/* top field prediction */ + if(stwtop < 2) + { + recon(video, video->refframe, mv_field_sel[0][1], video->newframe, 0, + (video->coded_picture_width << 1), (video->coded_picture_width<<1), WIDTH, 8, bx, (by >> 1), + PMV[0][1][0], (PMV[0][1][1] >> 1), stwtop); + } + +/* bottom field prediction */ + if(stwbot < 2) + { + recon(video, video->refframe, mv_field_sel[1][1], video->newframe, 1, (video->coded_picture_width << 1), + (video->coded_picture_width << 1), WIDTH, 8, bx, (by>>1), + PMV[1][1][0], (PMV[1][1][1]>>1), stwbot); + } + } + } + else + { +/* TOP_FIELD or BOTTOM_FIELD */ +/* field picture */ + if(motion_type == MC_FIELD) + { +/* field-based prediction */ + recon(video, video->refframe, mv_field_sel[0][1], video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 16, bx, by, + PMV[0][1][0], PMV[0][1][1], stwtop); + } + else if(motion_type==MC_16X8) + { + recon(video, video->refframe, mv_field_sel[0][1], video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by, + PMV[0][1][0], PMV[0][1][1], stwtop); + + recon(video, video->refframe, mv_field_sel[1][1], video->newframe, 0, + video->coded_picture_width << 1, video->coded_picture_width << 1, WIDTH, 8, bx, by+8, + PMV[1][1][0], PMV[1][1][1], stwtop); + } + else +/* invalid motion_type */ +/* fprintf(stderr, "reconstruct: invalid motion_type\n"); */ + ; + } + } /* mb_type & MB_BACKWARD */ + return 0; +} + + diff --git a/core/multimedia/opieplayer/libmpeg3/video/seek.c b/core/multimedia/opieplayer/libmpeg3/video/seek.c new file mode 100644 index 0000000..04faba4 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/seek.c @@ -0,0 +1,233 @@ +#include "../mpeg3private.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" +#include <stdlib.h> +#include <string.h> + +unsigned int mpeg3bits_next_startcode(mpeg3_bits_t* stream) +{ +/* Perform forwards search */ + mpeg3bits_byte_align(stream); + +/* Perform search */ + while((mpeg3bits_showbits32_noptr(stream) >> 8) != MPEG3_PACKET_START_CODE_PREFIX && + !mpeg3bits_eof(stream)) + { + mpeg3bits_getbyte_noptr(stream); + } + return mpeg3bits_showbits32_noptr(stream); +} + +/* Line up on the beginning of the next code. */ +int mpeg3video_next_code(mpeg3_bits_t* stream, unsigned int code) +{ + while(!mpeg3bits_eof(stream) && + mpeg3bits_showbits32_noptr(stream) != code) + { + mpeg3bits_getbyte_noptr(stream); + } + return mpeg3bits_eof(stream); +} + +/* Line up on the beginning of the previous code. */ +int mpeg3video_prev_code(mpeg3_bits_t* stream, unsigned int code) +{ + while(!mpeg3bits_bof(stream) && + mpeg3bits_showbits_reverse(stream, 32) != code) + { + mpeg3bits_getbits_reverse(stream, 8); + } + return mpeg3bits_bof(stream); +} + +long mpeg3video_goptimecode_to_frame(mpeg3video_t *video) +{ +/* printf("mpeg3video_goptimecode_to_frame %d %d %d %d %f\n", */ +/* video->gop_timecode.hour, video->gop_timecode.minute, video->gop_timecode.second, video->gop_timecode.frame, video->frame_rate); */ + return (long)(video->gop_timecode.hour * 3600 * video->frame_rate + + video->gop_timecode.minute * 60 * video->frame_rate + + video->gop_timecode.second * video->frame_rate + + video->gop_timecode.frame) - 1 - video->first_frame; +} + +int mpeg3video_match_refframes(mpeg3video_t *video) +{ + unsigned char *dst, *src; + int i, j, size; + + for(i = 0; i < 3; i++) + { + if(video->newframe[i]) + { + if(video->newframe[i] == video->refframe[i]) + { + src = video->refframe[i]; + dst = video->oldrefframe[i]; + } + else + { + src = video->oldrefframe[i]; + dst = video->refframe[i]; + } + + if(i == 0) + size = video->coded_picture_width * video->coded_picture_height + 32 * video->coded_picture_width; + else + size = video->chrom_width * video->chrom_height + 32 * video->chrom_width; + + memcpy(dst, src, size); + } + } + return 0; +} + +int mpeg3video_seek(mpeg3video_t *video) +{ + long this_gop_start; + int result = 0; + int back_step; + int attempts; + mpeg3_t *file = video->file; + mpeg3_bits_t *vstream = video->vstream; + double percentage; + long frame_number; + int match_refframes = 1; + +/* Seek to a percentage */ + if(video->percentage_seek >= 0) + { + percentage = video->percentage_seek; + video->percentage_seek = -1; + mpeg3bits_seek_percentage(vstream, percentage); +// Go to previous I-frame + mpeg3bits_start_reverse(vstream); + result = mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE); + if(!result) mpeg3bits_getbits_reverse(vstream, 32); + mpeg3bits_start_forward(vstream); + + if(mpeg3bits_tell_percentage(vstream) < 0) mpeg3bits_seek_percentage(vstream, 0); + +// Read up to the correct percentage + result = 0; + while(!result && mpeg3bits_tell_percentage(vstream) < percentage) + { + result = mpeg3video_read_frame_backend(video, 0); + if(match_refframes) + mpeg3video_match_refframes(video); + match_refframes = 0; + } + } + else +/* Seek to a frame */ + if(video->frame_seek >= 0) + { + frame_number = video->frame_seek; + video->frame_seek = -1; + if(frame_number < 0) frame_number = 0; + if(frame_number > video->maxframe) frame_number = video->maxframe; + +/* Seek to start of file */ + if(frame_number < 16) + { + video->repeat_count = video->current_repeat = 0; + mpeg3bits_seek_start(vstream); + video->framenum = 0; + result = mpeg3video_drop_frames(video, frame_number - video->framenum); + } + else + { +/* Seek to an I frame. */ + if((frame_number < video->framenum || frame_number - video->framenum > MPEG3_SEEK_THRESHOLD)) + { +/* Elementary stream */ + if(file->is_video_stream) + { + mpeg3_t *file = video->file; + mpeg3_vtrack_t *track = video->track; + long byte = (long)((float)(mpeg3demuxer_total_bytes(vstream->demuxer) / + track->total_frames) * + frame_number); + long minimum = 65535; + int done = 0; + +//printf("seek elementary %d\n", frame_number); +/* Get GOP just before frame */ + do + { + result = mpeg3bits_seek_byte(vstream, byte); + mpeg3bits_start_reverse(vstream); + if(!result) result = mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE); + mpeg3bits_start_forward(vstream); + mpeg3bits_getbits(vstream, 8); + if(!result) result = mpeg3video_getgophdr(video); + this_gop_start = mpeg3video_goptimecode_to_frame(video); + +//printf("wanted %ld guessed %ld byte %ld result %d\n", frame_number, this_gop_start, byte, result); + if(labs(this_gop_start - frame_number) >= labs(minimum)) + done = 1; + else + { + minimum = this_gop_start - frame_number; + byte += (long)((float)(frame_number - this_gop_start) * + (float)(mpeg3demuxer_total_bytes(vstream->demuxer) / + track->total_frames)); + if(byte < 0) byte = 0; + } + }while(!result && !done); + +//printf("wanted %d guessed %d\n", frame_number, this_gop_start); + if(!result) + { + video->framenum = this_gop_start; + result = mpeg3video_drop_frames(video, frame_number - video->framenum); + } + } + else +/* System stream */ + { + mpeg3bits_seek_time(vstream, (double)frame_number / video->frame_rate); + percentage = mpeg3bits_tell_percentage(vstream); +//printf("seek frame %ld percentage %f byte %ld\n", frame_number, percentage, mpeg3bits_tell(vstream)); + mpeg3bits_start_reverse(vstream); + mpeg3video_prev_code(vstream, MPEG3_GOP_START_CODE); + mpeg3bits_getbits_reverse(vstream, 32); + mpeg3bits_start_forward(vstream); +//printf("seek system 1 %f\n", (double)frame_number / video->frame_rate); + + while(!result && mpeg3bits_tell_percentage(vstream) < percentage) + { + result = mpeg3video_read_frame_backend(video, 0); + if(match_refframes) + mpeg3video_match_refframes(video); + +//printf("seek system 2 %f %f\n", mpeg3bits_tell_percentage(vstream) / percentage); + match_refframes = 0; + } +//printf("seek system 3 %f\n", (double)frame_number / video->frame_rate); + } + + video->framenum = frame_number; + } + else +// Drop frames + { + mpeg3video_drop_frames(video, frame_number - video->framenum); + } + } + } + + return result; +} + +int mpeg3video_drop_frames(mpeg3video_t *video, long frames) +{ + int result = 0; + long frame_number = video->framenum + frames; + +/* Read the selected number of frames and skip b-frames */ + while(!result && frame_number > video->framenum) + { + result = mpeg3video_read_frame_backend(video, frame_number - video->framenum); + } + return result; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/slice.c b/core/multimedia/opieplayer/libmpeg3/video/slice.c new file mode 100644 index 0000000..90891b0 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/slice.c @@ -0,0 +1,702 @@ +#include "../libmpeg3.h" +#include "../mpeg3protos.h" +#include "mpeg3video.h" +#include "mpeg3videoprotos.h" +#include "slice.h" + +#include <stdlib.h> + +static ULONGLONG MMX_128 = 0x80008000800080LL; + +int mpeg3_new_slice_buffer(mpeg3_slice_buffer_t *slice_buffer) +{ + pthread_mutexattr_t mutex_attr; + slice_buffer->data = (unsigned char*)malloc(1024); + slice_buffer->buffer_size = 0; + slice_buffer->buffer_allocation = 1024; + slice_buffer->current_position = 0; + slice_buffer->bits_size = 0; + slice_buffer->bits = 0; + slice_buffer->done = 0; + pthread_mutexattr_init(&mutex_attr); + pthread_mutex_init(&(slice_buffer->completion_lock), &mutex_attr); + return 0; +} + +int mpeg3_delete_slice_buffer(mpeg3_slice_buffer_t *slice_buffer) +{ + free(slice_buffer->data); + pthread_mutex_destroy(&(slice_buffer->completion_lock)); + return 0; +} + +int mpeg3_expand_slice_buffer(mpeg3_slice_buffer_t *slice_buffer) +{ + int i; + unsigned char *new_buffer = + (unsigned char*)malloc(slice_buffer->buffer_allocation * 2); + for(i = 0; i < slice_buffer->buffer_size; i++) + new_buffer[i] = slice_buffer->data[i]; + free(slice_buffer->data); + slice_buffer->data = new_buffer; + slice_buffer->buffer_allocation *= 2; + return 0; +} + +/* limit coefficients to -2048..2047 */ + +/* move/add 8x8-Block from block[comp] to refframe */ + +static inline int mpeg3video_addblock(mpeg3_slice_t *slice, + mpeg3video_t *video, + int comp, + int bx, + int by, + int dct_type, + int addflag) +{ + int cc, i, iincr; + unsigned char *rfp; + short *bp; + int spar = slice->sparse[comp]; +/* color component index */ + cc = (comp < 4) ? 0 : (comp & 1) + 1; + + if(cc == 0) + { +/* luminance */ + if(video->pict_struct == FRAME_PICTURE) + { + if(dct_type) + { +/* field DCT coding */ + rfp = video->newframe[0] + + video->coded_picture_width * (by + ((comp & 2) >> 1)) + bx + ((comp & 1) << 3); + iincr = (video->coded_picture_width << 1); + } + else + { +/* frame DCT coding */ + rfp = video->newframe[0] + + video->coded_picture_width * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3); + iincr = video->coded_picture_width; + } + } + else + { +/* field picture */ + rfp = video->newframe[0] + + (video->coded_picture_width << 1) * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3); + iincr = (video->coded_picture_width << 1); + } + } + else + { +/* chrominance */ + +/* scale coordinates */ + if(video->chroma_format != CHROMA444) bx >>= 1; + if(video->chroma_format == CHROMA420) by >>= 1; + if(video->pict_struct == FRAME_PICTURE) + { + if(dct_type && (video->chroma_format != CHROMA420)) + { +/* field DCT coding */ + rfp = video->newframe[cc] + + video->chrom_width * (by + ((comp & 2) >> 1)) + bx + (comp & 8); + iincr = (video->chrom_width << 1); + } + else + { +/* frame DCT coding */ + rfp = video->newframe[cc] + + video->chrom_width * (by + ((comp & 2) << 2)) + bx + (comp & 8); + iincr = video->chrom_width; + } + } + else + { +/* field picture */ + rfp = video->newframe[cc] + + (video->chrom_width << 1) * (by + ((comp & 2) << 2)) + bx + (comp & 8); + iincr = (video->chrom_width << 1); + } + } + + bp = slice->block[comp]; + + if(addflag) + { +#ifdef HAVE_MMX + if(video->have_mmx) + { + if(spar) + { + __asm__ __volatile__( + "movq (%2), %%mm6\n" /* 4 blockvals */ + "pxor %%mm4, %%mm4\n" + "punpcklwd %%mm6, %%mm6\n" + "punpcklwd %%mm6, %%mm6\n" + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" /* 8 rindex1 */ + "movq %%mm0, %%mm2\n" + "punpcklbw %%mm4, %%mm0\n" + "punpckhbw %%mm4, %%mm2\n" + "paddw %%mm6, %%mm0\n" + "paddw %%mm6, %%mm2\n" + + "packuswb %%mm2, %%mm0\n" + "movq %%mm0, (%1)\n" + + "leal (%1, %3), %1\n" + "loop 1b\n" + : /* scr dest */ + : "c" (8),"r" (rfp), "r" (bp), "r" (iincr) + ); + } + else + { + __asm__ __volatile__( + "pxor %%mm4, %%mm4\n" + + ".align 8\n" + "1:" + "movq (%2), %%mm0\n" /* 8 rfp 0 1 2 3 4 5 6 7*/ + "movq (%1), %%mm6\n" /* 4 blockvals 0 1 2 3 */ + + "movq %%mm0, %%mm2\n" + "movq 8(%1), %%mm5\n" /* 4 blockvals 0 1 2 3 */ + "punpcklbw %%mm4, %%mm0\n" /* 0 2 4 6 */ + "punpckhbw %%mm4, %%mm2\n" /* 1 3 5 7 */ + + "paddw %%mm6, %%mm0\n" + "paddw %%mm5, %%mm2\n" + "packuswb %%mm2, %%mm0\n" + + "addl $16, %1\n" + "movq %%mm0, (%2)\n" + + "leal (%2,%3), %2\n" + "loop 1b\n" + : /* scr dest */ + : "c" (8),"r" (bp), "r" (rfp), "r" (iincr) + ); + } + } + else +#endif + for(i = 0; i < 8; i++) + { + rfp[0] = CLIP(bp[0] + rfp[0]); + rfp[1] = CLIP(bp[1] + rfp[1]); + rfp[2] = CLIP(bp[2] + rfp[2]); + rfp[3] = CLIP(bp[3] + rfp[3]); + rfp[4] = CLIP(bp[4] + rfp[4]); + rfp[5] = CLIP(bp[5] + rfp[5]); + rfp[6] = CLIP(bp[6] + rfp[6]); + rfp[7] = CLIP(bp[7] + rfp[7]); + rfp += iincr; + bp += 8; + } + } + else + { +#ifdef HAVE_MMX + if(video->have_mmx) + { + if(spar) + { + __asm__ __volatile__( + "movd (%2), %%mm0\n" /* " 0 0 0 v1" */ + "punpcklwd %%mm0, %%mm0\n" /* " 0 0 v1 v1" */ + "punpcklwd %%mm0, %%mm0\n" + "paddw MMX_128, %%mm0\n" + "packuswb %%mm0, %%mm0\n" + "leal (%0,%1,2), %%eax\n" + + "movq %%mm0, (%0, %1)\n" + "movq %%mm0, (%%eax)\n" + "leal (%%eax,%1,2), %0\n" + "movq %%mm0, (%%eax, %1)\n" + + "movq %%mm0, (%0)\n" + "leal (%0,%1,2), %%eax\n" + "movq %%mm0, (%0, %1)\n" + + "movq %%mm0, (%%eax)\n" + "movq %%mm0, (%%eax, %1)\n" + : + : "D" (rfp), "c" (iincr), "b" (bp) + : "eax"); + } + else + { + __asm__ __volatile__( + "movq MMX_128,%%mm4\n" + ".align 8\n" + "1:" + "movq (%1), %%mm0\n" + "movq 8(%1), %%mm1\n" + "paddw %%mm4, %%mm0\n" + + "movq 16(%1), %%mm2\n" + "paddw %%mm4, %%mm1\n" + + "movq 24(%1), %%mm3\n" + "paddw %%mm4, %%mm2\n" + + "packuswb %%mm1, %%mm0\n" + "paddw %%mm4, %%mm3\n" + + "addl $32, %1\n" + "packuswb %%mm3, %%mm2\n" + + "movq %%mm0, (%2)\n" + + "movq %%mm2, (%2,%3)\n" + + "leal (%2,%3,2), %2\n" + "loop 1b\n" + : + : "c" (4), "r" (bp), "r" (rfp), "r" (iincr) + ); + } + } + else +#endif + for(i = 0; i < 8; i++) + { + rfp[0] = CLIP(bp[0] + 128); + rfp[1] = CLIP(bp[1] + 128); + rfp[2] = CLIP(bp[2] + 128); + rfp[3] = CLIP(bp[3] + 128); + rfp[4] = CLIP(bp[4] + 128); + rfp[5] = CLIP(bp[5] + 128); + rfp[6] = CLIP(bp[6] + 128); + rfp[7] = CLIP(bp[7] + 128); + rfp+= iincr; + bp += 8; + } + } + return 0; +} + +int mpeg3_decode_slice(mpeg3_slice_t *slice) +{ + mpeg3video_t *video = slice->video; + int comp; + int mb_type, cbp, motion_type = 0, dct_type; + int macroblock_address, mba_inc, mba_max; + int slice_vert_pos_ext; + unsigned int code; + int bx, by; + int dc_dct_pred[3]; + int mv_count, mv_format, mvscale; + int pmv[2][2][2], mv_field_sel[2][2]; + int dmv, dmvector[2]; + int qs; + int stwtype, stwclass; + int snr_cbp; + int i; + mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer; + +/* number of macroblocks per picture */ + mba_max = video->mb_width * video->mb_height; + +/* field picture has half as many macroblocks as frame */ + if(video->pict_struct != FRAME_PICTURE) + mba_max >>= 1; + +/* macroblock address */ + macroblock_address = 0; +/* first macroblock in slice is not skipped */ + mba_inc = 0; + slice->fault = 0; + + code = mpeg3slice_getbits(slice_buffer, 32); +/* decode slice header (may change quant_scale) */ + slice_vert_pos_ext = mpeg3video_getslicehdr(slice, video); + +/* reset all DC coefficient and motion vector predictors */ + dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0; + pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; + pmv[0][1][0] = pmv[0][1][1] = pmv[1][1][0] = pmv[1][1][1] = 0; + + for(i = 0; + slice_buffer->current_position < slice_buffer->buffer_size; + i++) + { + if(mba_inc == 0) + { +/* Done */ + if(!mpeg3slice_showbits(slice_buffer, 23)) return 0; +/* decode macroblock address increment */ + mba_inc = mpeg3video_get_macroblock_address(slice); + + if(slice->fault) return 1; + + if(i == 0) + { +/* Get the macroblock_address */ + macroblock_address = ((slice_vert_pos_ext << 7) + (code & 255) - 1) * video->mb_width + mba_inc - 1; +/* first macroblock in slice: not skipped */ + mba_inc = 1; + } + } + + if(slice->fault) return 1; + + if(macroblock_address >= mba_max) + { +/* mba_inc points beyond picture dimensions */ + /*fprintf(stderr, "mpeg3_decode_slice: too many macroblocks in picture\n"); */ + return 1; + } + +/* not skipped */ + if(mba_inc == 1) + { + mpeg3video_macroblock_modes(slice, + video, + &mb_type, + &stwtype, + &stwclass, + &motion_type, + &mv_count, + &mv_format, + &dmv, + &mvscale, + &dct_type); + + if(slice->fault) return 1; + + if(mb_type & MB_QUANT) + { + qs = mpeg3slice_getbits(slice_buffer, 5); + + if(video->mpeg2) + slice->quant_scale = video->qscale_type ? mpeg3_non_linear_mquant_table[qs] : (qs << 1); + else + slice->quant_scale = qs; + + if(video->scalable_mode == SC_DP) +/* make sure quant_scale is valid */ + slice->quant_scale = slice->quant_scale; + } + +/* motion vectors */ + + +/* decode forward motion vectors */ + if((mb_type & MB_FORWARD) || ((mb_type & MB_INTRA) && video->conceal_mv)) + { + if(video->mpeg2) + mpeg3video_motion_vectors(slice, + video, + pmv, + dmvector, + mv_field_sel, + 0, + mv_count, + mv_format, + video->h_forw_r_size, + video->v_forw_r_size, + dmv, + mvscale); + else + mpeg3video_motion_vector(slice, + video, + pmv[0][0], + dmvector, + video->forw_r_size, + video->forw_r_size, + 0, + 0, + video->full_forw); + } + if(slice->fault) return 1; + +/* decode backward motion vectors */ + if(mb_type & MB_BACKWARD) + { + if(video->mpeg2) + mpeg3video_motion_vectors(slice, + video, + pmv, + dmvector, + mv_field_sel, + 1, + mv_count, + mv_format, + video->h_back_r_size, + video->v_back_r_size, + 0, + mvscale); + else + mpeg3video_motion_vector(slice, + video, + pmv[0][1], + dmvector, + video->back_r_size, + video->back_r_size, + 0, + 0, + video->full_back); + } + + if(slice->fault) return 1; + +/* remove marker_bit */ + if((mb_type & MB_INTRA) && video->conceal_mv) + mpeg3slice_flushbit(slice_buffer); + +/* macroblock_pattern */ + if(mb_type & MB_PATTERN) + { + cbp = mpeg3video_get_cbp(slice); + if(video->chroma_format == CHROMA422) + { +/* coded_block_pattern_1 */ + cbp = (cbp << 2) | mpeg3slice_getbits2(slice_buffer); + } + else + if(video->chroma_format == CHROMA444) + { +/* coded_block_pattern_2 */ + cbp = (cbp << 6) | mpeg3slice_getbits(slice_buffer, 6); + } + } + else + cbp = (mb_type & MB_INTRA) ? ((1 << video->blk_cnt) - 1) : 0; + + if(slice->fault) return 1; +/* decode blocks */ + mpeg3video_clearblock(slice, 0, video->blk_cnt); + for(comp = 0; comp < video->blk_cnt; comp++) + { + if(cbp & (1 << (video->blk_cnt - comp - 1))) + { + if(mb_type & MB_INTRA) + { + if(video->mpeg2) + mpeg3video_getmpg2intrablock(slice, video, comp, dc_dct_pred); + else + mpeg3video_getintrablock(slice, video, comp, dc_dct_pred); + } + else + { + if(video->mpeg2) + mpeg3video_getmpg2interblock(slice, video, comp); + else + mpeg3video_getinterblock(slice, video, comp); + } + if(slice->fault) return 1; + } + } + +/* reset intra_dc predictors */ + if(!(mb_type & MB_INTRA)) + dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0; + +/* reset motion vector predictors */ + if((mb_type & MB_INTRA) && !video->conceal_mv) + { +/* intra mb without concealment motion vectors */ + pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; + pmv[0][1][0] = pmv[0][1][1] = pmv[1][1][0] = pmv[1][1][1] = 0; + } + + if((video->pict_type == P_TYPE) && !(mb_type & (MB_FORWARD | MB_INTRA))) + { +/* non-intra mb without forward mv in a P picture */ + pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; + +/* derive motion_type */ + if(video->pict_struct == FRAME_PICTURE) + motion_type = MC_FRAME; + else + { + motion_type = MC_FIELD; +/* predict from field of same parity */ + mv_field_sel[0][0] = (video->pict_struct == BOTTOM_FIELD); + } + } + + if(stwclass == 4) + { +/* purely spatially predicted macroblock */ + pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; + pmv[0][1][0] = pmv[0][1][1] = pmv[1][1][0] = pmv[1][1][1] = 0; + } + } + else + { +/* mba_inc!=1: skipped macroblock */ + mpeg3video_clearblock(slice, 0, video->blk_cnt); + +/* reset intra_dc predictors */ + dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0; + +/* reset motion vector predictors */ + if(video->pict_type == P_TYPE) + pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; + +/* derive motion_type */ + if(video->pict_struct == FRAME_PICTURE) + motion_type = MC_FRAME; + else + { + motion_type = MC_FIELD; +/* predict from field of same parity */ + mv_field_sel[0][0] = mv_field_sel[0][1] = (video->pict_struct == BOTTOM_FIELD); + } + +/* skipped I are spatial-only predicted, */ +/* skipped P and B are temporal-only predicted */ + stwtype = (video->pict_type == I_TYPE) ? 8 : 0; + +/* clear MB_INTRA */ + mb_type &= ~MB_INTRA; + +/* no block data */ + cbp = 0; + } + + snr_cbp = 0; + +/* pixel coordinates of top left corner of current macroblock */ + bx = 16 * (macroblock_address % video->mb_width); + by = 16 * (macroblock_address / video->mb_width); + +/* motion compensation */ + if(!(mb_type & MB_INTRA)) + mpeg3video_reconstruct(video, + bx, + by, + mb_type, + motion_type, + pmv, + mv_field_sel, + dmvector, + stwtype); + +/* copy or add block data into picture */ + for(comp = 0; comp < video->blk_cnt; comp++) + { + if((cbp | snr_cbp) & (1 << (video->blk_cnt - 1 - comp))) + { +#ifdef HAVE_MMX + if(video->have_mmx) + IDCT_mmx(slice->block[comp]); + else +#endif + mpeg3video_idct_conversion(slice->block[comp]); + + mpeg3video_addblock(slice, + video, + comp, + bx, + by, + dct_type, + (mb_type & MB_INTRA) == 0); + } + } + +/* advance to next macroblock */ + macroblock_address++; + mba_inc--; + } + + return 0; +} + +void mpeg3_slice_loop(mpeg3_slice_t *slice) +{ + mpeg3video_t *video = slice->video; + int result = 1; + + while(!slice->done) + { + pthread_mutex_lock(&(slice->input_lock)); + + if(!slice->done) + { +/* Get a buffer to decode */ + result = 1; + pthread_mutex_lock(&(video->slice_lock)); + if(slice->buffer_step > 0) + { + while(slice->current_buffer <= slice->last_buffer) + { + if(!video->slice_buffers[slice->current_buffer].done && + slice->current_buffer <= slice->last_buffer) + { + result = 0; + break; + } + slice->current_buffer += slice->buffer_step; + } + } + else + { + while(slice->current_buffer >= slice->last_buffer) + { + if(!video->slice_buffers[slice->current_buffer].done && + slice->current_buffer >= slice->last_buffer) + { + result = 0; + break; + } + slice->current_buffer += slice->buffer_step; + } + } + +/* Got one */ + if(!result && slice->current_buffer >= 0 && slice->current_buffer < video->total_slice_buffers) + { + slice->slice_buffer = &(video->slice_buffers[slice->current_buffer]); + slice->slice_buffer->done = 1; + pthread_mutex_unlock(&(video->slice_lock)); + pthread_mutex_unlock(&(slice->input_lock)); + mpeg3_decode_slice(slice); + pthread_mutex_unlock(&(slice->slice_buffer->completion_lock)); + } + else + pthread_mutex_unlock(&(video->slice_lock)); + } + + pthread_mutex_unlock(&(slice->output_lock)); + } +} + +int mpeg3_new_slice_decoder(mpeg3video_t *video, mpeg3_slice_t *slice) +{ + pthread_attr_t attr; + //struct sched_param param; + pthread_mutexattr_t mutex_attr; + + slice->video = video; + slice->done = 0; + pthread_mutexattr_init(&mutex_attr); + pthread_mutex_init(&(slice->input_lock), &mutex_attr); + pthread_mutex_lock(&(slice->input_lock)); + pthread_mutex_init(&(slice->output_lock), &mutex_attr); + pthread_mutex_lock(&(slice->output_lock)); + + pthread_attr_init(&attr); + pthread_create(&(slice->tid), &attr, + (void * (*)(void *))mpeg3_slice_loop, slice); + + return 0; +} + +int mpeg3_delete_slice_decoder(mpeg3_slice_t *slice) +{ + slice->done = 1; + pthread_mutex_unlock(&(slice->input_lock)); + pthread_join(slice->tid, 0); + pthread_mutex_destroy(&(slice->input_lock)); + pthread_mutex_destroy(&(slice->output_lock)); + return 0; +} diff --git a/core/multimedia/opieplayer/libmpeg3/video/slice.h b/core/multimedia/opieplayer/libmpeg3/video/slice.h new file mode 100644 index 0000000..e36ffef --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/slice.h @@ -0,0 +1,194 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef SLICE_H +#define SLICE_H + +#ifndef _WIN32 +#include <pthread.h> +#endif + +/* Array of these feeds the slice decoders */ +typedef struct +{ + unsigned char *data; /* Buffer for holding the slice data */ + int buffer_size; /* Size of buffer */ + int buffer_allocation; /* Space allocated for buffer */ + int current_position; /* Position in buffer */ + unsigned MPEG3_INT32 bits; + int bits_size; + pthread_mutex_t completion_lock; /* Lock slice until completion */ + int done; /* Signal for slice decoder to skip */ +} mpeg3_slice_buffer_t; + +/* Each slice decoder */ +typedef struct +{ + struct mpeg3video_rec *video; + mpeg3_slice_buffer_t *slice_buffer; + + int thread_number; /* Number of this thread */ + int current_buffer; /* Buffer this slice decoder is on */ + int buffer_step; /* Number of buffers to skip */ + int last_buffer; /* Last buffer this decoder should process */ + int fault; + int done; + int quant_scale; + int pri_brk; /* slice/macroblock */ + short block[12][64]; + int sparse[12]; + pthread_t tid; /* ID of thread */ + pthread_mutex_t input_lock, output_lock; +} mpeg3_slice_t; + +#define mpeg3slice_fillbits(buffer, nbits) \ + while(((mpeg3_slice_buffer_t*)(buffer))->bits_size < (nbits)) \ + { \ + if(((mpeg3_slice_buffer_t*)(buffer))->current_position < ((mpeg3_slice_buffer_t*)(buffer))->buffer_size) \ + { \ + ((mpeg3_slice_buffer_t*)(buffer))->bits <<= 8; \ + ((mpeg3_slice_buffer_t*)(buffer))->bits |= ((mpeg3_slice_buffer_t*)(buffer))->data[((mpeg3_slice_buffer_t*)(buffer))->current_position++]; \ + } \ + ((mpeg3_slice_buffer_t*)(buffer))->bits_size += 8; \ + } + +#define mpeg3slice_flushbits(buffer, nbits) \ + { \ + mpeg3slice_fillbits((buffer), (nbits)); \ + ((mpeg3_slice_buffer_t*)(buffer))->bits_size -= (nbits); \ + } + +#define mpeg3slice_flushbit(buffer) \ +{ \ + if(((mpeg3_slice_buffer_t*)(buffer))->bits_size) \ + ((mpeg3_slice_buffer_t*)(buffer))->bits_size--; \ + else \ + if(((mpeg3_slice_buffer_t*)(buffer))->current_position < ((mpeg3_slice_buffer_t*)(buffer))->buffer_size) \ + { \ + ((mpeg3_slice_buffer_t*)(buffer))->bits = \ + ((mpeg3_slice_buffer_t*)(buffer))->data[((mpeg3_slice_buffer_t*)(buffer))->current_position++]; \ + ((mpeg3_slice_buffer_t*)(buffer))->bits_size = 7; \ + } \ +} + +extern inline unsigned int mpeg3slice_getbit(mpeg3_slice_buffer_t *buffer) +{ + if(buffer->bits_size) + return (buffer->bits >> (--buffer->bits_size)) & 0x1; + else + if(buffer->current_position < buffer->buffer_size) + { + buffer->bits = buffer->data[buffer->current_position++]; + buffer->bits_size = 7; + return (buffer->bits >> 7) & 0x1; + } + return 0; // WWA - stop warn +} + +extern inline unsigned int mpeg3slice_getbits2(mpeg3_slice_buffer_t *buffer) +{ + if(buffer->bits_size >= 2) + return (buffer->bits >> (buffer->bits_size -= 2)) & 0x3; + else + if(buffer->current_position < buffer->buffer_size) + { + buffer->bits <<= 8; + buffer->bits |= buffer->data[buffer->current_position++]; + buffer->bits_size += 6; + return (buffer->bits >> buffer->bits_size) & 0x3; + } + return 0; // WWA - stop warn +} + +extern inline unsigned int mpeg3slice_getbyte(mpeg3_slice_buffer_t *buffer) +{ + if(buffer->bits_size >= 8) + return (buffer->bits >> (buffer->bits_size -= 8)) & 0xff; + else + if(buffer->current_position < buffer->buffer_size) + { + buffer->bits <<= 8; + buffer->bits |= buffer->data[buffer->current_position++]; + return (buffer->bits >> buffer->bits_size) & 0xff; + } + return 0; // WWA - stop warn +} + + +extern inline unsigned int mpeg3slice_getbits(mpeg3_slice_buffer_t *slice_buffer, int bits) +{ + if(bits == 1) return mpeg3slice_getbit(slice_buffer); + mpeg3slice_fillbits(slice_buffer, bits); + return (slice_buffer->bits >> (slice_buffer->bits_size -= bits)) & (0xffffffff >> (32 - bits)); +} + +extern inline unsigned int mpeg3slice_showbits16(mpeg3_slice_buffer_t *buffer) +{ + if(buffer->bits_size >= 16) + return (buffer->bits >> (buffer->bits_size - 16)) & 0xffff; + else + if(buffer->current_position < buffer->buffer_size) + { + buffer->bits <<= 16; + buffer->bits_size += 16; + buffer->bits |= (unsigned int)buffer->data[buffer->current_position++] << 8; + buffer->bits |= buffer->data[buffer->current_position++]; + return (buffer->bits >> (buffer->bits_size - 16)) & 0xffff; + } + return 0; // WWA - stop warn +} + +extern inline unsigned int mpeg3slice_showbits9(mpeg3_slice_buffer_t *buffer) +{ + if(buffer->bits_size >= 9) + return (buffer->bits >> (buffer->bits_size - 9)) & 0x1ff; + else + if(buffer->current_position < buffer->buffer_size) + { + buffer->bits <<= 16; + buffer->bits_size += 16; + buffer->bits |= (unsigned int)buffer->data[buffer->current_position++] << 8; + buffer->bits |= buffer->data[buffer->current_position++]; + return (buffer->bits >> (buffer->bits_size - 9)) & 0x1ff; + } + return 0; // WWA - stop warn +} + +extern inline unsigned int mpeg3slice_showbits5(mpeg3_slice_buffer_t *buffer) +{ + if(buffer->bits_size >= 5) + return (buffer->bits >> (buffer->bits_size - 5)) & 0x1f; + else + if(buffer->current_position < buffer->buffer_size) + { + buffer->bits <<= 8; + buffer->bits_size += 8; + buffer->bits |= buffer->data[buffer->current_position++]; + return (buffer->bits >> (buffer->bits_size - 5)) & 0x1f; + } + return 0; // WWA - stop warn +} + +extern inline unsigned int mpeg3slice_showbits(mpeg3_slice_buffer_t *slice_buffer, int bits) +{ + mpeg3slice_fillbits(slice_buffer, bits); + return (slice_buffer->bits >> (slice_buffer->bits_size - bits)) & (0xffffffff >> (32 - bits)); +} + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/video/vlc.c b/core/multimedia/opieplayer/libmpeg3/video/vlc.c new file mode 100644 index 0000000..4328d8a --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/vlc.c @@ -0,0 +1,421 @@ +#include "mpeg3video.h" +#include "vlc.h" + +/* variable length code tables */ + +/* Table B-3, mb_type in P-pictures, codes 001..1xx */ +mpeg3_VLCtab_t mpeg3_PMBtab0[8] = { + {ERROR,0}, + {MB_FORWARD,3}, + {MB_PATTERN,2}, {MB_PATTERN,2}, + {MB_FORWARD|MB_PATTERN,1}, {MB_FORWARD|MB_PATTERN,1}, + {MB_FORWARD|MB_PATTERN,1}, {MB_FORWARD|MB_PATTERN,1} +}; + +/* Table B-3, mb_type in P-pictures, codes 000001..00011x */ +mpeg3_VLCtab_t mpeg3_PMBtab1[8] = { + {ERROR,0}, + {MB_QUANT|MB_INTRA,6}, + {MB_QUANT|MB_PATTERN,5}, {MB_QUANT|MB_PATTERN,5}, + {MB_QUANT|MB_FORWARD|MB_PATTERN,5}, {MB_QUANT|MB_FORWARD|MB_PATTERN,5}, + {MB_INTRA,5}, {MB_INTRA,5} +}; + +/* Table B-4, mb_type in B-pictures, codes 0010..11xx */ +mpeg3_VLCtab_t mpeg3_BMBtab0[16] = { + {ERROR,0}, {ERROR,0}, + {MB_FORWARD,4}, + {MB_FORWARD|MB_PATTERN,4}, + {MB_BACKWARD,3}, {MB_BACKWARD,3}, + {MB_BACKWARD|MB_PATTERN,3}, {MB_BACKWARD|MB_PATTERN,3}, + {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD,2}, + {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2} +}; + +/* Table B-4, mb_type in B-pictures, codes 000001..00011x */ +mpeg3_VLCtab_t mpeg3_BMBtab1[8] = { + {ERROR,0}, + {MB_QUANT|MB_INTRA,6}, + {MB_QUANT|MB_BACKWARD|MB_PATTERN,6}, + {MB_QUANT|MB_FORWARD|MB_PATTERN,6}, + {MB_QUANT|MB_FORWARD|MB_BACKWARD|MB_PATTERN,5}, + {MB_QUANT|MB_FORWARD|MB_BACKWARD|MB_PATTERN,5}, + {MB_INTRA,5}, {MB_INTRA,5} +}; + +/* Table B-5, mb_type in spat. scal. I-pictures, codes 0001..1xxx */ +mpeg3_VLCtab_t mpeg3_spIMBtab[16] = { + {ERROR,0}, + {MB_CLASS4,4}, + {MB_QUANT|MB_INTRA,4}, + {MB_INTRA,4}, + {MB_CLASS4|MB_QUANT|MB_PATTERN,2}, {MB_CLASS4|MB_QUANT|MB_PATTERN,2}, + {MB_CLASS4|MB_QUANT|MB_PATTERN,2}, {MB_CLASS4|MB_QUANT|MB_PATTERN,2}, + {MB_CLASS4|MB_PATTERN,1}, {MB_CLASS4|MB_PATTERN,1}, + {MB_CLASS4|MB_PATTERN,1}, {MB_CLASS4|MB_PATTERN,1}, + {MB_CLASS4|MB_PATTERN,1}, {MB_CLASS4|MB_PATTERN,1}, + {MB_CLASS4|MB_PATTERN,1}, {MB_CLASS4|MB_PATTERN,1} +}; + +/* Table B-6, mb_type in spat. scal. P-pictures, codes 0010..11xx */ +mpeg3_VLCtab_t mpeg3_spPMBtab0[16] = +{ + {ERROR,0},{ERROR,0}, + {MB_FORWARD,4}, + {MB_WEIGHT|MB_FORWARD,4}, + {MB_QUANT|MB_FORWARD|MB_PATTERN,3}, {MB_QUANT|MB_FORWARD|MB_PATTERN,3}, + {MB_WEIGHT|MB_FORWARD|MB_PATTERN,3}, {MB_WEIGHT|MB_FORWARD|MB_PATTERN,3}, + {MB_FORWARD|MB_PATTERN,2}, {MB_FORWARD|MB_PATTERN,2}, + {MB_FORWARD|MB_PATTERN,2}, {MB_FORWARD|MB_PATTERN,2}, + {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,2}, + {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,2}, + {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,2}, + {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,2} +}; + +/* Table B-6, mb_type in spat. scal. P-pictures, codes 0000010..000111x */ +mpeg3_VLCtab_t mpeg3_spPMBtab1[16] = { + {ERROR,0},{ERROR,0}, + {MB_CLASS4|MB_QUANT|MB_PATTERN,7}, + {MB_CLASS4,7}, + {MB_PATTERN,7}, + {MB_CLASS4|MB_PATTERN,7}, + {MB_QUANT|MB_INTRA,7}, + {MB_INTRA,7}, + {MB_QUANT|MB_PATTERN,6}, {MB_QUANT|MB_PATTERN,6}, + {MB_WEIGHT|MB_QUANT|MB_PATTERN,6}, {MB_WEIGHT|MB_QUANT|MB_PATTERN,6}, + {MB_WEIGHT,6}, {MB_WEIGHT,6}, + {MB_WEIGHT|MB_PATTERN,6}, {MB_WEIGHT|MB_PATTERN,6} +}; + +/* Table B-7, mb_type in spat. scal. B-pictures, codes 0010..11xx */ +mpeg3_VLCtab_t mpeg3_spBMBtab0[14] = { + {MB_FORWARD,4}, + {MB_FORWARD|MB_PATTERN,4}, + {MB_BACKWARD,3}, {MB_BACKWARD,3}, + {MB_BACKWARD|MB_PATTERN,3}, {MB_BACKWARD|MB_PATTERN,3}, + {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD,2}, + {MB_FORWARD|MB_BACKWARD,2}, {MB_FORWARD|MB_BACKWARD,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2}, + {MB_FORWARD|MB_BACKWARD|MB_PATTERN,2} +}; + +/* Table B-7, mb_type in spat. scal. B-pictures, codes 0000100..000111x */ +mpeg3_VLCtab_t mpeg3_spBMBtab1[12] = { + {MB_QUANT|MB_FORWARD|MB_PATTERN,7}, + {MB_QUANT|MB_BACKWARD|MB_PATTERN,7}, + {MB_INTRA,7}, + {MB_QUANT|MB_FORWARD|MB_BACKWARD|MB_PATTERN,7}, + {MB_WEIGHT|MB_FORWARD,6}, {MB_WEIGHT|MB_FORWARD,6}, + {MB_WEIGHT|MB_FORWARD|MB_PATTERN,6}, {MB_WEIGHT|MB_FORWARD|MB_PATTERN,6}, + {MB_WEIGHT|MB_BACKWARD,6}, {MB_WEIGHT|MB_BACKWARD,6}, + {MB_WEIGHT|MB_BACKWARD|MB_PATTERN,6}, {MB_WEIGHT|MB_BACKWARD|MB_PATTERN,6} +}; + +/* Table B-7, mb_type in spat. scal. B-pictures, codes 00000100x..000001111 */ +mpeg3_VLCtab_t mpeg3_spBMBtab2[8] = { + {MB_QUANT|MB_INTRA,8}, {MB_QUANT|MB_INTRA,8}, + {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,8}, + {MB_WEIGHT|MB_QUANT|MB_FORWARD|MB_PATTERN,8}, + {MB_WEIGHT|MB_QUANT|MB_BACKWARD|MB_PATTERN,9}, + {MB_CLASS4|MB_QUANT|MB_PATTERN,9}, + {MB_CLASS4,9}, + {MB_CLASS4|MB_PATTERN,9} +}; + +/* Table B-8, mb_type in spat. scal. B-pictures, codes 001..1xx */ +mpeg3_VLCtab_t mpeg3_SNRMBtab[8] = { + {ERROR,0}, + {0,3}, + {MB_QUANT|MB_PATTERN,2}, {MB_QUANT|MB_PATTERN,2}, + {MB_PATTERN,1}, {MB_PATTERN,1}, {MB_PATTERN,1}, {MB_PATTERN,1} +}; + +/* Table B-10, motion_code, codes 0001 ... 01xx */ +mpeg3_VLCtab_t mpeg3_MVtab0[8] = +{ {ERROR,0}, {3,3}, {2,2}, {2,2}, {1,1}, {1,1}, {1,1}, {1,1} +}; + +/* Table B-10, motion_code, codes 0000011 ... 000011x */ +mpeg3_VLCtab_t mpeg3_MVtab1[8] = +{ {ERROR,0}, {ERROR,0}, {ERROR,0}, {7,6}, {6,6}, {5,6}, {4,5}, {4,5} +}; + +/* Table B-10, motion_code, codes 0000001100 ... 000001011x */ +mpeg3_VLCtab_t mpeg3_MVtab2[12] = +{ {16,9}, {15,9}, {14,9}, {13,9}, + {12,9}, {11,9}, {10,8}, {10,8}, + {9,8}, {9,8}, {8,8}, {8,8} +}; + +/* Table B-9, coded_block_pattern, codes 01000 ... 111xx */ +mpeg3_VLCtab_t mpeg3_CBPtab0[32] = +{ {ERROR,0}, {ERROR,0}, {ERROR,0}, {ERROR,0}, + {ERROR,0}, {ERROR,0}, {ERROR,0}, {ERROR,0}, + {62,5}, {2,5}, {61,5}, {1,5}, {56,5}, {52,5}, {44,5}, {28,5}, + {40,5}, {20,5}, {48,5}, {12,5}, {32,4}, {32,4}, {16,4}, {16,4}, + {8,4}, {8,4}, {4,4}, {4,4}, {60,3}, {60,3}, {60,3}, {60,3} +}; + +/* Table B-9, coded_block_pattern, codes 00000100 ... 001111xx */ +mpeg3_VLCtab_t mpeg3_CBPtab1[64] = +{ {ERROR,0}, {ERROR,0}, {ERROR,0}, {ERROR,0}, + {58,8}, {54,8}, {46,8}, {30,8}, + {57,8}, {53,8}, {45,8}, {29,8}, {38,8}, {26,8}, {37,8}, {25,8}, + {43,8}, {23,8}, {51,8}, {15,8}, {42,8}, {22,8}, {50,8}, {14,8}, + {41,8}, {21,8}, {49,8}, {13,8}, {35,8}, {19,8}, {11,8}, {7,8}, + {34,7}, {34,7}, {18,7}, {18,7}, {10,7}, {10,7}, {6,7}, {6,7}, + {33,7}, {33,7}, {17,7}, {17,7}, {9,7}, {9,7}, {5,7}, {5,7}, + {63,6}, {63,6}, {63,6}, {63,6}, {3,6}, {3,6}, {3,6}, {3,6}, + {36,6}, {36,6}, {36,6}, {36,6}, {24,6}, {24,6}, {24,6}, {24,6} +}; + +/* Table B-9, coded_block_pattern, codes 000000001 ... 000000111 */ +mpeg3_VLCtab_t mpeg3_CBPtab2[8] = +{ {ERROR,0}, {0,9}, {39,9}, {27,9}, {59,9}, {55,9}, {47,9}, {31,9} +}; + +/* Table B-1, macroblock_address_increment, codes 00010 ... 011xx */ +mpeg3_VLCtab_t mpeg3_MBAtab1[16] = +{ {ERROR,0}, {ERROR,0}, {7,5}, {6,5}, {5,4}, {5,4}, {4,4}, {4,4}, + {3,3}, {3,3}, {3,3}, {3,3}, {2,3}, {2,3}, {2,3}, {2,3} +}; + +/* Table B-1, macroblock_address_increment, codes 00000011000 ... 0000111xxxx */ +mpeg3_VLCtab_t mpeg3_MBAtab2[104] = +{ + {33,11}, {32,11}, {31,11}, {30,11}, {29,11}, {28,11}, {27,11}, {26,11}, + {25,11}, {24,11}, {23,11}, {22,11}, {21,10}, {21,10}, {20,10}, {20,10}, + {19,10}, {19,10}, {18,10}, {18,10}, {17,10}, {17,10}, {16,10}, {16,10}, + {15,8}, {15,8}, {15,8}, {15,8}, {15,8}, {15,8}, {15,8}, {15,8}, + {14,8}, {14,8}, {14,8}, {14,8}, {14,8}, {14,8}, {14,8}, {14,8}, + {13,8}, {13,8}, {13,8}, {13,8}, {13,8}, {13,8}, {13,8}, {13,8}, + {12,8}, {12,8}, {12,8}, {12,8}, {12,8}, {12,8}, {12,8}, {12,8}, + {11,8}, {11,8}, {11,8}, {11,8}, {11,8}, {11,8}, {11,8}, {11,8}, + {10,8}, {10,8}, {10,8}, {10,8}, {10,8}, {10,8}, {10,8}, {10,8}, + {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, + {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, {9,7}, + {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, + {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7}, {8,7} +}; + +/* Table B-12, dct_dc_size_luminance, codes 00xxx ... 11110 */ +mpeg3_VLCtab_t mpeg3_DClumtab0[32] = +{ {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5}, {ERROR, 0} +}; + +/* Table B-12, dct_dc_size_luminance, codes 111110xxx ... 111111111 */ +mpeg3_VLCtab_t mpeg3_DClumtab1[16] = +{ {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, + {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10,9}, {11,9} +}; + +/* Table B-13, dct_dc_size_chrominance, codes 00xxx ... 11110 */ +mpeg3_VLCtab_t mpeg3_DCchromtab0[32] = +{ {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5}, {ERROR, 0} +}; + +/* Table B-13, dct_dc_size_chrominance, codes 111110xxxx ... 1111111111 */ +mpeg3_VLCtab_t mpeg3_DCchromtab1[32] = +{ {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, + {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, {6, 6}, + {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, + {8, 8}, {8, 8}, {8, 8}, {8, 8}, {9, 9}, {9, 9}, {10,10}, {11,10} +}; + +/* Table B-14, DCT coefficients table zero, + * codes 0100 ... 1xxx (used for first (DC) coefficient) + */ +mpeg3_DCTtab_t mpeg3_DCTtabfirst[12] = +{ + {0,2,4}, {2,1,4}, {1,1,3}, {1,1,3}, + {0,1,1}, {0,1,1}, {0,1,1}, {0,1,1}, + {0,1,1}, {0,1,1}, {0,1,1}, {0,1,1} +}; + +/* Table B-14, DCT coefficients table zero, + * codes 0100 ... 1xxx (used for all other coefficients) + */ +mpeg3_DCTtab_t mpeg3_DCTtabnext[12] = +{ + {0,2,4}, {2,1,4}, {1,1,3}, {1,1,3}, + {64,0,2}, {64,0,2}, {64,0,2}, {64,0,2}, /* EOB */ + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2} +}; + +/* Table B-14, DCT coefficients table zero, + * codes 000001xx ... 00111xxx + */ +mpeg3_DCTtab_t mpeg3_DCTtab0[60] = +{ + {65,0,6}, {65,0,6}, {65,0,6}, {65,0,6}, /* Escape */ + {2,2,7}, {2,2,7}, {9,1,7}, {9,1,7}, + {0,4,7}, {0,4,7}, {8,1,7}, {8,1,7}, + {7,1,6}, {7,1,6}, {7,1,6}, {7,1,6}, + {6,1,6}, {6,1,6}, {6,1,6}, {6,1,6}, + {1,2,6}, {1,2,6}, {1,2,6}, {1,2,6}, + {5,1,6}, {5,1,6}, {5,1,6}, {5,1,6}, + {13,1,8}, {0,6,8}, {12,1,8}, {11,1,8}, + {3,2,8}, {1,3,8}, {0,5,8}, {10,1,8}, + {0,3,5}, {0,3,5}, {0,3,5}, {0,3,5}, + {0,3,5}, {0,3,5}, {0,3,5}, {0,3,5}, + {4,1,5}, {4,1,5}, {4,1,5}, {4,1,5}, + {4,1,5}, {4,1,5}, {4,1,5}, {4,1,5}, + {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, + {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5} +}; + +/* Table B-15, DCT coefficients table one, + * codes 000001xx ... 11111111 +*/ +mpeg3_DCTtab_t mpeg3_DCTtab0a[252] = +{ + {65,0,6}, {65,0,6}, {65,0,6}, {65,0,6}, /* Escape */ + {7,1,7}, {7,1,7}, {8,1,7}, {8,1,7}, + {6,1,7}, {6,1,7}, {2,2,7}, {2,2,7}, + {0,7,6}, {0,7,6}, {0,7,6}, {0,7,6}, + {0,6,6}, {0,6,6}, {0,6,6}, {0,6,6}, + {4,1,6}, {4,1,6}, {4,1,6}, {4,1,6}, + {5,1,6}, {5,1,6}, {5,1,6}, {5,1,6}, + {1,5,8}, {11,1,8}, {0,11,8}, {0,10,8}, + {13,1,8}, {12,1,8}, {3,2,8}, {1,4,8}, + {2,1,5}, {2,1,5}, {2,1,5}, {2,1,5}, + {2,1,5}, {2,1,5}, {2,1,5}, {2,1,5}, + {1,2,5}, {1,2,5}, {1,2,5}, {1,2,5}, + {1,2,5}, {1,2,5}, {1,2,5}, {1,2,5}, + {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, + {3,1,5}, {3,1,5}, {3,1,5}, {3,1,5}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {1,1,3}, {1,1,3}, {1,1,3}, {1,1,3}, + {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, /* EOB */ + {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, + {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, + {64,0,4}, {64,0,4}, {64,0,4}, {64,0,4}, + {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, + {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, + {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, + {0,3,4}, {0,3,4}, {0,3,4}, {0,3,4}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,1,2}, {0,1,2}, {0,1,2}, {0,1,2}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,2,3}, {0,2,3}, {0,2,3}, {0,2,3}, + {0,4,5}, {0,4,5}, {0,4,5}, {0,4,5}, + {0,4,5}, {0,4,5}, {0,4,5}, {0,4,5}, + {0,5,5}, {0,5,5}, {0,5,5}, {0,5,5}, + {0,5,5}, {0,5,5}, {0,5,5}, {0,5,5}, + {9,1,7}, {9,1,7}, {1,3,7}, {1,3,7}, + {10,1,7}, {10,1,7}, {0,8,7}, {0,8,7}, + {0,9,7}, {0,9,7}, {0,12,8}, {0,13,8}, + {2,3,8}, {4,2,8}, {0,14,8}, {0,15,8} +}; + +/* Table B-14, DCT coefficients table zero, + * codes 0000001000 ... 0000001111 + */ +mpeg3_DCTtab_t mpeg3_DCTtab1[8] = +{ + {16,1,10}, {5,2,10}, {0,7,10}, {2,3,10}, + {1,4,10}, {15,1,10}, {14,1,10}, {4,2,10} +}; + +/* Table B-15, DCT coefficients table one, + * codes 000000100x ... 000000111x + */ +mpeg3_DCTtab_t mpeg3_DCTtab1a[8] = +{ + {5,2,9}, {5,2,9}, {14,1,9}, {14,1,9}, + {2,4,10}, {16,1,10}, {15,1,9}, {15,1,9} +}; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 000000010000 ... 000000011111 + */ +mpeg3_DCTtab_t mpeg3_DCTtab2[16] = +{ + {0,11,12}, {8,2,12}, {4,3,12}, {0,10,12}, + {2,4,12}, {7,2,12}, {21,1,12}, {20,1,12}, + {0,9,12}, {19,1,12}, {18,1,12}, {1,5,12}, + {3,3,12}, {0,8,12}, {6,2,12}, {17,1,12} +}; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 0000000010000 ... 0000000011111 + */ +mpeg3_DCTtab_t mpeg3_DCTtab3[16] = +{ + {10,2,13}, {9,2,13}, {5,3,13}, {3,4,13}, + {2,5,13}, {1,7,13}, {1,6,13}, {0,15,13}, + {0,14,13}, {0,13,13}, {0,12,13}, {26,1,13}, + {25,1,13}, {24,1,13}, {23,1,13}, {22,1,13} +}; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 00000000010000 ... 00000000011111 + */ +mpeg3_DCTtab_t mpeg3_DCTtab4[16] = +{ + {0,31,14}, {0,30,14}, {0,29,14}, {0,28,14}, + {0,27,14}, {0,26,14}, {0,25,14}, {0,24,14}, + {0,23,14}, {0,22,14}, {0,21,14}, {0,20,14}, + {0,19,14}, {0,18,14}, {0,17,14}, {0,16,14} +}; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 000000000010000 ... 000000000011111 + */ +mpeg3_DCTtab_t mpeg3_DCTtab5[16] = +{ + {0,40,15}, {0,39,15}, {0,38,15}, {0,37,15}, + {0,36,15}, {0,35,15}, {0,34,15}, {0,33,15}, + {0,32,15}, {1,14,15}, {1,13,15}, {1,12,15}, + {1,11,15}, {1,10,15}, {1,9,15}, {1,8,15} +}; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 0000000000010000 ... 0000000000011111 + */ +mpeg3_DCTtab_t mpeg3_DCTtab6[16] = +{ + {1,18,16}, {1,17,16}, {1,16,16}, {1,15,16}, + {6,3,16}, {16,2,16}, {15,2,16}, {14,2,16}, + {13,2,16}, {12,2,16}, {11,2,16}, {31,1,16}, + {30,1,16}, {29,1,16}, {28,1,16}, {27,1,16} +}; diff --git a/core/multimedia/opieplayer/libmpeg3/video/vlc.h b/core/multimedia/opieplayer/libmpeg3/video/vlc.h new file mode 100644 index 0000000..727040b --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/vlc.h @@ -0,0 +1,164 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef VLC_H +#define VLC_H + +/* variable length code tables */ + +typedef struct { + char val, len; +} mpeg3_VLCtab_t; + +typedef struct { + char run, level, len; +} mpeg3_DCTtab_t; + +/* Added 03/38/96 by Alex de Jong : avoid IRIX GNU warning */ +#ifdef ERROR +#undef ERROR +#define ERROR 99 +#endif + +/* Table B-3, mb_type in P-pictures, codes 001..1xx */ +extern mpeg3_VLCtab_t mpeg3_PMBtab0[8]; + +/* Table B-3, mb_type in P-pictures, codes 000001..00011x */ +extern mpeg3_VLCtab_t mpeg3_PMBtab1[8]; + +/* Table B-4, mb_type in B-pictures, codes 0010..11xx */ +extern mpeg3_VLCtab_t mpeg3_BMBtab0[16]; + +/* Table B-4, mb_type in B-pictures, codes 000001..00011x */ +extern mpeg3_VLCtab_t mpeg3_BMBtab1[8]; + +/* Table B-5, mb_type in spat. scal. I-pictures, codes 0001..1xxx */ +extern mpeg3_VLCtab_t mpeg3_spIMBtab[16]; + +/* Table B-6, mb_type in spat. scal. P-pictures, codes 0010..11xx */ +extern mpeg3_VLCtab_t mpeg3_spPMBtab0[16]; + +/* Table B-6, mb_type in spat. scal. P-pictures, codes 0000010..000111x */ +extern mpeg3_VLCtab_t mpeg3_spPMBtab1[16]; + +/* Table B-7, mb_type in spat. scal. B-pictures, codes 0010..11xx */ +extern mpeg3_VLCtab_t mpeg3_spBMBtab0[14]; + +/* Table B-7, mb_type in spat. scal. B-pictures, codes 0000100..000111x */ +extern mpeg3_VLCtab_t mpeg3_spBMBtab1[12]; + +/* Table B-7, mb_type in spat. scal. B-pictures, codes 00000100x..000001111 */ +extern mpeg3_VLCtab_t mpeg3_spBMBtab2[8]; + +/* Table B-8, mb_type in spat. scal. B-pictures, codes 001..1xx */ +extern mpeg3_VLCtab_t mpeg3_SNRMBtab[8]; + +/* Table B-10, motion_code, codes 0001 ... 01xx */ +extern mpeg3_VLCtab_t mpeg3_MVtab0[8]; + +/* Table B-10, motion_code, codes 0000011 ... 000011x */ +extern mpeg3_VLCtab_t mpeg3_MVtab1[8]; + +/* Table B-10, motion_code, codes 0000001100 ... 000001011x */ +extern mpeg3_VLCtab_t mpeg3_MVtab2[12]; + +/* Table B-9, coded_block_pattern, codes 01000 ... 111xx */ +extern mpeg3_VLCtab_t mpeg3_CBPtab0[32]; + +/* Table B-9, coded_block_pattern, codes 00000100 ... 001111xx */ +extern mpeg3_VLCtab_t mpeg3_CBPtab1[64]; + +/* Table B-9, coded_block_pattern, codes 000000001 ... 000000111 */ +extern mpeg3_VLCtab_t mpeg3_CBPtab2[8]; + +/* Table B-1, macroblock_address_increment, codes 00010 ... 011xx */ +extern mpeg3_VLCtab_t mpeg3_MBAtab1[16]; + +/* Table B-1, macroblock_address_increment, codes 00000011000 ... 0000111xxxx */ +extern mpeg3_VLCtab_t mpeg3_MBAtab2[104]; + +/* Table B-12, dct_dc_size_luminance, codes 00xxx ... 11110 */ +extern mpeg3_VLCtab_t mpeg3_DClumtab0[32]; + +/* Table B-12, dct_dc_size_luminance, codes 111110xxx ... 111111111 */ +extern mpeg3_VLCtab_t mpeg3_DClumtab1[16]; + +/* Table B-13, dct_dc_size_chrominance, codes 00xxx ... 11110 */ +extern mpeg3_VLCtab_t mpeg3_DCchromtab0[32]; + +/* Table B-13, dct_dc_size_chrominance, codes 111110xxxx ... 1111111111 */ +extern mpeg3_VLCtab_t mpeg3_DCchromtab1[32]; + +/* Table B-14, DCT coefficients table zero, + * codes 0100 ... 1xxx (used for first (DC) coefficient) + */ +extern mpeg3_DCTtab_t mpeg3_DCTtabfirst[12]; + +/* Table B-14, DCT coefficients table zero, + * codes 0100 ... 1xxx (used for all other coefficients) + */ +extern mpeg3_DCTtab_t mpeg3_DCTtabnext[12]; + +/* Table B-14, DCT coefficients table zero, + * codes 000001xx ... 00111xxx + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab0[60]; + +/* Table B-15, DCT coefficients table one, + * codes 000001xx ... 11111111 +*/ +extern mpeg3_DCTtab_t mpeg3_DCTtab0a[252]; + +/* Table B-14, DCT coefficients table zero, + * codes 0000001000 ... 0000001111 + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab1[8]; + +/* Table B-15, DCT coefficients table one, + * codes 000000100x ... 000000111x + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab1a[8]; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 000000010000 ... 000000011111 + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab2[16]; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 0000000010000 ... 0000000011111 + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab3[16]; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 00000000010000 ... 00000000011111 + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab4[16]; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 000000000010000 ... 000000000011111 + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab5[16]; + +/* Table B-14/15, DCT coefficients table zero / one, + * codes 0000000000010000 ... 0000000000011111 + */ +extern mpeg3_DCTtab_t mpeg3_DCTtab6[16]; + + +#endif diff --git a/core/multimedia/opieplayer/libmpeg3/video/worksheet.c b/core/multimedia/opieplayer/libmpeg3/video/worksheet.c new file mode 100644 index 0000000..c5a0553 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/video/worksheet.c @@ -0,0 +1,30 @@ +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + + +static LONGLONG mpeg3_MMX_601_Y_COEF = 0x0000004000400040; + +inline void mpeg3_601_mmx(unsigned long y, + unsigned long *output) +{ +asm(" +/* Output will be 0x00rrggbb */ + movd (%0), %%mm0; /* Load y 0x00000000000000yy */ +/* pmullw mpeg3_MMX_601_Y_COEF, %%mm0; // Scale y 0x00000000000000yy */ + psllw $6, %%mm0; /* Shift y coeffs 0x0000yyy0yyy0yyy0 */ + movd %%mm0, (%1); /* Store output */ + " +: +: "r" (&y), "r" (output)); +} + + +int main(int argc, char *argv[]) +{ + unsigned char output[1024]; + + memset(output, 0, 1024); + mpeg3_601_mmx(1, (unsigned long*)output); + printf("%02x%02x\n", *(unsigned char*)&output[1], *(unsigned char*)&output[0]); +} |