/* * * This file is part of libmpeg3 * * LibMPEG3 * Author: Adam Williams * Page: heroine.linuxbox.com * Page: http://www.smalltalkconsulting.com/html/mpeg3source.html (for Squeak) * LibMPEG3 was originally licenced under GPL. It was relicensed by the author under the LGPL and the Squeak license on Nov 1st, 2000 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also licensed under the Squeak license. http://www.squeak.org/license.html */ /* Changed Sept 15th by John M McIntosh to support Macintosh & Squeak */ #include "mpeg3private.h" #include "mpeg3video.h" #include "vlc.h" #include #include #include 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 { 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=0, 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; } 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; } #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=0, 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=0, 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; #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; } 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=0, 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; } 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; #ifdef USE_PTHREADS pthread_mutex_lock(&(slice_buffer->completion_lock)); #endif 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; } #ifdef USE_PTHREADS pthread_mutex_unlock(&(video->slice_decoders[i].input_lock)); #endif } } /* Wait for the slice decoders to finish */ if(video->total_slice_buffers > 0) { #ifdef USE_PTHREADS 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)); #else for(i = 0; i < video->total_slice_decoders; i++) { mpeg3_slice_loop(&video->slice_decoders[i]); #endif } } return 0; } int mpeg3video_allocate_decoders(mpeg3video_t *video, int decoder_count) { int i; mpeg3_t *file = (mpeg3_t *) 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 = (mpeg3_t *) 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; }