📄 mpgplay.cpp
字号:
// simple program to demonstrate mpeg playback// supports mpeg-1 system and mpeg-2 program streams#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/time.h>#include <sys/ipc.h>#include <sys/msg.h>#include <sys/wait.h>#include <malloc.h>#include "mpgparse/mpgparse.h"#include "mpegdec/mpegdec.h"#include "mpegdec/em85xx.h"#include "realmagichwl.h"#include "jasperlib.h"#include "mpegdec/myfont.c"#ifdef SUPPORT_IR#include "../ir/ir_ioctl.h"#endif#if 1static void debug_break (void){}#define ASSERT(exp) ((void)((exp)?1:(printf ("***ASSERT failed: line %d, file %s\n", __LINE__,__FILE__), debug_break(), 0)))#define DEBUGMSG(cond,printf_exp) ((void)((cond)?(printf printf_exp),1:0))#else#define ASSERT(exp)#define DEBUGMSG(cond,printf_exp)#endif// global data buffers#define NBUFFERS (32)#define BUFFERSIZE (64*1024) // MUST be a multiple of 32kstatic RMuint32 databuffers[NBUFFERS * BUFFERSIZE/4];static BufferPool BPmpg;static RMuint32 *mpg_buffer = (databuffers);static MpegDecoder *pMpegDecoder = 0;static RMint32 iframe_only = 0;static RMint64 lastPTS = 0;static RMint32 videoFormat_mpeg12 = 1;static RMint64 mpeg4TimeScale = 60;// change for your remote control#define PLAY_SCANCODE 0xe817e608#define FF_SCANCODE 0xaf50e608#define FR_SCANCODE 0xa758e608//////// keyboard input#include <sys/time.h>#include <termios.h>static struct termios tio_save;static unsigned long init_count = 0;static void open_input(void){ struct termios tio; if (init_count++) return; if (tcgetattr(STDIN_FILENO, &tio_save) < 0) { init_count--; return; } tio = tio_save; if (0) { tio.c_lflag &= ~(ECHO | ICANON | ISIG); tio.c_iflag &= ~(BRKINT); } else { tio.c_lflag |= (ISIG); tio.c_lflag &= ~(ECHO | ICANON); tio.c_iflag |= (BRKINT); tio.c_iflag &= ~(IGNBRK); } tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio);}static void close_input(void){ if (--init_count) return; tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio_save);}static int available_input_key(void){ struct timeval tv; fd_set readfds; tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&readfds); FD_SET(STDIN_FILENO, &readfds); return (select(STDIN_FILENO + 1, &readfds, NULL, NULL, &tv) > 0);}static int get_input_key(char *pKey){ if (! available_input_key() ) return 0; if (pKey == NULL) return 0; return (read(STDIN_FILENO, pKey, 1) == 1);}// define USE_FATFS_LIB when you want to use the sigma provided// fat file system instead of the linux one// note that the linux ide driver and fat file system must be// disabled in the kernel for the sigma fat file system to operate// correctly// #define USE_FATFS_LIB 1#ifdef USE_FATFS_LIB#include "fatfs.h"#include "ata_ioctl.h"//////////////////////////////////////////////////////////////////////// required fatfs callbacksstatic int ata_fd = -1;static RMuint32 fatfs_Ata_SendCmdRWS ( RMuint8 bDrive, RMuint8 bCmd, RMuint32 nSectorLBA, RMuint16 nNumSectors, RMuint8 *pbBuf, RMuint32 SizeInBytes){ RMint32 result; ATA_COMMAND AtaCommand; CMD_PACKET *pCmdPacket; RMuint8 CmdPacket[16]; if (ata_fd == -1) { printf ("***Error: Ata_ReadSectorsLBA: Invalid gAtaFd. Kernel Driver not open.\n"); return (RMuint32)-1; } pCmdPacket = (CMD_PACKET *)&(CmdPacket[0]); pCmdPacket->bCmd = bCmd; pCmdPacket->dwLBA = nSectorLBA; pCmdPacket->wXxLength = nNumSectors; // N sectors AtaCommand.pbCmdPkt = CmdPacket; AtaCommand.wPacketSize = 12; AtaCommand.bDrv = bDrive; // Primary Drive AtaCommand.pbBuffer = pbBuf; AtaCommand.dwRequestedXferCount = SizeInBytes; // SizeOf AtaCommand.pbBuffer AtaCommand.dwActualXferCount = 0; AtaCommand.wAtaStatus = 0; AtaCommand.wAtaError = 0; AtaCommand.wExStatusBytes = 0; result = ioctl (ata_fd, ATA_IOCTL_ISSUE_ATA_COMMAND, &AtaCommand); if (AtaCommand.wAtaError != 0) { // Some Error printf ("***Error: Ata_SendCmd(): ioctl(): AtaCommand.wAtaError = 0x%04X.\n", AtaCommand.wAtaError); } return ((RMuint32)AtaCommand.wAtaError);}static RMuint32 fatfs_Ata_SendCmd ( RMuint8 bDrive, RMuint8 bCmd, RMuint8 bFeature, RMuint8 bSectCounter, RMuint8 bSectNumber, RMuint8 bCylinderLo, RMuint8 bCylinderHi, RMuint8 bDevHead, RMuint8 *pbIoBuf, RMuint32 dwBufSizeInBytes){ RMint32 result; ATA_COMMAND AtaCommand; RMuint8 CmdPacket[16]; if (ata_fd == -1) { printf ("***Error: Ata_ReadSectorsLBA: Invalid gAtaFd. Kernel Driver not open.\n"); return (RMuint32)-1; } // Universal control - Send values for all registers + bDrv CmdPacket[0] = bCmd; CmdPacket[1] = bFeature; CmdPacket[2] = bSectCounter; CmdPacket[3] = bSectNumber; CmdPacket[4] = bCylinderLo; CmdPacket[5] = bCylinderHi; CmdPacket[6] = bDevHead; AtaCommand.pbCmdPkt = CmdPacket; AtaCommand.wPacketSize = 12; AtaCommand.bDrv = bDrive; // Primary Drive AtaCommand.pbBuffer = pbIoBuf; AtaCommand.dwRequestedXferCount = dwBufSizeInBytes; // SizeOf AtaCommand.pbBuffer AtaCommand.dwActualXferCount = 0; AtaCommand.wAtaStatus = 0; AtaCommand.wAtaError = 0; AtaCommand.wExStatusBytes = 0; result = ioctl (ata_fd, ATA_IOCTL_ISSUE_ATA_COMMAND, &AtaCommand); if (AtaCommand.wAtaError != 0) { // Some Error printf ("***Error: Ata_SendCmd(): ioctl(): AtaCommand.wAtaError = 0x%04X.\n", AtaCommand.wAtaError); } return( (RMuint32)AtaCommand.wAtaError );}static void *fatfs_malloc (RMuint32 s){ void *p; p = malloc (s); printf ("%08lx = fatfs_malloc (%d)\n", (RMuint32)p, (RMint32)s); return p;}static void fatfs_free (void *p){ printf ("fatfs_free (%08lx)\n", (RMuint32)p); return free (p);}#endifstatic int gettime_ms (void){ struct timeval tv1; struct timezone tz; gettimeofday (&tv1, &tz); return tv1.tv_sec * 1000 + tv1.tv_usec/1000;}/////////////////////////////////////////////////////////////////////////////// filesystem callbacksstatic RMuint32 mpg_fopen (RMint8 *filename, void *context){#ifdef USE_FATFS_LIB FATFS_ERROR fatfs_err; RMuint32 fd = (RMuint32)INVALID_HANDLE; fatfs_err = fatfs_fopen ((RMuint8 *)filename, _O_RDONLY, &fd); ASSERT (fatfs_err == FATFS_ERROR_NO_ERROR); if (fatfs_err != FATFS_ERROR_NO_ERROR) return 0; return fd;#else return (RMint32)fopen (filename, "rb");#endif}static RMuint32 mpg_fread (RMuint32 handle, void *buf, RMuint32 length, void *context){#ifdef USE_FATFS_LIB FATFS_ERROR fatfs_err; RMuint32 n; fatfs_err = fatfs_fread (handle, (RMuint8 *)buf, length, &n); if (fatfs_err != FATFS_ERROR_NO_ERROR) return 0; return n;#else return (RMint32)fread (buf, 1, length, (FILE *)handle);#endif}static RMuint32 mpg_fseek (RMuint32 handle, RMint32 pos, RMint32 whence, void *context){#ifdef USE_FATFS_LIB FATFS_ERROR fatfs_err; ASSERT (whence == SEEK_SET); fatfs_err = fatfs_fseek (handle, pos, SEEK_SET); if (fatfs_err != FATFS_ERROR_NO_ERROR) return 0; return pos;#else return fseek ((FILE *)handle, pos, whence);#endif}static RMuint32 mpg_fclose (RMuint32 handle, void *context){#ifdef USE_FATFS_LIB fatfs_fclose (handle);#else return fclose ((FILE *)handle);#endif}//////////////////////////////////////////////////////////////////////////////static RMuint32 mpg_addref (RMuint8 *pBuffer, void *context){ BufferPool *BP = &BPmpg; int idx = ((int)pBuffer - (int)BP->start_address) / BP->buffers_size; ASSERT (idx >= 0); addref_buffer (&(BP->B[idx])); return 0;}static RMuint32 mpg_release (RMuint8 *pBuffer, void *context){ BufferPool *BP = &BPmpg; int idx = ((int)pBuffer - (int)BP->start_address) / BP->buffers_size; ASSERT (idx >= 0); release_buffer (&(BP->B[idx])); return 0;}static RMuint32 mpg_getMPG (RMuint8 **pBuffer, RMuint32 *plength, void *context){ int idx = find_free_buffer (&BPmpg, 0); if (idx < 0) { return 1; } DEBUGMSG (0, ("idx = %d\n", idx)); *plength = (RMuint32)BPmpg.buffers_size; *pBuffer = (RMuint8 *)get_buffer_address (&BPmpg, idx); return 0;}static RMuint32 mpg_info (RMint32 msg, void *info, void *context){ return 0;}static RMuint8 videoStreamId = 0xff;static RMuint8 audioStreamId = 0xff;static RMuint8 audioSubStreamId = 0xff;static RMint32 audioFreq = 0;// you can select diffent stream ids here// in this sample implementation, the first audio/video stream// encountered are selectedRMuint32 mpg_putpayload (RMuint8 *pData, RMuint32 Length, RMuint8 StreamId, RMuint8 SubStreamId, RMint64 Scr, RMint64 Pts, RMint64 Dts, RMuint8 Flags, void *context){ if (Flags & PTS_VALID_FLAG) lastPTS = Pts; if (Length == 0) return 0; // if a video stream has not been selected yet if (videoStreamId == 0xff) { if ((StreamId & 0xf0) == 0xe0) { // mpeg1/2 video videoStreamId = StreamId; printf ("videoStreamId = %02x\n", videoStreamId); } } // if an audio stream has not been selected yet if (audioStreamId == 0xff) { if ((StreamId & 0xf0) == 0xc0) { // mpeg audio // check sampling rate RMuint8 *p = pData; for (RMuint32 i=0; i<Length-3; i++) { // check header if ((p[0] == 0xff) && ((p[1] & 0xf0) == 0xf0)) { // check layer if ((p[1] & 0x6) != 0) { // check bitrate index if ((p[2] & 0xf0) != 0xf0) { // check sample frequency if ((p[2] & 0xc) != 0xc) { RMint32 audioFreqTable[] = {44100, 48000, 32000, 44100}; // assume ok ... audioStreamId = StreamId; audioSubStreamId = SubStreamId; audioFreq = audioFreqTable[(p[2] & 0xc) >> 2]; printf ("StreamId = %02x, SubStreamId = %02x, mpeg @ %d\n", audioStreamId, audioSubStreamId, audioFreq); MPEGAUDIO_PARAMETERS mpeginfo; mpeginfo.layer = 2; mpeginfo.rawOutput = 0; mpeginfo.SamplesPerSecond = audioFreq; pMpegDecoder->SetMpegAudioParameters (&mpeginfo); break; } } } } p++; } } if (StreamId == 0xbd) { if ((SubStreamId & 0x88) == 0x80) { // ac3 audioStreamId = StreamId; audioSubStreamId = SubStreamId; // assume 48000 audioFreq = 48000; printf ("StreamId = %02x, SubStreamId = %02x, ac3\n", audioStreamId, audioSubStreamId); AC3_PARAMETERS ac3info; ac3info.rawOutput = 0; ac3info.SamplesPerSecond = audioFreq; pMpegDecoder->SetAC3Parameters (&ac3info); } if ((SubStreamId & 0x88) == 0x88) { // dts audioStreamId = StreamId; audioSubStreamId = SubStreamId; // assume 48000 audioFreq = 48000; printf ("StreamId = %02x, SubStreamId = %02x, ac3\n", audioStreamId, audioSubStreamId); DTS_PARAMETERS dtsinfo; dtsinfo.rawOutput = 1; dtsinfo.SamplesPerSecond = audioFreq; pMpegDecoder->SetDTSParameters (&dtsinfo); } } } if (videoStreamId == StreamId) { BufferPool *BP = &BPmpg; int idx = ((int)pData - (int)BP->start_address) / BP->buffers_size; ASSERT (idx >= 0); addref_buffer (&(BP->B[idx])); if (Flags & PTS_VALID_FLAG) { if (Flags & SCR_VALID_FLAG) { Scr = Scr * mpeg4TimeScale / 90000; if (Scr == 0) Scr = 1; } else if (videoFormat_mpeg12 == 0) { Scr = 0; } Flags = PTS_AVAILABLE_FLAG; if (videoFormat_mpeg12 == 0) { Pts = Pts * mpeg4TimeScale / 90000; Flags = CTS_AVAILABLE_FLAG; } DEBUGMSG (0, ("video: [%d] scr=%d, pts=%d\n", (int)Length, (int)Scr, (int)Pts)); } else { DEBUGMSG (0, ("video: [%d]\n", (int)Length)); Flags = 0; } ASSERT (Length); pMpegDecoder->WriteMpegVideo (pData, Length, &(BP->B[idx]), Flags, Scr, Pts); } if (iframe_only) return 0; if ((audioStreamId == StreamId) && (audioSubStreamId == SubStreamId)) { BufferPool *BP = &BPmpg; int idx = ((int)pData - (int)BP->start_address) / BP->buffers_size; ASSERT (idx >= 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -