[Mplayer-cvslog] CVS: main/libaf af_export.c,NONE,1.1 Makefile,1.11,1.12 af.c,1.24,1.25 control.h,1.5,1.6

Anders Johansson CVS anders at mplayerhq.hu
Sat Sep 20 15:42:55 CEST 2003


Update of /cvsroot/mplayer/main/libaf
In directory mail:/var/tmp.root/cvs-serv2795

Modified Files:
	Makefile af.c control.h 
Added Files:
	af_export.c 
Log Message:
Adding filter for exporting audio data to visual effect applications

--- NEW FILE ---
/* This audio filter exports the incomming signal to other processes
   using memory mapping. Memory mapped area contains a header: 
      int nch, 
      int size, 
      unsigned long long counter (updated every time the  contents of
                                  the area changes),
   the rest is payload (non-interleaved).
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "af.h"

extern char * get_path( char * filename );


#define DEF_SZ 512 // default buffer size (in samples)
#define SHARED_FILE "mplayer-af_export" /* default file name 
					   (relative to ~/.mplayer/ */

#define SIZE_HEADER (2 * sizeof(int) + sizeof(unsigned long long))

// Data for specific instances of this filter
typedef struct af_export_s
{
  unsigned long long  count; // Used for sync
  void* buf[AF_NCH]; 	// Buffers for storing the data before it is exported
  int 	sz;	      	// Size of buffer in samples
  int 	wi;  		// Write index
  int	fd;           	// File descriptor to shared memory area
  char* filename;      	// File to export data
  void* mmap_area;     	// MMap shared area
} af_export_t;


/* Initialization and runtime control
   af audio filter instance
   cmd control command
   arg argument
*/
static int control(struct af_instance_s* af, int cmd, void* arg)
{
  af_export_t* s = af->setup;
  switch (cmd){
  case AF_CONTROL_REINIT:{
    int i=0;
    int mapsize;

    // Free previous buffers
    if (s->buf && s->buf[0])
      free(s->buf[0]);

    // unmap previous area
    if(s->mmap_area)
      munmap(s->mmap_area, SIZE_HEADER + (af->data->bps*s->sz*af->data->nch));
    // close previous file descriptor
    if(s->fd)
      close(s->fd);	

    // Accept only int16_t as input fomat (which sucks)
    af->data->rate   = ((af_data_t*)arg)->rate;
    af->data->nch    = ((af_data_t*)arg)->nch;
    af->data->format = AF_FORMAT_SI | AF_FORMAT_NE;
    af->data->bps    = 2;
	
    // If buffer length isn't set, set it to the default value
    if(s->sz == 0)
      s->sz = DEF_SZ;
	
    // Allocate new buffers (as one continous block)
    s->buf[0] = calloc(DEF_SZ*af->data->nch, af->data->bps);
    if(NULL == s->buf[0])
      af_msg(AF_MSG_FATAL, "[export] Out of memory\n");
    for(i = 1; i < af->data->nch; i++)
      s->buf[i] = s->buf[0] + i*DEF_SZ*af->data->bps;
	
    // Init memory mapping
    s->fd = open(s->filename, O_RDWR | O_CREAT | O_TRUNC, 0640);
    af_msg(AF_MSG_INFO, "[export] Exporting to file: %s\n", s->filename);
    if(s->fd < 0)
      af_msg(AF_MSG_FATAL, "[export] Could not open/create file: %s\n", 
	     s->filename);
    
    // header + buffer
    mapsize = (SIZE_HEADER + (af->data->bps * s->sz * af->data->nch));
    
    // grow file to needed size
    for(i = 0; i < mapsize; i++){
      char null = 0;
      write(s->fd, (void*) &null, 1);
    }
	
    // mmap size
    s->mmap_area = mmap(0, mapsize, PROT_READ|PROT_WRITE,MAP_SHARED, s->fd, 0);
    if(s->mmap_area == NULL)
      af_msg(AF_MSG_FATAL, "[export] Could not mmap file %s\n", s->filename);
    af_msg(AF_MSG_INFO, "[export] Memory mapped to file: %s (%p)\n", 
	   s->filename, s->mmap_area);

    // Initialize header
    *((int*)s->mmap_area) = af->data->nch;
    *((int*)s->mmap_area + 1) = s->sz * af->data->bps * af->data->nch;
    msync(s->mmap_area, mapsize, MS_ASYNC);

    // Use test_output to return FALSE if necessary
    return af_test_output(af, (af_data_t*)arg);
  }
  case AF_CONTROL_COMMAND_LINE:{
    int i=0;
    char *str = arg;
    
    if (!str){
      if(s->filename) 
	free(s->filename);

      s->filename = get_path(SHARED_FILE);
      return AF_OK;
    }
	
    while((str[i]) && (str[i] != ':'))
      i++;

    if(s->filename)
      free(s->filename);

    s->filename = calloc(i + 1, sizeof(char));
    memcpy(s->filename, str, i);
    s->filename[i] = 0;
	
    sscanf(str + i, "%d", &(s->sz));
  
    return af->control(af, AF_CONTROL_EXPORT_SZ | AF_CONTROL_SET, &s->sz);
  }
  case AF_CONTROL_EXPORT_SZ | AF_CONTROL_SET:
    s->sz = * (int *) arg;
    if((s->sz <= 0) || (s->sz > 2048))
      af_msg( AF_MSG_ERROR, "[export] Buffer size must be between"
	      " 1 and 2048\n" );

    return AF_OK;
  case AF_CONTROL_EXPORT_SZ | AF_CONTROL_GET:
    *(int*) arg = s->sz;
    return AF_OK;
      
  }
  return AF_UNKNOWN;
}

/* Free allocated memory and clean up other stuff too.
   af audio filter instance
*/
static void uninit( struct af_instance_s* af )
{
  int i;
  if (af->data){
    free(af->data);
    af->data = NULL;
  }

  if(af->setup){
    af_export_t* s = af->setup;
    if (s->buf && s->buf[0])
      free(s->buf[0]);
    
    // Free mmaped area
    if(s->mmap_area)
      munmap(s->mmap_area, sizeof(af_export_t));	  

    if(s->fd > -1)
      close(s->fd);

    if(s->filename)
	free(s->filename);

    free(af->setup);
    af->setup = NULL;
  }
}

/* Filter data through filter
   af audio filter instance
   data audio data
*/
static af_data_t* play( struct af_instance_s* af, af_data_t* data )
{
  af_data_t*   	c   = data;	     // Current working data
  af_export_t* 	s   = af->setup;     // Setup for this instance
  int16_t* 	a   = c->audio;	     // Incomming sound
  int 		nch = c->nch;	     // Number of channels
  int		len = c->len/c->bps; // Number of sample in data chunk
  int 		sz  = s->sz;         // buffer size (in samples)
  int 		flag = 0;	     // Set to 1 if buffer is filled
  
  int 		ch, i;

  // Fill all buffers
  for(ch = 0; ch < nch; ch++){
    int 	wi = s->wi;    	 // Reset write index
    int16_t* 	b  = s->buf[ch]; // Current buffer 

    // Copy data to export buffers 
    for(i = ch; i < len; i += nch){
      b[wi++] = a[i];
      if(wi >= sz){ // Don't write outside the end of the buffer
	flag = 1;
	break;
      }
    }
    s->wi = wi % s->sz;
  }

  // Export buffer to mmaped area
  if(flag){
    // update buffer in mapped area
    memcpy(s->mmap_area + SIZE_HEADER, s->buf[0], sz * c->bps * nch);
    s->count++; // increment counter (to sync)
    memcpy(s->mmap_area + SIZE_HEADER - sizeof(s->count), 
	   &(s->count), sizeof(s->count));
  }

  // We don't modify data, just export it
  return data;
}

/* Allocate memory and set function pointers
   af audio filter instance 
   returns AF_OK or AF_ERROR
*/
static int af_open( af_instance_t* af )
{
  af->control = control;
  af->uninit  = uninit;
  af->play    = play;
  af->mul.n   = 1;
  af->mul.d   = 1;
  af->data    = calloc(1, sizeof(af_data_t));
  af->setup   = calloc(1, sizeof(af_export_t));
  if((af->data == NULL) || (af->setup == NULL))
    return AF_ERROR;

  ((af_export_t *)af->setup)->filename = get_path(SHARED_FILE);

  return AF_OK;
}

// Description of this filter
af_info_t af_info_export = {
    "Sound export filter",
    "export",
    "Anders; Gustavo Sverzut Barbieri <gustavo.barbieri at ic.unicamp.br>",
    "",
    AF_FLAGS_REENTRANT,
    af_open
};

Index: Makefile
===================================================================
RCS file: /cvsroot/mplayer/main/libaf/Makefile,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- Makefile	31 Mar 2003 16:55:53 -0000	1.11
+++ Makefile	20 Sep 2003 13:42:26 -0000	1.12
@@ -2,7 +2,7 @@
 
 LIBNAME = libaf.a
 
-SRCS=af.c af_mp.c af_dummy.c af_delay.c af_channels.c af_format.c af_resample.c window.c filter.c af_volume.c af_equalizer.c af_tools.c af_comp.c af_gate.c af_pan.c af_surround.c af_sub.c
+SRCS=af.c af_mp.c af_dummy.c af_delay.c af_channels.c af_format.c af_resample.c window.c filter.c af_volume.c af_equalizer.c af_tools.c af_comp.c af_gate.c af_pan.c af_surround.c af_sub.c af_export.c
 
 OBJS=$(SRCS:.c=.o)
 

Index: af.c
===================================================================
RCS file: /cvsroot/mplayer/main/libaf/af.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- af.c	17 Jan 2003 01:00:07 -0000	1.24
+++ af.c	20 Sep 2003 13:42:26 -0000	1.25
@@ -21,6 +21,7 @@
 extern af_info_t af_info_pan;
 extern af_info_t af_info_surround;
 extern af_info_t af_info_sub;
+extern af_info_t af_info_export;
 
 static af_info_t* filter_list[]={ \
    &af_info_dummy,\
@@ -35,6 +36,7 @@
    &af_info_pan,\
    &af_info_surround,\
    &af_info_sub,\
+   &af_info_export,\
    NULL \
 };
 

Index: control.h
===================================================================
RCS file: /cvsroot/mplayer/main/libaf/control.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- control.h	7 Jan 2003 10:33:30 -0000	1.5
+++ control.h	20 Sep 2003 13:42:26 -0000	1.6
@@ -215,4 +215,7 @@
 #define AF_CONTROL_SUB_FC		0x00001F00 | AF_CONTROL_FILTER_SPECIFIC
 
 
+// Export
+#define AF_CONTROL_EXPORT_SZ            0x00002000 | AF_CONTROL_FILTER_SPECIFIC
+
 #endif /*__af_control_h */



More information about the MPlayer-cvslog mailing list