[MPlayer-dev-eng] Supporting em84xx as output device - Done !
Helmut Auer
vdr at helmutauer.de
Sun Oct 22 11:32:37 CEST 2006
Hi List,
It's done :)
With the attached Patch ( must be used after configure ) mplayer-1.0pre8 will be able to use the
em84xx decoder for playback. You need the sigma sdk to compile it ( fmp.h ) and the library
libEM84xx.so for linking.
--
Helmut Auer, helmut at helmutauer.de
diff -uN -x '*.o' -x '*.a' libao2/ao_em84xx.c libao2/ao_em84xx.c
--- libao2/ao_em84xx.c 1970-01-01 01:00:00.000000000 +0100
+++ libao2/ao_em84xx.c 2006-10-16 15:26:55.000000000 +0200
@@ -0,0 +1,166 @@
+/*
+ * Based on: ao_em84xx.c
+ *
+ * ao_em84.c - audio out to vdr-file
+ *
+ * Copyright (C) 2006 Helmut Auer & Uwe Scheffler
+ *
+ */
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#include <errno.h>
+
+#include "audio_out.h"
+#include "audio_out_internal.h"
+
+#include "libaf/af_format.h"
+
+#define _DEFINE_FMP_TYPES_
+#define _BARBADOS_
+#include <fmp.h>
+
+extern int vo_vdr_fd;
+
+int em84Volume[2]={50,50};
+
+static ao_info_t info =
+{
+ "Mpeg-PES audio output to em84 or vdr-file",
+ "em84xx",
+ "HelAu",
+ ""
+};
+
+LIBAO_EXTERN(em84xx)
+
+// to set/get/query special features/parameters
+static int control(int cmd,void *arg)
+{
+ if(vo_vdr_fd < 0) {
+ switch(cmd){
+ case AOCONTROL_GET_VOLUME:
+ ((ao_control_vol_t*)(arg))->left=em84Volume[0];
+ ((ao_control_vol_t*)(arg))->right=em84Volume[1];
+ mp_msg(MSGT_AO,MSGL_V, "EM84 Get_Volume(%d-%d)\n", em84Volume[0],em84Volume[1]);
+ return CONTROL_OK;
+ case AOCONTROL_SET_VOLUME:
+ em84Volume[0]=((ao_control_vol_t*)(arg))->left;
+ em84Volume[1]=((ao_control_vol_t*)(arg))->right;
+ mp_msg(MSGT_AO,MSGL_V, "EM84 Set_Volume(%d-%d)\n", em84Volume[0],em84Volume[1]);
+ FMPSet(FMPI_LEFT_VOLUME,em84Volume[0]);
+ FMPSet(FMPI_RIGHT_VOLUME,em84Volume[1]);
+ return CONTROL_OK;
+ }
+ }
+ return CONTROL_UNKNOWN;
+}
+
+static int freq=0;
+static int freq_id=0;
+
+// open & setup audio device
+// return: 1=success 0=fail
+static int init(int rate,int channels,int format,int flags)
+{
+ ao_data.channels=2;
+ ao_data.outburst=2000;
+ switch( format ) {
+ case AF_FORMAT_S16_LE:
+ case AF_FORMAT_S16_BE:
+ case AF_FORMAT_MPEG2:
+ case AF_FORMAT_AC3:
+ ao_data.format=format;
+ break;
+ default:
+ ao_data.format=AF_FORMAT_S16_BE;
+ }
+
+ switch( rate ) {
+ case 48000: freq_id=0;break;
+ case 96000: freq_id=1;break;
+ case 44100: freq_id=2;break;
+ case 32000: freq_id=3;break;
+ default:
+ mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_MPEGPES_UnsupSamplerate, rate);
+ rate=48000; freq_id=0;
+ }
+
+ ao_data.bps=rate*2*2;
+ freq=ao_data.samplerate=rate;
+
+ if(vo_vdr_fd < 0) {
+ FMPSet(FMPI_LEFT_VOLUME,em84Volume[0]);
+ FMPSet(FMPI_RIGHT_VOLUME,em84Volume[1]);
+ }
+
+ return 1;
+}
+
+// close audio device
+static void uninit(int immed)
+{
+}
+
+// stop playing and empty buffers (for seeking/pause)
+static void reset(void)
+{
+}
+
+// stop playing, keep buffers (for pause)
+static void audio_pause(void)
+{
+ // for now, just call reset();
+ reset();
+}
+
+// resume playing, after audio_pause()
+static void audio_resume(void)
+{
+}
+
+void send_em84_pes_packet(unsigned char* data,int len,int id,int timestamp);
+void send_em84_lpcm_packet(unsigned char* data,int len,int id,int timestamp,int freq_id);
+extern int vo_pts;
+
+// return: how many bytes can be played without blocking
+static int get_space(void)
+{
+ float x=(float)(vo_pts-ao_data.pts)/90000.0;
+ int y;
+// printf("vo_pts: %5.3f ao_pts: %5.3f\n",vo_pts/90000.0,ao_data.pts/90000.0);
+ if( x<=0 ) return 0;
+ y=freq*4*x;y/=ao_data.outburst;y*=ao_data.outburst;
+ if( y>32000 ) y=32000;
+// printf("diff: %5.3f -> %d \n",x,y);
+ return y;
+}
+
+// plays 'len' bytes of 'data'
+// it should round it down to outburst*n
+// return: number of bytes played
+static int play(void* data,int len,int flags)
+{
+ mp_msg(MSGT_AO,MSGL_V, "ao_vdr: play(%d) freq=%d\n",len,freq_id);
+ if( ao_data.format==AF_FORMAT_MPEG2 )
+ send_em84_pes_packet(data,len,0x1C0,ao_data.pts);
+ else {
+ int i;
+ unsigned short *s=data;
+ if( ao_data.format==AF_FORMAT_S16_LE || ao_data.format==AF_FORMAT_AC3 )
+ for( i=0;i<len/2;i++ ) s[i]=(s[i]>>8)|(s[i]<<8); // le<->be
+ send_em84_lpcm_packet(data,len,0xA0,ao_data.pts,freq_id);
+ }
+ return len;
+}
+
+// return: delay in seconds between first and last sample in buffer
+static float get_delay(void)
+{
+ return 0.0;
+}
diff -uN -x '*.o' -x '*.a' libao2/audio_out.c libao2/audio_out.c
--- libao2/audio_out.c 2006-06-11 20:35:42.000000000 +0200
+++ libao2/audio_out.c 2006-10-04 13:40:42.000000000 +0200
@@ -66,6 +66,7 @@
extern ao_functions_t audio_out_dxr2;
#endif
extern ao_functions_t audio_out_mpegpes;
+extern ao_functions_t audio_out_em84xx;
extern ao_functions_t audio_out_pcm;
extern ao_functions_t audio_out_pss;
@@ -73,6 +74,7 @@
{
// vo-related: will fail unless you also do -vo mpegpes/dxr2
&audio_out_mpegpes,
+ &audio_out_em84xx,
#ifdef HAVE_DXR2
&audio_out_dxr2,
#endif
diff -uN -x '*.o' -x '*.a' libao2/Makefile libao2/Makefile
--- libao2/Makefile 2006-06-11 20:35:42.000000000 +0200
+++ libao2/Makefile 2006-10-04 13:41:12.000000000 +0200
@@ -4,6 +4,7 @@
SRCS=audio_out.c \
ao_mpegpes.c \
+ ao_em84xx.c \
ao_null.c \
ao_pcm.c \
$(OPTIONAL_SRCS) \
--- etc/codecs.conf 2006-06-11 20:35:46.000000000 +0200
+++ etc/codecs.conf 2006-10-04 13:39:50.000000000 +0200
@@ -43,6 +43,15 @@
driver mpegpes
out MPES
+videocodec em84xx
+ info "EM84xx (em84 decoder)"
+ comment "for hardware decoding"
+ status working
+ format 0x10000001 ; mpeg 1
+ format 0x10000002 ; mpeg 2
+ driver em84xx
+ out MPES
+
videocodec mpeg12
info "MPEG-1 or 2 (libmpeg2)"
comment "with postprocessing"
--- Makefile 2006-06-11 20:35:47.000000000 +0200
+++ Makefile 2006-10-04 14:33:56.000000000 +0200
@@ -74,6 +74,7 @@
$(DIRECTFB_LIB) \
$(CACA_LIB) \
$(VESA_LIB) \
+ -lEM84xx \
ifeq ($(EXTERNAL_VIDIX),yes)
VO_LIBS += $(EXTERNAL_VIDIX_LIB)
diff -uN -x '*.o' -x '*.a' libvo/Makefile libvo/Makefile
--- libvo/Makefile 2006-06-11 20:35:43.000000000 +0200
+++ libvo/Makefile 2006-10-04 13:41:27.000000000 +0200
@@ -13,6 +13,7 @@
sub.c \
video_out.c \
vo_mpegpes.c \
+ vo_em84xx.c \
vo_null.c \
vo_yuv4mpeg.c \
$(OPTIONAL_SRCS) \
diff -uN -x '*.o' -x '*.a' libvo/video_out.c libvo/video_out.c
--- libvo/video_out.c 2006-06-11 20:35:43.000000000 +0200
+++ libvo/video_out.c 2006-10-04 13:40:56.000000000 +0200
@@ -92,6 +92,7 @@
extern vo_functions_t video_out_aa;
extern vo_functions_t video_out_caca;
extern vo_functions_t video_out_mpegpes;
+extern vo_functions_t video_out_em84xx;
extern vo_functions_t video_out_yuv4mpeg;
#ifdef HAVE_DIRECTX
extern vo_functions_t video_out_directx;
@@ -242,6 +243,7 @@
&video_out_xvmc,
#endif
&video_out_mpegpes,
+ &video_out_em84xx,
&video_out_yuv4mpeg,
#ifdef HAVE_PNG
&video_out_png,
diff -uN -x '*.o' -x '*.a' libvo/vo_em84xx.c libvo/vo_em84xx.c
--- libvo/vo_em84xx.c 1970-01-01 01:00:00.000000000 +0100
+++ libvo/vo_em84xx.c 2006-10-16 15:26:20.000000000 +0200
@@ -0,0 +1,504 @@
+/*
+ * Based on: vo_mpegpes.c
+ *
+ * vo_em84xx.c - video out to em84xx decoder
+ *
+ * Copyright (C) 2006 Helmut Auer & Uwe Scheffler
+ *
+ */
+#define KILOBYTE(n) ((n) * 1024)
+#define _DEFINE_FMP_TYPES_
+#define _BARBADOS_
+
+#include <fmp.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+
+#define PES_EM_MAX_SIZE KILOBYTE(32)
+#define PES_FILE_MAX_SIZE KILOBYTE(32)
+
+#define PES_HEADER_MAX_LEN 32 // a little bit more than needed :)
+
+#include "mp_msg.h"
+#include "aspect.h"
+#include "video_out.h"
+#include "video_out_internal.h"
+
+#define VDR_FILE_MAX_LEN 2000000000
+#define VDR_DEF_NAME "/video/001.vdr"
+
+extern float monitor_aspect;
+extern float movie_aspect;
+static int so_width=0, so_height=0;
+int mdelay=0;
+int mLastAspect=0;
+int mSourceAspect = 0;
+
+int SetAudioSampleRate=48000;
+int mLastSetAudioSampleRate=0;
+
+int vo_vdr_fd = -1;
+static int vdrFileLen = 0;
+
+static char vdrFileName[1024] = "";
+
+static vo_info_t info =
+{
+ "Mpeg-PES video to EM84 or file",
+ "em84xx",
+ "HelAu",
+ ""
+};
+
+LIBVO_EXTERN (em84xx)
+
+static int
+config(uint32_t s_width, uint32_t s_height, uint32_t width, uint32_t height, uint32_t flags,
char *title, uint32_t format)
+{
+ switch( s_height ) {
+ case 288:
+ case 576:
+ case 240:
+ case 480:
+ break;
+ default:
+ mp_msg(MSGT_VO,MSGL_ERR,"EM84: height=%d not supported (try 240/480 (ntsc) or 288/576
(pal)\n",s_height);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int preinit(const char *arg)
+{
+ DWORD PropVal, PropValSize, rc;
+
+ if( arg ) {
+ strcpy( vdrFileName, arg );
+
+ vo_vdr_fd=open(vdrFileName,O_WRONLY|O_CREAT|O_TRUNC,0666);
+ if(vo_vdr_fd<0){
+ mp_msg(MSGT_VO,MSGL_ERR, "Error opening <%s>\n", vdrFileName);
+ return -1;
+ }
+ mp_msg(MSGT_VO,MSGL_INFO, "Saving PES stream to %s\n", vdrFileName);
+// mp_msg(MSGT_VO,MSGL_V, "Saving PES stream to %s\n", vdrFileName);
+ }
+ else {
+ MPEGDriverEntry(NO_DRIVE);
+ if( (rc = FMPOpen(FMPF_PROGRAM, PES_EM_MAX_SIZE, 10, NULL, 0)) != FMPE_OK ) {
+ mp_msg(MSGT_VO,MSGL_ERR,"EM84: FMPOpen Error: %x\n",rc);
+ return -1;
+ }
+
+ Wnd_type dest_wnd;
+ dest_wnd.x = 0;
+ dest_wnd.y = 0;
+ dest_wnd.w = 720;
+ dest_wnd.h = 576;
+
+ DWORD sizeOut = 0;
+ DWORD doHwReset = 0;
+ DWORD disableSpdifOndoHwReset = 0;
+ eAudioDigitalOutput_type spdifMode = eAudioDigitalOutput_Pcm;
+
+ DWORD tvOut = SET_TV | SET_PAL;// | 0x10;// | SET_ONETOONE;// | SET_TV_AS_USER;
+
+ FMPProperty (KSPROPERTY_TYPE_SET, REGISTRY_COMMON_SET, eTvOut, 0, &tvOut, sizeof(tvOut ),
&sizeOut);
+ FMPProperty (KSPROPERTY_TYPE_SET, REGISTRY_COMMON_SET, eDoHwReset, 0, &doHwReset,
sizeof(doHwReset), &sizeOut);
+ FMPProperty (KSPROPERTY_TYPE_SET, REGISTRY_COMMON_SET, eDisableSpdifOutputInReset , 0,
&disableSpdifOndoHwReset , sizeof(disableSpdifOndoHwReset ), &sizeOut); // not needed, but you
never now :)
+// FMPProperty (KSPROPERTY_TYPE_SET, AUDIO_SET, eAudioDigitalOutput, 0, &spdifMode,
sizeof(eAudioDigitalOutput_type), &sizeOut);
+ FMPProperty (KSPROPERTY_TYPE_SET, VIDEO_SET, evDestinationWindow, 0, &dest_wnd,
sizeof(Wnd_type), &sizeOut);
+
+ // this line is necc, so that 16x9 switching works even after setting the video dest.
window from above
+ FMPSet(FMPI_OVERLAY_FLAGS, OSD_VIDEO_INDEPENDENT_DEST);
+
+ // Disable 16 bit VMI (at least by 6086N2 doesn't like this, YMMV again)
+ PropVal=0;
+
FMPProperty(KSPROPERTY_TYPE_SET,REGISTRY_VGAVENDOR_SET,eVmi_16bits,0,&PropVal,sizeof(PropVal),&PropValSize);
+
+ eAudioFormat_type audioformat = eAudioFormat_PCM;
+ FMPProperty (KSPROPERTY_TYPE_SET, AUDIO_SET, eAudioFormat, 0, &audioformat,
sizeof(eAudioFormat_type), &sizeOut);
+
+ FMPSet(FMPI_VIDEOOUT, FMPV_VIDEOOUT_COMPOSITE | FMPV_VIDEOOUT_TV |
+ FMPV_VIDEOOUT_PAL);
+
+ // SetVideoFormat(Setup.VideoFormat);
+ FMPSetVideoPortDimensions(720, 576);
+
+ FMPPlay();
+ }
+
+ return 0;
+}
+
+
+static void draw_osd(void)
+{
+}
+
+
+static void my_write(unsigned char* header,int headerLen, unsigned char* data,int dataLen, int
streamType)
+{
+ FMP_BUFFER fmpBuf;
+ DWORD rc;
+ DWORD flags = 0;
+// static int count=0;
+
+
+ if(vo_vdr_fd<0){
+ if ( dataLen > 0 && ( dataLen + headerLen ) <= PES_EM_MAX_SIZE ) {
+ fmpBuf.dwFlagsEx = streamType;
+ if( (rc = FMPGetBuffer(&fmpBuf, TRUE)) != FMPE_OK ) {
+ mp_msg(MSGT_VO,MSGL_ERR,"[mplayer] Couldn't allocate em8400 replaybuffer: %lx\n", rc);
+ return;
+ }
+
+ memcpy( fmpBuf.pBuffer, header, headerLen );
+ memcpy( fmpBuf.pBuffer + headerLen, data, dataLen );
+
+ fmpBuf.dwDataSize = headerLen + dataLen;
+
+ if( (rc = FMPPush(&fmpBuf)) != FMPE_OK ) {
+ mp_msg(MSGT_VO,MSGL_ERR,"EM84: FMPPush Error: %x\n",rc);
+ }
+ }
+ else
+ mp_msg(MSGT_VO,MSGL_ERR,"EM84: my_write invalid length: %d-%d\n",headerLen,dataLen);
+ }
+ else {
+ if( vdrFileLen + headerLen + dataLen > VDR_FILE_MAX_LEN ) {
+ close(vo_vdr_fd);
+ vdrFileLen = 0;
+ if(vdrFileName[strlen(vdrFileName)-1] == '9') {
+ (vdrFileName[strlen(vdrFileName)-1]) = '0';
+ if(vdrFileName[strlen(vdrFileName)-2] == '9') {
+ (vdrFileName[strlen(vdrFileName)-2]) = '0';
+ (vdrFileName[strlen(vdrFileName)-3])++;
+ }
+ else
+ (vdrFileName[strlen(vdrFileName)-2])++;
+ }
+ else
+ (vdrFileName[strlen(vdrFileName)-1])++;
+
+ vo_vdr_fd=open(vdrFileName,O_WRONLY|O_CREAT,0666);
+ if(vo_vdr_fd<0)
+ mp_msg(MSGT_VO,MSGL_ERR, "Error opening <%s>\n", vdrFileName);
+ else
+ mp_msg(MSGT_VO,MSGL_INFO, "Saving PES stream to %s\n", vdrFileName);
+ }
+
+ if(vo_vdr_fd>=0){
+ write(vo_vdr_fd,header,headerLen); // write to file
+ write(vo_vdr_fd,data,dataLen); // write to file
+ usleep(0);
+ vdrFileLen += headerLen + dataLen;
+ }
+
+ }
+}
+
+
+void send_em84_pes_packet(unsigned char* data,int len,int id,int timestamp)
+{
+
+ int pos = 0;
+ int esLength = 0;
+
+
+ if (!data[pos] && !data[pos+1] && data[pos+2] == 0x01 && (data[pos+3] == 0xB3 ))
+ {
+
+ mp_msg(MSGT_VO,MSGL_V,"VO: [em84xx] switch: %d \n",((data[pos + 7]) & 0xF0) );
+ switch ((data[pos + 7]) & 0xF0)
+ {
+
+ case 0x20:
+ mp_msg(MSGT_VO,MSGL_V,"VO: [em84xx] (case 0x20) FMPV_VIDEOASPECT
--> 4x3 \n");
+ mSourceAspect=43;
+ break;
+
+ case 0x30:
+ mp_msg(MSGT_VO,MSGL_V,"VO: [em84xx] (case 0x30) FMPV_VIDEOASPECT
--> 16x9 \n");
+ mSourceAspect=169;
+ break;
+
+ default:
+ mp_msg(MSGT_VO,MSGL_V,"VO: [em84xx] (default) FMPV_VIDEOASPECT
--> NORMAL \n");
+ mSourceAspect=1;
+ break;
+
+ }
+
+
+
+ if (mLastAspect != mSourceAspect && mSourceAspect != 0)
+ {
+
+ // Aspect ratio
+ if (mSourceAspect == 169) {
+ //Source 16:9
+ mp_msg(MSGT_VO,MSGL_V,"VO: [em84xx] source aspect ratio 16:9\n");
+ if (1.76 <= monitor_aspect && monitor_aspect <=1.80) {
+ //OUTPUT 16:9
+ FMPSet(FMPI_VIDEOASPECT, FMPV_VIDEOASPECT_16x9_16x9_NORMAL);
+ mp_msg(MSGT_VO,MSGL_V,"VO: [em84xx] monitor aspect ratio 16:9\n");
+ } else {
+ FMPSet(FMPI_VIDEOASPECT, FMPV_VIDEOASPECT_16x9_4x3_LETTERBOX);
+ mp_msg(MSGT_VO,MSGL_V,"VO: [em84xx] monitor aspect ratio 4:3\n");
+ }
+ }
+ if (mSourceAspect == 43) {
+ //Source 4:3
+ mp_msg(MSGT_VO,MSGL_V,"VO: [em84xx] source aspect ratio 4:3\n");
+ if (1.76 <= monitor_aspect && monitor_aspect <=1.80) {
+ //OUTPUT 16:9
+ FMPSet(FMPI_VIDEOASPECT, FMPV_VIDEOASPECT_4x3_16x9_ZOOM_OFF);
+ mp_msg(MSGT_VO,MSGL_V,"VO: [em84xx] monitor aspect ratio 16:9\n");
+ } else {
+ FMPSet(FMPI_VIDEOASPECT, FMPV_VIDEOASPECT_4x3_4x3_NORMAL);
+ mp_msg(MSGT_VO,MSGL_V,"VO: [em84xx] monitor aspect ratio 4:3\n");
+ }
+ }
+ if (mSourceAspect == 1) {
+ //Source 1:1
+ mp_msg(MSGT_VO,MSGL_V,"VO: [em84xx] source aspect ratio 1:1\n");
+ if (1.76 <= monitor_aspect && monitor_aspect <=1.80) {
+ //OUTPUT 16:9
+ FMPSet(FMPI_VIDEOASPECT, FMPV_VIDEOASPECT_16x9_16x9_NORMAL);
+ mp_msg(MSGT_VO,MSGL_V,"VO: [em84xx] monitor aspect ratio 16:9\n");
+ } else {
+ FMPSet(FMPI_VIDEOASPECT, FMPV_VIDEOASPECT_4x3_4x3_NORMAL);
+ mp_msg(MSGT_VO,MSGL_V,"VO: [em84xx] monitor aspect ratio 4:3\n");
+ }
+ }
+ if (mdelay >= 2)
+ {
+ mLastAspect = mSourceAspect;
+ mdelay = 0;
+ }else
+ mdelay +=1;
+ }
+ }
+
+
+ unsigned char pes_header[PES_HEADER_MAX_LEN];
+ int ptslen=timestamp?5:1;
+ int pesMaxLen = ( vo_vdr_fd >= 0 ) ? PES_FILE_MAX_SIZE : PES_EM_MAX_SIZE;
+ int payload_size;
+
+ mp_msg(MSGT_VO,MSGL_V, "Sending PES pts=%x size=%d\n",timestamp,len);
+
+ // startcode:
+ pes_header[0]=pes_header[1]=0;
+ pes_header[2]=id>>8; pes_header[3]=id&255;
+
+ while( len>0 ) {
+ if( 6+ptslen+len > pesMaxLen )
+ payload_size=pesMaxLen-(6+ptslen);
+ else
+ payload_size=len; // data + PTS
+
+ // construct PES header: (code from ffmpeg's libav)
+ // packetsize:
+ pes_header[4]=(ptslen+payload_size)>>8;
+ pes_header[5]=(ptslen+payload_size)&255;
+
+ if( ptslen==5 ) {
+ int x;
+ // presentation time stamp:
+ x=(0x02 << 4) | (((timestamp >> 30) & 0x07) << 1) | 1;
+ pes_header[6]=x;
+ x=((((timestamp >> 15) & 0x7fff) << 1) | 1);
+ pes_header[7]=x>>8; pes_header[8]=x&255;
+ x=((((timestamp) & 0x7fff) << 1) | 1);
+ pes_header[9]=x>>8; pes_header[10]=x&255;
+ }
+ else {
+ // stuffing and header bits:
+ pes_header[6]=0x0f;
+ }
+
+ my_write(pes_header,6+ptslen,data,payload_size, FMP_VIDEO_PES);
+
+ len-=payload_size; data+=payload_size;
+ ptslen=1; // store PTS only once, at first packet!
+ }
+}
+
+
+void send_em84_lpcm_packet(unsigned char* data,int len,int id,unsigned int timestamp,int freq_id)
+{
+
+ switch (freq_id)
+ {
+ case 0:
+ SetAudioSampleRate=48000;
+ break;
+
+ case 1:
+ SetAudioSampleRate=96000;
+ break;
+
+ case 2:
+ SetAudioSampleRate=44100;
+ break;
+
+ case 3:
+ SetAudioSampleRate=32000;
+ break;
+
+ default:
+ break;
+ }
+
+ if (SetAudioSampleRate != mLastSetAudioSampleRate)
+ {
+ mLastSetAudioSampleRate = SetAudioSampleRate;
+
+ DWORD sizeOut;
+ FMPProperty (KSPROPERTY_TYPE_SET, AUDIO_SET, eAudioSampleRate, 0,
&mLastSetAudioSampleRate, sizeof(mLastSetAudioSampleRate), &sizeOut);
+
+ int newSampleFactor = (int)(((float)mLastSetAudioSampleRate/48000.0)*1000.0);
+ FMPSet(FMPI_AUDIO_SPEED, newSampleFactor);
+ mp_msg(MSGT_VO,MSGL_INFO,"VO: [em84xx] SetAudioSampleRate:%d newSampleFactor:%d \n",
SetAudioSampleRate, newSampleFactor);
+ }
+
+
+ unsigned char pes_header[PES_HEADER_MAX_LEN];
+ int payload_size;
+ int ptslen=timestamp?5:0;
+ int pesMaxLen = ( vo_vdr_fd >= 0 ) ? PES_FILE_MAX_SIZE : PES_EM_MAX_SIZE;
+
+ mp_msg(MSGT_VO,MSGL_V, "Sending LPCM pts=%x size=%d\n",timestamp,len);
+
+ // startcode:
+ pes_header[0]=pes_header[1]=0;
+ pes_header[2]=1; pes_header[3]=0xA0;//0xA0
+
+ while( len>=4 ) {
+ if( 16+ptslen+len > pesMaxLen )
+ payload_size=pesMaxLen-(16+ptslen);
+ else
+ payload_size=len; // data + PTS
+
+ payload_size&=(~3); // align!
+
+ // packetsize:
+ pes_header[4]=(payload_size+3+ptslen+7)>>8;
+ pes_header[5]=(payload_size+3+ptslen+7)&255;
+
+ // stuffing:
+ // TTCCxxxx CC=css TT=type: 1=STD 0=mpeg1 2=vob
+ pes_header[6]=0x81;
+
+ // FFxxxxxx FF=pts flags=2 vs 0
+ pes_header[7]=ptslen ? 0x80 : 0;
+
+ // hdrlen:
+ pes_header[8]=ptslen;
+
+ if( ptslen ) {
+ int x;
+ // presentation time stamp:
+ x=(0x02 << 4) | (((timestamp >> 30) & 0x07) << 1) | 1;
+ pes_header[9]=x;
+ x=((((timestamp >> 15) & 0x7fff) << 1) | 1);
+ pes_header[10]=x>>8; pes_header[11]=x&255;
+ x=((((timestamp) & 0x7fff) << 1) | 1);
+ pes_header[12]=x>>8; pes_header[13]=x&255;
+ }
+
+// ============ LPCM header: (7 bytes) =================
+// Info by mocm at convergence.de
+
+// ID:
+ pes_header[ptslen+9]=id;
+// pes_header[ptslen+9]=MM_AUDIO_FORMAT_PCM;
+
+// number of frames:
+ pes_header[ptslen+10]=0x07;
+
+// first acces unit pointer, i.e. start of audio frame:
+ pes_header[ptslen+11]=0x00;
+ pes_header[ptslen+12]=0x04;
+
+// audio emphasis on-off 1 bit
+// audio mute on-off 1 bit
+// reserved 1 bit
+// audio frame number 5 bit
+ pes_header[ptslen+13]=0x0C;
+
+// quantization word length 2 bit
+// audio sampling frequency (48khz = 0, 96khz = 1) 2 bit
+// reserved 1 bit
+// number of audio channels - 1 (e.g. stereo = 1) 3 bit
+ pes_header[ptslen+14]=1;//|(freq_id<<4);
+
+// dynamic range control (0x80 if off)
+ pes_header[ptslen+15]=0x80;
+
+ my_write(pes_header,16+ptslen,data,payload_size, FMP_AUDIO_PES);
+
+ len-=payload_size;
+ data+=payload_size;
+ ptslen=0; // store PTS only once, at first packet!
+ }
+}
+
+
+static int draw_frame(uint8_t * src[])
+{
+ vo_mpegpes_t *p=(vo_mpegpes_t *)src[0];
+ send_em84_pes_packet(p->data,p->size,p->id,(p->timestamp>0)?p->timestamp:vo_pts); // video data
+ return 0;
+}
+
+static void flip_page (void)
+{
+}
+
+static int draw_slice(uint8_t *srcimg[], int stride[], int w,int h,int x0,int y0)
+{
+ return 0;
+}
+
+
+static int query_format(uint32_t format)
+{
+ if( format==IMGFMT_MPEGPES )
+ return VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW|VFCAP_TIMER;
+
+ return 0;
+}
+
+static void uninit(void)
+{
+ if(vo_vdr_fd<0){
+ FMPStop();
+ FMPClose();
+ MPEGDriverUnload();
+ }
+ else
+ close( vo_vdr_fd );
+}
+
+
+static void check_events(void)
+{
+}
+
+static int control(uint32_t request, void *data, ...)
+{
+ mp_msg(MSGT_VO,MSGL_V, "control() request: %d\n", request);
+ switch( request ) {
+ case VOCTRL_QUERY_FORMAT:
+
+ return query_format(*((uint32_t*)data));
+ }
+
+ return VO_NOTIMPL;
+}
+
More information about the MPlayer-dev-eng
mailing list