Initial import of MPlayer SVN rev 28382 and FFmpeg SVN rev 16846.
[vaapi:mplayer.git] / libmpdemux / demux_mf.c
1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <unistd.h>
8
9 #include "config.h"
10 #include "mp_msg.h"
11 #include "help_mp.h"
12
13 #include "stream/stream.h"
14 #include "demuxer.h"
15 #include "stheader.h"
16 #include "mf.h"
17
18 static void demux_seek_mf(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){
19   mf_t * mf = (mf_t *)demuxer->priv;
20   sh_video_t   * sh_video = demuxer->video->sh;
21   int newpos = (flags & SEEK_ABSOLUTE)?0:mf->curr_frame - 1;
22   
23   if ( flags & SEEK_FACTOR ) newpos+=rel_seek_secs*(mf->nr_of_files - 1);
24    else newpos+=rel_seek_secs * sh_video->fps;
25   if ( newpos < 0 ) newpos=0;
26   if( newpos >= mf->nr_of_files) newpos=mf->nr_of_files - 1;
27   mf->curr_frame=newpos;
28 }
29
30 // return value:
31 //     0 = EOF or no stream found
32 //     1 = successfully read a packet
33 static int demux_mf_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds){
34   mf_t         * mf;
35   struct stat    fs;
36   FILE         * f;
37
38   mf=(mf_t*)demuxer->priv;
39   if ( mf->curr_frame >= mf->nr_of_files ) return 0;
40
41   stat( mf->names[mf->curr_frame],&fs );
42 //  printf( "[demux_mf] frame: %d (%s,%d)\n",mf->curr_frame,mf->names[mf->curr_frame],fs.st_size );
43
44   if ( !( f=fopen( mf->names[mf->curr_frame],"rb" ) ) ) return 0;
45   {
46    sh_video_t     * sh_video = demuxer->video->sh;
47    demux_packet_t * dp = new_demux_packet( fs.st_size );
48    if ( !fread( dp->buffer,fs.st_size,1,f ) ) return 0;
49    dp->pts=mf->curr_frame / sh_video->fps;
50    dp->pos=mf->curr_frame;
51    dp->flags=0;
52    // append packet to DS stream:
53    ds_add_packet( demuxer->video,dp );
54   }
55   fclose( f );
56
57   mf->curr_frame++;
58   return 1;
59 }
60
61 static const struct {
62   const char *type;
63   uint32_t format;
64 } type2format[] = {
65   { "bmp",  mmioFOURCC('b', 'm', 'p', ' ') },
66   { "jpeg", mmioFOURCC('I', 'J', 'P', 'G') },
67   { "jpg",  mmioFOURCC('I', 'J', 'P', 'G') },
68   { "pcx",  mmioFOURCC('p', 'c', 'x', ' ') },
69   { "png",  mmioFOURCC('M', 'P', 'N', 'G') },
70   { "ptx",  mmioFOURCC('p', 't', 'x', ' ') },
71   { "tga",  mmioFOURCC('M', 'T', 'G', 'A') },
72   { "tif",  mmioFOURCC('t', 'i', 'f', 'f') },
73   { "sgi",  mmioFOURCC('S', 'G', 'I', '1') },
74   { "sun",  mmioFOURCC('s', 'u', 'n', ' ') },
75   { "ras",  mmioFOURCC('s', 'u', 'n', ' ') },
76   { "ra",  mmioFOURCC('s', 'u', 'n', ' ') },
77   { "im1",  mmioFOURCC('s', 'u', 'n', ' ') },
78   { "im8",  mmioFOURCC('s', 'u', 'n', ' ') },
79   { "im24",  mmioFOURCC('s', 'u', 'n', ' ') },
80   { "sunras",  mmioFOURCC('s', 'u', 'n', ' ') },
81   { NULL,   0 }
82 };
83
84 static demuxer_t* demux_open_mf(demuxer_t* demuxer){
85   sh_video_t   *sh_video = NULL;
86   mf_t         *mf = NULL;
87   int i;
88   
89   if(!demuxer->stream->url) return NULL;
90   if(strncmp(demuxer->stream->url, "mf://", 5)) return NULL;
91
92
93   mf=open_mf(demuxer->stream->url + 5);
94   if(!mf) return NULL;
95
96   if(!mf_type){
97     char* p=strrchr(mf->names[0],'.');
98     if(!p){
99       mp_msg(MSGT_DEMUX, MSGL_INFO, "[demux_mf] file type was not set! (try -mf type=xxx)\n" );
100       free( mf ); return NULL;
101     }
102     mf_type=strdup(p+1);
103     mp_msg(MSGT_DEMUX, MSGL_INFO, "[demux_mf] file type was not set! trying 'type=%s'...\n", mf_type);
104   }
105
106   mf->curr_frame=0;
107
108   demuxer->movi_start = 0;
109   demuxer->movi_end = mf->nr_of_files - 1;
110
111   // create a new video stream header
112   sh_video = new_sh_video(demuxer, 0);
113   // make sure the demuxer knows about the new video stream header
114   // (even though new_sh_video() ought to take care of it)
115   demuxer->video->sh = sh_video;
116
117   // make sure that the video demuxer stream header knows about its
118   // parent video demuxer stream (this is getting wacky), or else
119   // video_read_properties() will choke
120   sh_video->ds = demuxer->video;
121   
122   for (i = 0; type2format[i].type; i++)
123     if (strcasecmp(mf_type, type2format[i].type) == 0)
124       break;
125   if (!type2format[i].type) {
126     mp_msg(MSGT_DEMUX, MSGL_INFO, "[demux_mf] unknown input file type.\n" );
127     free(mf);
128     return NULL;
129   }
130   sh_video->format = type2format[i].format;
131
132   sh_video->disp_w = mf_w;
133   sh_video->disp_h = mf_h;
134   sh_video->fps = mf_fps;
135   sh_video->frametime = 1 / sh_video->fps;
136
137   // emulate BITMAPINFOHEADER:
138   sh_video->bih=malloc(sizeof(BITMAPINFOHEADER));
139   memset(sh_video->bih,0,sizeof(BITMAPINFOHEADER));
140   sh_video->bih->biSize=40;
141   sh_video->bih->biWidth = mf_w;
142   sh_video->bih->biHeight = mf_h;
143   sh_video->bih->biPlanes=1;
144   sh_video->bih->biBitCount=24;
145   sh_video->bih->biCompression=sh_video->format;
146   sh_video->bih->biSizeImage=sh_video->bih->biWidth*sh_video->bih->biHeight*3;
147
148   /* disable seeking */
149 //  demuxer->seekable = 0;
150
151   demuxer->priv=(void*)mf;
152
153   return demuxer;
154 }
155
156 static void demux_close_mf(demuxer_t* demuxer) {
157   mf_t *mf = demuxer->priv;
158
159   if(!mf)
160     return;
161   free(mf);  
162 }
163
164 static int demux_control_mf(demuxer_t *demuxer, int cmd, void *arg) {
165   mf_t *mf = (mf_t *)demuxer->priv;
166   sh_video_t *sh_video = demuxer->video->sh;
167
168   switch(cmd) {
169     case DEMUXER_CTRL_GET_TIME_LENGTH:
170       *((double *)arg) = (double)mf->nr_of_files / sh_video->fps;
171       return DEMUXER_CTRL_OK;
172
173     case DEMUXER_CTRL_GET_PERCENT_POS:
174       if (mf->nr_of_files <= 1)
175         return DEMUXER_CTRL_DONTKNOW;
176       *((int *)arg) = 100 * mf->curr_frame / (mf->nr_of_files - 1);
177       return DEMUXER_CTRL_OK;
178
179     default:
180       return DEMUXER_CTRL_NOTIMPL;
181   }
182 }
183
184 const demuxer_desc_t demuxer_desc_mf = {
185   "mf demuxer",
186   "mf",
187   "MF",
188   "?",
189   "multiframe?, pictures demuxer",
190   DEMUXER_TYPE_MF,
191   0, // no autodetect
192   NULL,
193   demux_mf_fill_buffer,
194   demux_open_mf,
195   demux_close_mf,
196   demux_seek_mf,
197   demux_control_mf
198 };