[vlc-devel] Re: Problem with an access_demux module

Christophe Démaret vlc at cdemaret.com
Sat Jun 10 12:12:51 CEST 2006


Laurent Aimar a écrit :
>  Same thing again, all changes in sys->fmt after es_out_Add are ignored ...

Thanks, fenrir, it worked :)

Unfortunately I still have some issues and I'm sure this because I 
missed something in the VLC API once again.

I have cleaned the code to make it more readable.
What I would like to do here is very simple: take the data I've read 
from an FPGA into a block as RV24 (RAW RGB 24 bits/pixel) and just send it.

The stream was (hopefully) correctly declared following fenrir's 
instructions.
Now what to I get ?
I cannot display it on the platform it is running on so I've tried to 
--sout it into an AVI (only container I found for RV24 content).
For the test, the buffer contains a 32 bits counter so: 00 00 00 00 01 
00 00 00 02 00 00 00 etc. Of course after FF 00 00 00 we have 00 01 00 
00 (Big Endian is fun).
I know that the data are correctly read (look at the attempt n°1 + The 
function I use are well tested).
However when I look into the AVI with an hex editor there is a lot of 
garbage (mostly zeros but also somme error messages from VLC etc. Looks 
like uninitialized memory)  :-/ do you see any good reason for that ? Is 
it normal for an AVI (padding or something) ? Am I sending the packet a 
wrong way ?

Anyway the AVI cannot be read: VLC only displays some "middle grey" 
(0x808080 in RGB or YUV) :-/ As the TS problem (see after) it looks like 
a date problem.

I've patched the ts.c muxer to accept RV24 (attempt 3) but the resulting 
data is empty (0 bytes) probably due to:
 > [00000159] mux_ts private warning: packet with too strange dts
 > (dts=12603000240,old=12583001107,pcr=12583001107)
but although I have looked in the source code I didn't really understood 
what's wrong (the "if" is... hmm... no-that-easy to understand :D) Is 
this because of my 0.1 FPS frame rate ? The final goal is to stream so 
if ts doesn't work... :-/

My main questions are :
1) Are my AVI file completely broken and what is wrong with them ?
2) Is the general structure of my module correct: am I doing was should 
be done in the right order ?
3) What is wrong with my DTS/PTS ?

In ftp://ftp2.cdemaret.com/cdemaret/ml I have upload the result of 3 
tests with -vvv (the complete command line is on the first line of the log):
1) with MASSIVE_DEBUG enabled and AVI output
2) with MASSIVE_DEBUG disabled and AVI output
3) with MASSIVE_DEBUG disabled and TS output

If someone here could be of any help, I would be very grateful.

Have a nice week end and don't forget to find a gift for father's day.

Christophe.


--- CODE ---

/*****************************************************************************
  * Preamble
 
*****************************************************************************/
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>

#include <vlc/vlc.h>
#include <vlc/input.h>
#include <ibis_v2.h>

/*****************************************************************************
* Defines: some useful stuff...
******************************************************************************/

#define FPGA_FPS .1
/* Yes, 1/10 FPS. This we are SLOW */
/* THREAD_COND_TIMEOUT in include/vlc_config.h has to be patched 
accordingly */

#define CACHING_TEXT N_("Caching value in ms")
#define CACHING_LONGTEXT N_( \
     "Allows you to modify the default caching value for fpga streams. 
This " \
     "value should be set in millisecond units." )
#define FPS_TEXT N_("Framerate")
#define FPS_LONGTEXT N_( \
     "Specifies the number of frames per second (eg. 24, 25, 29.97, 30).")

#define MAX(x,y) ((x)>(y)?(x):(y))
#define MIN(x,y) ((x)<(y)?(x):(y))

#define FPGA_WIDTH          320
#define FPGA_HEIGHT         240
#define FPGA_OFF_H          0
#define FPGA_OFF_V          0

#define FPGA_TOTAL_WIDTH    600
/* 600 since 800/4*3 = 600 */
/* WARNING: FPGA_TOTAL_WIDTH and FPGA_WIDTH are NOT in the same units */
/* FPGA_TOTAL_WIDTH = words (32 bits), FPGA_WIDTH = pixels (24 bits)*/

// #define MASSIVE_DEBUG
/* Only few lines will be read and 100% of the data will be displayed in 
the debug */


/*****************************************************************************
  * Module descriptor
 
*****************************************************************************/

static int  Open ( vlc_object_t * );
static void Close( vlc_object_t * );

vlc_module_begin();
     set_description( _("SMVP card FPGA frame reader") );
     set_shortname( _("FPGA SMVP") );
     set_category( CAT_INPUT );
     set_subcategory( SUBCAT_INPUT_ACCESS );
     add_integer( "fpga-caching", DEFAULT_PTS_DELAY / 1000, NULL,
      CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
     add_float( "fpga-fps", FPGA_FPS, NULL, FPS_TEXT, FPS_LONGTEXT, 
VLC_TRUE );
     set_capability( "access_demux", 10 );
     add_shortcut( "fpga" );
     set_callbacks( Open, Close );
vlc_module_end();

/*****************************************************************************
  * Local prototypes
 
*****************************************************************************/
static int Control( demux_t *, int, va_list );
static int Demux  ( demux_t * );

struct demux_sys_t
{
     es_format_t fmt;
     es_out_id_t *es;

     float f_fps;
     mtime_t i_next_date;
     int i_incr;

     int fd;
};

/*****************************************************************************
  * DemuxOpen:
 
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
     demux_t     *p_demux = (demux_t*)p_this;
     demux_sys_t *p_sys;
     vlc_value_t val;

     /* Fill p_demux field */
     /* callbacks*/
     p_demux->pf_demux = Demux;
     p_demux->pf_control = Control;
     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
     memset( p_sys, 0, sizeof( demux_sys_t ) );

     msg_Dbg( p_demux, "opening fpga access_demux");

     var_Create( p_demux, "fpga-caching", 
VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
     var_Create( p_demux, "fpga-fps", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT );
     var_Get( p_demux, "fpga-fps", &val );
     p_sys->f_fps = val.f_float;
     p_sys->i_incr = 1000000 / val.f_float;
     p_sys->i_next_date = 0;

     es_format_Init( &p_sys->fmt, VIDEO_ES, VLC_FOURCC('R','V','2','4') );

     /* basic infos about the stream */
     p_sys->fmt.video.i_width = FPGA_WIDTH;
     p_sys->fmt.video.i_height = FPGA_HEIGHT;
     p_sys->fmt.video.i_bits_per_pixel = 24;
     msg_Dbg( p_demux, "screen width: %i, height: %i, depth: %i",
      p_sys->fmt.video.i_width, p_sys->fmt.video.i_height,
      p_sys->fmt.video.i_bits_per_pixel );

     /* RGB stuff to give the component order*/
     p_sys->fmt.video.i_rmask = 0x00ff0000;
     p_sys->fmt.video.i_gmask = 0x0000ff00;
     p_sys->fmt.video.i_bmask = 0x000000ff;

     p_sys->es = es_out_Add( p_demux->out, &p_sys->fmt );

     /* FPGA initialization */
     fpga_init();

     return VLC_SUCCESS;
}

/*****************************************************************************
  * Close:
 
*****************************************************************************/
static void Close( vlc_object_t *p_this )
{
     demux_t     *p_demux = (demux_t*)p_this;
     demux_sys_t *p_sys = p_demux->p_sys;
#if 0
     screen_CloseCapture( p_demux );
#endif
     fpga_release();
     close(p_sys->fd);
     free( p_sys );
}

/*****************************************************************************
  * Demux:
 
*****************************************************************************
  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 
*****************************************************************************/
static int Demux( demux_t *p_demux )
{
     int i_size, ret_read, ret_dump;
     demux_sys_t *p_sys = p_demux->p_sys;
     block_t *p_block;
     int i,j,k;
     unsigned long i_src;
     uint8_t *p_dst;

     /* 24/32 bits conversion: 24/32 = 3/4*/
     unsigned char i_width_word = (unsigned char) (FPGA_WIDTH*3/4);

     if( !p_sys->i_next_date ) p_sys->i_next_date = mdate();

     /* Frame skipping if necessary */
     while( mdate() >= p_sys->i_next_date + p_sys->i_incr )
         p_sys->i_next_date += p_sys->i_incr;
     mwait( p_sys->i_next_date );

     /* frame size in bytes, 24 bits = 3 Bytes */
     i_size = FPGA_HEIGHT * FPGA_WIDTH * 3;

     /* allocating the new block */
     msg_Dbg( p_demux, "preparing for block_New, i_size=%d", i_size);

     if( !( p_block = block_New( p_demux, i_size ) ) )
     {
         msg_Err( p_demux, "cannot get block, p_block=%p", p_block );
     }
     else
     {
         /* effectively reading data from the driver */
         msg_Dbg( p_demux, "block allocated, pbuffer=%p", 
p_block->p_buffer );
         p_dst = p_block->p_buffer;
         /* plane 0 has address 0 in the FPGA */
         i_src = 0x000000;
         /* Coord of the first pixel we want to read */
         i_src += FPGA_OFF_V * FPGA_TOTAL_WIDTH;
         msg_Dbg( p_demux, "Before the frame dump: date=%lld", mdate());

         /* i is the number of the line being read */
         /* FPGA_HEIGHT can be replaced with 1 for test purpose*/
#ifdef MASSIVE_DEBUG
         for (i = 0; i < 2; i++)
#else
         for (i = 0; i < FPGA_HEIGHT; i++)
#endif
         {
         /*  It is only possible to read max 120 words (32 bits) at once.
             So let's divide the work...
             j = amount of pixels already read (unit: 32 bits words)
             k = how much we read this time (max 120) */

             j = 0;
             while(j < i_width_word)
             {

                 k = MIN(120,(i_width_word - j));
                 msg_Dbg( p_demux, "Before dump: src=%u, dst=%p k=%d",
                  i_src + j + FPGA_OFF_H , p_dst + j, k);
#if 0
                 /* Enable to be sure that the buffer was correctly 
allocated */
                 memset(p_dst, 0, k);
                 msg_Dbg( p_demux, "memset done");
#endif
                 ret_dump=fpga_sdram_dump(i_src + j + FPGA_OFF_H, k, 
p_dst + j);


                 /* MASSIVE DEBUG: Let's display EVERYTHING we read.
                    Thank God, we have 10 seconds per frame :D
                    /!\ Will segfault if FPGA_WIDTH*3/4 is not a 
multiple of 120
                    (gruiky, i know)
                    320 (*3/4=240, 240/120=2) is OK anyway.  */
#ifdef MASSIVE_DEBUG
                 msg_Dbg( p_demux, "Data read: [00] %.2X %.2X %.2X %.2X 
%.2X %.2X %.2X %.2X %.2X %.2X", \
                     p_block->p_buffer[0 + j + (i*i_width_word)], \
                     p_block->p_buffer[1 + j + (i*i_width_word)], \
                     p_block->p_buffer[2 + j + (i*i_width_word)], \
                     p_block->p_buffer[3 + j + (i*i_width_word)], \
                     p_block->p_buffer[4 + j + (i*i_width_word)], \
                     p_block->p_buffer[5 + j + (i*i_width_word)], \
                     p_block->p_buffer[6 + j + (i*i_width_word)], \
                     p_block->p_buffer[7 + j + (i*i_width_word)], \
                     p_block->p_buffer[8 + j + (i*i_width_word)], \
                     p_block->p_buffer[9 + j + (i*i_width_word)]);
                 msg_Dbg( p_demux, "Data read: [01] %.2X %.2X %.2X %.2X 
%.2X %.2X %.2X %.2X %.2X %.2X", \
                     p_block->p_buffer[10 + j + (i*i_width_word)], \
                     p_block->p_buffer[11 + j + (i*i_width_word)], \
                     p_block->p_buffer[12 + j + (i*i_width_word)], \
                     p_block->p_buffer[13 + j + (i*i_width_word)], \
                     p_block->p_buffer[14 + j + (i*i_width_word)], \
                     p_block->p_buffer[15 + j + (i*i_width_word)], \
                     p_block->p_buffer[16 + j + (i*i_width_word)], \
                     p_block->p_buffer[17 + j + (i*i_width_word)], \
                     p_block->p_buffer[18 + j + (i*i_width_word)], \
                     p_block->p_buffer[19 + j + (i*i_width_word)]);
                 msg_Dbg( p_demux, "Data read: [02] %.2X %.2X %.2X %.2X 
%.2X %.2X %.2X %.2X %.2X %.2X", \
                     p_block->p_buffer[20 + j + (i*i_width_word)], \
                     p_block->p_buffer[21 + j + (i*i_width_word)], \
                     p_block->p_buffer[22 + j + (i*i_width_word)], \
                     p_block->p_buffer[23 + j + (i*i_width_word)], \
                     p_block->p_buffer[24 + j + (i*i_width_word)], \
                     p_block->p_buffer[25 + j + (i*i_width_word)], \
                     p_block->p_buffer[26 + j + (i*i_width_word)], \
                     p_block->p_buffer[27 + j + (i*i_width_word)], \
                     p_block->p_buffer[28 + j + (i*i_width_word)], \
                     p_block->p_buffer[29 + j + (i*i_width_word)]);
                 msg_Dbg( p_demux, "Data read: [03] %.2X %.2X %.2X %.2X 
%.2X %.2X %.2X %.2X %.2X %.2X", \
                     p_block->p_buffer[30 + j + (i*i_width_word)], \
                     p_block->p_buffer[31 + j + (i*i_width_word)], \
                     p_block->p_buffer[32 + j + (i*i_width_word)], \
                     p_block->p_buffer[33 + j + (i*i_width_word)], \
                     p_block->p_buffer[34 + j + (i*i_width_word)], \
                     p_block->p_buffer[35 + j + (i*i_width_word)], \
                     p_block->p_buffer[36 + j + (i*i_width_word)], \
                     p_block->p_buffer[37 + j + (i*i_width_word)], \
                     p_block->p_buffer[38 + j + (i*i_width_word)], \
                     p_block->p_buffer[39 + j + (i*i_width_word)]);
                 msg_Dbg( p_demux, "Data read: [04] %.2X %.2X %.2X %.2X 
%.2X %.2X %.2X %.2X %.2X %.2X", \
                     p_block->p_buffer[40 + j + (i*i_width_word)], \
                     p_block->p_buffer[41 + j + (i*i_width_word)], \
                     p_block->p_buffer[42 + j + (i*i_width_word)], \
                     p_block->p_buffer[43 + j + (i*i_width_word)], \
                     p_block->p_buffer[44 + j + (i*i_width_word)], \
                     p_block->p_buffer[45 + j + (i*i_width_word)], \
                     p_block->p_buffer[46 + j + (i*i_width_word)], \
                     p_block->p_buffer[47 + j + (i*i_width_word)], \
                     p_block->p_buffer[48 + j + (i*i_width_word)], \
                     p_block->p_buffer[49 + j + (i*i_width_word)]);
                 msg_Dbg( p_demux, "Data read: [05] %.2X %.2X %.2X %.2X 
%.2X %.2X %.2X %.2X %.2X %.2X", \
                     p_block->p_buffer[50 + j + (i*i_width_word)], \
                     p_block->p_buffer[51 + j + (i*i_width_word)], \
                     p_block->p_buffer[52 + j + (i*i_width_word)], \
                     p_block->p_buffer[53 + j + (i*i_width_word)], \
                     p_block->p_buffer[54 + j + (i*i_width_word)], \
                     p_block->p_buffer[55 + j + (i*i_width_word)], \
                     p_block->p_buffer[56 + j + (i*i_width_word)], \
                     p_block->p_buffer[57 + j + (i*i_width_word)], \
                     p_block->p_buffer[58 + j + (i*i_width_word)], \
                     p_block->p_buffer[59 + j + (i*i_width_word)]);
                 msg_Dbg( p_demux, "Data read: [06] %.2X %.2X %.2X %.2X 
%.2X %.2X %.2X %.2X %.2X %.2X", \
                     p_block->p_buffer[60 + j + (i*i_width_word)], \
                     p_block->p_buffer[61 + j + (i*i_width_word)], \
                     p_block->p_buffer[62 + j + (i*i_width_word)], \
                     p_block->p_buffer[63 + j + (i*i_width_word)], \
                     p_block->p_buffer[64 + j + (i*i_width_word)], \
                     p_block->p_buffer[65 + j + (i*i_width_word)], \
                     p_block->p_buffer[66 + j + (i*i_width_word)], \
                     p_block->p_buffer[67 + j + (i*i_width_word)], \
                     p_block->p_buffer[68 + j + (i*i_width_word)], \
                     p_block->p_buffer[69 + j + (i*i_width_word)]);
                 msg_Dbg( p_demux, "Data read: [07] %.2X %.2X %.2X %.2X 
%.2X %.2X %.2X %.2X %.2X %.2X", \
                     p_block->p_buffer[70 + j + (i*i_width_word)], \
                     p_block->p_buffer[71 + j + (i*i_width_word)], \
                     p_block->p_buffer[72 + j + (i*i_width_word)], \
                     p_block->p_buffer[73 + j + (i*i_width_word)], \
                     p_block->p_buffer[74 + j + (i*i_width_word)], \
                     p_block->p_buffer[75 + j + (i*i_width_word)], \
                     p_block->p_buffer[76 + j + (i*i_width_word)], \
                     p_block->p_buffer[77 + j + (i*i_width_word)], \
                     p_block->p_buffer[78 + j + (i*i_width_word)], \
                     p_block->p_buffer[79 + j + (i*i_width_word)]);
                 msg_Dbg( p_demux, "Data read: [08] %.2X %.2X %.2X %.2X 
%.2X %.2X %.2X %.2X %.2X %.2X", \
                     p_block->p_buffer[80 + j + (i*i_width_word)], \
                     p_block->p_buffer[81 + j + (i*i_width_word)], \
                     p_block->p_buffer[82 + j + (i*i_width_word)], \
                     p_block->p_buffer[83 + j + (i*i_width_word)], \
                     p_block->p_buffer[84 + j + (i*i_width_word)], \
                     p_block->p_buffer[85 + j + (i*i_width_word)], \
                     p_block->p_buffer[86 + j + (i*i_width_word)], \
                     p_block->p_buffer[87 + j + (i*i_width_word)], \
                     p_block->p_buffer[88 + j + (i*i_width_word)], \
                     p_block->p_buffer[89 + j + (i*i_width_word)]);
                 msg_Dbg( p_demux, "Data read: [09] %.2X %.2X %.2X %.2X 
%.2X %.2X %.2X %.2X %.2X %.2X", \
                     p_block->p_buffer[90 + j + (i*i_width_word)], \
                     p_block->p_buffer[91 + j + (i*i_width_word)], \
                     p_block->p_buffer[92 + j + (i*i_width_word)], \
                     p_block->p_buffer[93 + j + (i*i_width_word)], \
                     p_block->p_buffer[94 + j + (i*i_width_word)], \
                     p_block->p_buffer[95 + j + (i*i_width_word)], \
                     p_block->p_buffer[96 + j + (i*i_width_word)], \
                     p_block->p_buffer[97 + j + (i*i_width_word)], \
                     p_block->p_buffer[98 + j + (i*i_width_word)], \
                     p_block->p_buffer[99 + j + (i*i_width_word)]);
                 msg_Dbg( p_demux, "Data read: [10] %.2X %.2X %.2X %.2X 
%.2X %.2X %.2X %.2X %.2X %.2X", \
                     p_block->p_buffer[100 + j + (i*i_width_word)], \
                     p_block->p_buffer[101 + j + (i*i_width_word)], \
                     p_block->p_buffer[102 + j + (i*i_width_word)], \
                     p_block->p_buffer[103 + j + (i*i_width_word)], \
                     p_block->p_buffer[104 + j + (i*i_width_word)], \
                     p_block->p_buffer[105 + j + (i*i_width_word)], \
                     p_block->p_buffer[106 + j + (i*i_width_word)], \
                     p_block->p_buffer[107 + j + (i*i_width_word)], \
                     p_block->p_buffer[108 + j + (i*i_width_word)], \
                     p_block->p_buffer[109 + j + (i*i_width_word)]);
                 msg_Dbg( p_demux, "Data read: [11] %.2X %.2X %.2X %.2X 
%.2X %.2X %.2X %.2X %.2X %.2X", \
                     p_block->p_buffer[110 + j + (i*i_width_word)], \
                     p_block->p_buffer[111 + j + (i*i_width_word)], \
                     p_block->p_buffer[112 + j + (i*i_width_word)], \
                     p_block->p_buffer[113 + j + (i*i_width_word)], \
                     p_block->p_buffer[114 + j + (i*i_width_word)], \
                     p_block->p_buffer[115 + j + (i*i_width_word)], \
                     p_block->p_buffer[116 + j + (i*i_width_word)], \
                     p_block->p_buffer[117 + j + (i*i_width_word)], \
                     p_block->p_buffer[118 + j + (i*i_width_word)], \
                     p_block->p_buffer[119 + j + (i*i_width_word)]);


#endif
                 /* End of MASSIVE DEBUG */

                 j += k;

                 if (ret_dump != 0)
                 {
                     msg_Err( p_demux, "Error in fpga_sdram_dump. 
returned: %d",
                      ret_dump );
                 }

             }

             i_src += FPGA_TOTAL_WIDTH; /* next line */
             p_dst += (unsigned long) i_width_word; /* = 3/4*FPGA_WIDTH */
         }
         msg_Dbg( p_demux, "After the frame dump: date=%lld", mdate() );

     }
     if( !p_block )
     {
         /* allocation failed */
         p_sys->i_next_date += p_sys->i_incr;
         return 1;
     }
     p_block->i_dts = p_block->i_pts = p_sys->i_next_date;
     msg_Dbg( p_demux, "Finished. p_block=%p, date=%lld", p_block, 
p_block->i_dts );

     es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts );
     es_out_Send( p_demux->out, p_sys->es, p_block );

     p_sys->i_next_date += p_sys->i_incr;

     return 1;
}

/*****************************************************************************
  * Control:
 
*****************************************************************************/
static int Control( demux_t *p_demux, int i_query, va_list args )
{
     vlc_bool_t *pb;
     int64_t *pi64;

     switch( i_query )
     {
         /* Special for access_demux */
         case DEMUX_CAN_PAUSE:
         case DEMUX_CAN_CONTROL_PACE:
             /* TODO */
             pb = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
             *pb = VLC_FALSE;
             return VLC_SUCCESS;

         case DEMUX_GET_PTS_DELAY:
             pi64 = (int64_t*)va_arg( args, int64_t * );
             *pi64 = (int64_t)var_GetInteger( p_demux, "fpga-caching" ) 
*1000;
             return VLC_SUCCESS;

         /* TODO implement others */
         default:
             return VLC_EGENERIC;
     }
}

-- 
This is the vlc-devel mailing-list, see http://www.videolan.org/vlc/
To unsubscribe, please read http://developers.videolan.org/lists.html



More information about the vlc-devel mailing list