📄 decode.c
字号:
/* * decode.c * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org> * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> * * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. * See http://libmpeg2.sourceforge.net/ for updates. * * mpeg2dec is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * mpeg2dec 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "config.h"// $PP#include <stdio.h>#include <string.h> /* memcmp/memset, try to remove */#include <stdlib.h>#include <string.h>#ifdef MAE_HW#include "inttypes.h"#endif#include "mpeg2.h"#include "attributes.h"#include "mpeg2_internal.h"#ifdef MAE_HW#include "mae_pass_thru.h"#include "MAE_Global.h"#include "defines.h"#include "mai_types.h" /* for MAITimeStamp_t, m_s64 */#include "mae_interface.h"#ifdef USE_CMODELIF#include "cmodelif.h"#endif#include "sliceMAE.h"#include "driverif.h"#endif /* MAE_HW */#if !defined(UNDER_CE) && defined(MAE_RENDERER) #include "mae_renderer.h"#endif#ifdef TRACE_BUILD#include "mai_osal.h"/* enable these TIME printfs to assist in timestamp/PTS debugging */#define DPRINTF(_args_) /* MAIOSDebugPrint _args_ */#define DPRINTF2(_args_) /* MAIOSDebugPrint _args_ */#define APIPRINTF(_args_) MAIOSDebugPrint _args_ #define GETPRINTF(_args_) MAIOSDebugPrint _args_ #define PUTPRINTF(_args_) MAIOSDebugPrint _args_ #else#define DPRINTF(_args_)#define DPRINTF2(_args_)#define APIPRINTF(_args_)#define GETPRINTF(_args_)#define PUTPRINTF(_args_)#endif#if defined(MAE_HW)wrap_context *pWrapContext = NULL;#ifndef UNDER_CE /* Linux */extern uint32 g_flushMAE;#endif#endifextern unsigned char ucMarkFrameSet;extern unsigned char ucMarkFieldSet;#ifdef MAE_HWextern header_words local_header;#endif#if defined(MAE_HW) && !defined(USE_CMODELIF)extern int nDMVUpdate1, nDMVUpdate2;extern int prog_frame; // KK - rev2#endifstatic int mpeg2_accels = 0;#define BUFFER_SIZE (1194 * 1024)const mpeg2_info_t * mpeg2_info (mpeg2dec_t * mpeg2dec){ return &(mpeg2dec->info);}static inline int skip_chunk (mpeg2dec_t * mpeg2dec, int bytes){ uint8_t * current; uint32_t shift; uint8_t * limit; uint8_t byte; if (!bytes) return 0; current = mpeg2dec->buf_start; shift = mpeg2dec->shift; limit = current + bytes; do { byte = *current++; if (shift == 0x00000100) { int skipped; mpeg2dec->shift = 0xffffff00; skipped = current - mpeg2dec->buf_start; mpeg2dec->buf_start = current; return skipped; } shift = (shift | byte) << 8; } while (current < limit); mpeg2dec->shift = shift; mpeg2dec->buf_start = current; return 0;}static inline int copy_chunk (mpeg2dec_t * mpeg2dec, int bytes){ uint8_t * current; uint32_t shift; uint8_t * chunk_ptr; uint8_t * limit; uint8_t byte; if (!bytes) return 0; current = mpeg2dec->buf_start; shift = mpeg2dec->shift; chunk_ptr = mpeg2dec->chunk_ptr; limit = current + bytes; do { byte = *current++; if (shift == 0x00000100) { int copied; mpeg2dec->shift = 0xffffff00; mpeg2dec->chunk_ptr = chunk_ptr + 1; copied = current - mpeg2dec->buf_start; mpeg2dec->buf_start = current; return copied; } shift = (shift | byte) << 8; *chunk_ptr++ = byte; } while (current < limit); mpeg2dec->shift = shift; mpeg2dec->buf_start = current; return 0;}void mpeg2_buffer (mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end){ unsigned int bufsize=(int)(end-start); DPRINTF2((M_TEXT("mpeg2_buffer() size=%d Data=%02X %02X %02X %02X ...\n"), bufsize, start[0], start[1], start[2], start[3]));#if 0 /* enable for debug start codes in buffer */ { unsigned int i; for (i=0; i<(bufsize-3); i++) { if (start[i]==0x00 && start[i+1]==0x00 && start[i+2]==0x01) { DPRINTF((M_TEXT("mpeg2_buffer() code=0x%02X @ %d\n"), start[i+3], i)); } } }#endif mpeg2dec->buf_start = start; mpeg2dec->buf_end = end;}int mpeg2_getpos (mpeg2dec_t * mpeg2dec){ return mpeg2dec->buf_end - mpeg2dec->buf_start;}static inline mpeg2_state_t seek_chunk (mpeg2dec_t * mpeg2dec){ int size, skipped; size = mpeg2dec->buf_end - mpeg2dec->buf_start; skipped = skip_chunk (mpeg2dec, size); if (!skipped) { mpeg2dec->bytes_since_tag += size; return STATE_BUFFER; } mpeg2dec->bytes_since_tag += skipped; mpeg2dec->code = mpeg2dec->buf_start[-1]; return (mpeg2_state_t)-1;}mpeg2_state_t mpeg2_seek_header (mpeg2dec_t * mpeg2dec){ while (mpeg2dec->code != 0xb3 && ((mpeg2dec->code != 0xb7 && mpeg2dec->code != 0xb8 && mpeg2dec->code) || mpeg2dec->sequence.width == (unsigned)-1)) { if (seek_chunk (mpeg2dec) == STATE_BUFFER) { DPRINTF((M_TEXT("mpeg2_seek_header() no code found (last code=0x%02X) seq_width=%d\n"), mpeg2dec->code, mpeg2dec->sequence.width)); return STATE_BUFFER; } } mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer; mpeg2dec->user_data_len = 0; DPRINTF((M_TEXT("mpeg2_seek_header() code=0x%02X\n"), mpeg2dec->code)); return (mpeg2dec->code ? mpeg2_parse_header (mpeg2dec) : mpeg2_header_picture_start (mpeg2dec));}static void mpeg2_discontinuity (mpeg2dec_t * mpeg2dec){ /* HWG - discontinuity handling logic */ DPRINTF((M_TEXT("mpeg2_discontinuity() old: CurrentPTS=%d TempNum=%d GopCount=%d\n"), (int)mpeg2dec->decoder.tCurrentPTS, mpeg2dec->decoder.uiTemporalNum, mpeg2dec->decoder.uiGOPCount));#if defined(MAE_HW) if (pWrapContext) { PUTPRINTF((M_TEXT("mpeg2_discontinuity() Dummy submit\n"))); pWrapContext->dummysubmit = 1; WrapSubmitMBs(); pWrapContext = NULL; mpeg2dec->decoder.ulOkToSubmit = 0; mpeg2dec->decoder.ulSubmitCalled=1; }#ifndef UNDER_CE /* Linux */ /* Note: Under Linux the mae-driver is signaled to flush when next WrapGetContext() is called. It would be preferred to add the pWrapContext->nFlushMAE like under WinCE. */ PUTPRINTF((M_TEXT("mpeg2_discontinuity() bFlushing=1\n"))); mpeg2dec->decoder.bFlushing=1;#endif#endif DPRINTF((M_TEXT("mpeg2_discontinuity() reset parser\n"))); mpeg2dec->num_tags = 0; mpeg2dec->shift = 0xffffff00; if (mpeg2dec->sequence.width == (unsigned)-1) { DPRINTF((M_TEXT("mpeg2_discontinuity() no sequence header\n"))); /* sequence header unknown */ mpeg2dec->code = 0xb4; mpeg2dec->state = STATE_INVALID; } else { DPRINTF((M_TEXT("mpeg2_discontinuity() still have sequence header\n"))); mpeg2dec->code = 0xb8; // 0xb8 = seq header mpeg2dec->state = STATE_GOP; } mpeg2dec->action = mpeg2_seek_header; mpeg2dec->first = 1; mpeg2dec->first_decode_slice = 1; mpeg2dec->nb_decode_slices = 0xb0 - 1; mpeg2dec->decoder.uiWaitForIFrame = 1; mpeg2dec->decoder.uiOkToDecode = 0; mpeg2dec->decoder.tCurrentPTS = mpeg2dec->decoder.uiTemporalOffset = mpeg2dec->decoder.uiTemporalNum = 0; mpeg2dec->decoder.uiGOPCount = 0; mpeg2dec->decoder.uiMaxTemporal=0; mpeg2dec->decoder.tPTSLastSync = 0; mpeg2dec->decoder.bSyncedPTS = 0; mpeg2dec->decoder.iTemporalAtSyncPTS = 0; mpeg2dec->decoder.uiFramesSincePTSSync = 0; mpeg2dec->decoder.uiGOPsSincePTSSync = 0; mpeg2dec->decoder.uiIFramesProcessed = 0; mpeg2dec->decoder.uiPFramesProcessed = 0; mpeg2dec->decoder.uiBFramesProcessed = 0; if (mpeg2dec->decoder.uiFramesSinceNewPTS) { mpeg2dec->decoder.tNewPTS = 0; mpeg2dec->decoder.iTemporalAtNewPTS = 0; mpeg2dec->decoder.uiFramesSinceNewPTS = 0; DPRINTF((M_TEXT("mpeg2_discontinuity() reseting NewPTS, old: tNewPTS=%d iTemporalAtNewPTS=%d\n"), (int)mpeg2dec->decoder.tNewPTS, mpeg2dec->decoder.iTemporalAtNewPTS)); } }#define RECEIVED(code,state) (((state) << 8) + (code))mpeg2_state_t mpeg2_parse (mpeg2dec_t * mpeg2dec){ mpeg2_decoder_t * const decoder = &mpeg2dec->decoder; int size_buffer, size_chunk, copied; mpeg2_picture_t * picture = &(mpeg2dec->new_picture); // KK APIPRINTF((M_TEXT("mpeg2_parse() state=%d decmode=%d ctype=%d ulSubmitCalled=%d OKDecode=%d bDiscon=%d\n"), mpeg2dec->state, decoder->uiDecodeMode, decoder->coding_type, decoder->ulSubmitCalled, decoder->uiOkToDecode, decoder->bDiscon)); mpeg2dec->info.uiFrameSent = 0;#if defined(MAE_HW)#ifdef UNDER_CE if (decoder->bFlushing && decoder->ulSubmitCalled) { GETPRINTF((M_TEXT("mpeg2_parse() WrapGetContext(0)\n"))); pWrapContext = WrapGetContext (0); if (pWrapContext) { PUTPRINTF((M_TEXT("mpeg2_parse() nFlushMAE=1\n"))); pWrapContext->nFlushMAE = 1; decoder->bFlushing = 0; PUTPRINTF((M_TEXT("mpeg2_parse() WrapSubmitMBs() Flush\n"))); WrapSubmitMBs(); pWrapContext = NULL; } }#else /* Linux */ /* Linux - Driver (mae_interface) flushes via global variable g_flushMAE ** The mae-driver is signaled to flush when next GetContext() is called. ** It would be preferred to add the pWrapContext->nFlushMAE like under WinCE. */ if (decoder->bFlushing) { GETPRINTF((M_TEXT("mpeg2_parse() WrapGetContext(0)\n"))); PUTPRINTF((M_TEXT("mpeg2_parse() g_flushMAE=1\n"))); g_flushMAE=1; if (decoder->ulSubmitCalled || !pWrapContext) pWrapContext = WrapGetContext (0); if (pWrapContext) { decoder->bFlushing = 0; pWrapContext->dummysubmit = 1; PUTPRINTF((M_TEXT("mpeg2_parse() WrapSubmitMBs() Flush\n"))); WrapSubmitMBs(); pWrapContext = NULL; decoder->ulSubmitCalled=1; } }#endif#endif if (!decoder->bFlushing && decoder->bDiscon) { /* HWG - safe time to do Discontinuity handling */ DPRINTF((M_TEXT("mpeg2_parse() mpeg2_discontinuity\n"))); mpeg2_discontinuity(mpeg2dec); decoder->bDiscon=0; } if (mpeg2dec->action) { mpeg2_state_t state; state = mpeg2dec->action (mpeg2dec); DPRINTF2((M_TEXT("mpeg2_parse() state=%d\n"), state)); //$PP // If we decide to q macroblocks to the mae h/w on a field by field basis // then uncomment the following code block // this detects when the end of the slices for one field occur and q those MBs#if 0 if (mpeg2dec->state == STATE_PICTURE_2ND) { if ( mpeg2dec->decoder.bUseMAE && decoder->ulOkToSubmit ) { decoder->ulSubmitCalled = 1; WrapSubmitMBs(); decoder->ulOkToSubmit = 0; if ( decoder->bUseMAE && (decoder->bDumpFinal || decoder->bDumpFiles) ) WriteFrame (&mpeg2dec->decoder, DUMP, (mpeg2dec->decoder.picture_structure == FRAME_PICTURE ? 0 : 1)); } }#endif if ((int)state >= 0) return state; } #if defined(MAE_HW) && !defined(USE_MAI_RENDERER)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -