author | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
---|---|---|
committer | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
commit | 15318cad33835e4e2dc620d033e43cd930676cdd (patch) (side-by-side diff) | |
tree | c2fa0399a2c47fda8e2cd0092c73a809d17f68eb /core/multimedia/opieplayer/libmpeg3/video/getpicture.c | |
download | opie-15318cad33835e4e2dc620d033e43cd930676cdd.zip opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2 |
Initial revision
Diffstat (limited to 'core/multimedia/opieplayer/libmpeg3/video/getpicture.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/libmpeg3/video/getpicture.c | 767 |
1 files changed, 767 insertions, 0 deletions
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; +} |