~ubuntu-branches/ubuntu/hoary/kdemultimedia/hoary

« back to all changes in this revision

Viewing changes to mpeglib/lib/decoder/decoderPlugin.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Martin Schulze
  • Date: 2003-01-22 15:00:51 UTC
  • Revision ID: james.westby@ubuntu.com-20030122150051-uihwkdoxf15mi1tn
Tags: upstream-2.2.2
ImportĀ upstreamĀ versionĀ 2.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  base class for the player plugin
 
3
  Copyright (C) 1999  Martin Vogt
 
4
 
 
5
  This program is free software; you can redistribute it and/or modify
 
6
  it under the terms of the GNU Library General Public License as published by
 
7
  the Free Software Foundation.
 
8
 
 
9
  For more information look at the file COPYRIGHT in this package
 
10
 
 
11
 */
 
12
 
 
13
#include "decoderPlugin.h"
 
14
 
 
15
 
 
16
 
 
17
 
 
18
static void *playerThread(void *arg){
 
19
  ((DecoderPlugin*)arg)->idleThread();
 
20
  return NULL;
 
21
}   
 
22
 
 
23
static int instanceCnt=0;
 
24
 
 
25
DecoderPlugin::DecoderPlugin(){
 
26
  input=NULL;
 
27
  output=NULL;
 
28
  commandPipe=new CommandPipe();
 
29
  threadCommand=new Command(_COMMAND_NONE);
 
30
  abs_thread_cond_init(&streamStateCond);
 
31
  abs_thread_mutex_init(&streamStateMut);
 
32
  abs_thread_mutex_init(&shutdownMut);
 
33
 
 
34
  lCreatorLoop=true;
 
35
  lDecoderLoop=false;
 
36
  linDecoderLoop=false;
 
37
  streamState=_STREAM_STATE_EOF;
 
38
  lDecode=false;
 
39
  lhasLength=false;
 
40
  // this default is necessary. if you have a blocking
 
41
  // device and we start automatic the thread
 
42
  // may block on it and all commands (including play)
 
43
  // blocks everything
 
44
  // *you should not use autoplay*
 
45
  lAutoPlay=false;
 
46
 
 
47
  pluginInfo=new PluginInfo();
 
48
  runCheck_Counter=0;
 
49
  decode_loopCounter=0;
 
50
  instance=instanceCnt;
 
51
  instanceCnt++;
 
52
  abs_thread_create(&tr,playerThread,this);
 
53
 
 
54
  // we send a ping. because this signal is synchron
 
55
  // we block until the thread is started and
 
56
  // has read the ping singnal
 
57
  Command cmd(_COMMAND_PING);
 
58
  insertSyncCommand(&cmd);
 
59
 
 
60
 
 
61
}
 
62
 
 
63
 
 
64
DecoderPlugin::~DecoderPlugin(){
 
65
  void* ret;
 
66
  lCreatorLoop=false;
 
67
  Command cmd(_COMMAND_CLOSE);
 
68
  insertAsyncCommand(&cmd);
 
69
 
 
70
  abs_thread_join(tr,&ret);
 
71
 
 
72
  abs_thread_cond_destroy(&streamStateCond);
 
73
  abs_thread_mutex_destroy(&streamStateMut);
 
74
  abs_thread_mutex_destroy(&shutdownMut);
 
75
  
 
76
  delete commandPipe;
 
77
  delete threadCommand;
 
78
  delete pluginInfo;
 
79
}
 
80
 
 
81
  
 
82
void DecoderPlugin::close(){
 
83
  // from here we can only walk to init or eof
 
84
  // in both cases we sometimes catch out decoderMut :-)
 
85
  Command cmd(_COMMAND_CLOSE);
 
86
  insertAsyncCommand(&cmd);
 
87
  shutdownLock();
 
88
  if (input != NULL) {
 
89
    input->close();
 
90
  }
 
91
  shutdownUnlock();
 
92
  insertSyncCommand(&cmd);
 
93
  waitForStreamState(_STREAM_STATE_EOF);
 
94
  input=NULL;
 
95
}
 
96
 
 
97
 
 
98
void DecoderPlugin::pause() {
 
99
  Command cmd(_COMMAND_PAUSE);
 
100
  insertSyncCommand(&cmd);
 
101
}
 
102
 
 
103
  
 
104
 
 
105
 
 
106
int DecoderPlugin::play() {
 
107
  Command cmd(_COMMAND_PLAY);
 
108
  insertSyncCommand(&cmd);
 
109
 
 
110
  return true;
 
111
}
 
112
 
 
113
int DecoderPlugin::seek(int second) {
 
114
  Command cmd(_COMMAND_SEEK,second);
 
115
  insertSyncCommand(&cmd);
 
116
 
 
117
  return true;
 
118
}
 
119
 
 
120
void DecoderPlugin::insertAsyncCommand(Command* cmd) {
 
121
  commandPipe->sendCommandNoWait(*cmd);
 
122
}
 
123
 
 
124
void DecoderPlugin::insertSyncCommand(Command* cmd) {
 
125
  commandPipe->sendCommand(*cmd);
 
126
}
 
127
 
 
128
 
 
129
void DecoderPlugin::shutdownLock() {
 
130
  abs_thread_mutex_lock(&shutdownMut);
 
131
}
 
132
 
 
133
 
 
134
void DecoderPlugin::shutdownUnlock() {
 
135
  abs_thread_mutex_unlock(&shutdownMut);
 
136
}
 
137
 
 
138
int DecoderPlugin::getTime(int lCurrent) {
 
139
  int secLen=getTotalLength();
 
140
  
 
141
  if (lCurrent==false) {
 
142
    return secLen;
 
143
  }
 
144
  shutdownLock();
 
145
  int byteLen=1;
 
146
  int pos=1;
 
147
  if (input != NULL) {
 
148
    pos=input->getBytePosition()+1;
 
149
    byteLen=input->getByteLength()+1;
 
150
  }
 
151
  int back=(int)(((double)pos/(double)byteLen) * (double)secLen);
 
152
  shutdownUnlock();
 
153
  return back;
 
154
 
 
155
}
 
156
 
 
157
int DecoderPlugin::getTotalLength() {
 
158
  cout << "plugin does not support total playtime reporting"<<endl;
 
159
  return 0;
 
160
}
 
161
 
 
162
int DecoderPlugin::seek_impl(int) {
 
163
  cout << "plugin does not support seek"<<endl;
 
164
  return false;
 
165
}
 
166
 
 
167
 
 
168
 
 
169
 
 
170
void DecoderPlugin::setOutputPlugin(OutputStream* output) {
 
171
  this->output=output;
 
172
}
 
173
 
 
174
 
 
175
int DecoderPlugin::setInputPlugin(InputStream* input) {
 
176
  this->input=input;
 
177
 
 
178
  if (!input) {
 
179
    cout << "input is NULL"<<endl;
 
180
    exit(0);
 
181
  }
 
182
  pluginInfo->setUrl(input->getUrl());
 
183
 
 
184
 
 
185
  // the command is synchron we block until the
 
186
  // thread has read it
 
187
  Command cmd(_COMMAND_START);
 
188
  insertSyncCommand(&cmd);
 
189
 
 
190
 
 
191
  // now that we know he has read it, we send another
 
192
  // command, this is only read if the thread is in the
 
193
  // decode_loop, and we then know that the streamState 
 
194
  // is FIRST_INIT
 
195
  Command ping(_COMMAND_PING);
 
196
  insertSyncCommand(&ping);
 
197
  
 
198
 
 
199
  if (lAutoPlay) {
 
200
    play();
 
201
  }
 
202
  return true;
 
203
}
 
204
 
 
205
 
 
206
void DecoderPlugin::config(const char* key,const char* value,void* ){
 
207
  if (strcmp(key,"-y")==0) {
 
208
    if (strcmp(value,"on")==0) {
 
209
      lAutoPlay=true;
 
210
    } else {
 
211
      lAutoPlay=false;
 
212
    }
 
213
  }
 
214
  
 
215
}
 
216
 
 
217
/**
 
218
   during shutdown the streamState is undefined until
 
219
   the thread has left the decode_loop().
 
220
   Make sure we wait for this.
 
221
*/
 
222
int DecoderPlugin::getStreamState() {
 
223
  shutdownLock();
 
224
  int back=streamState;
 
225
  shutdownUnlock();
 
226
  return back;
 
227
}
 
228
 
 
229
 
 
230
int DecoderPlugin::waitForStreamState(int state) {
 
231
  int back;
 
232
  abs_thread_mutex_lock(&streamStateMut);
 
233
  while ((streamState & state) == false) {
 
234
    abs_thread_cond_wait(&streamStateCond,&streamStateMut);
 
235
  }
 
236
  back=streamState;
 
237
  abs_thread_mutex_unlock(&streamStateMut);
 
238
  return back;
 
239
}
 
240
 
 
241
 
 
242
void DecoderPlugin::setStreamState(int streamState) {
 
243
  abs_thread_mutex_lock(&streamStateMut);
 
244
  this->streamState=streamState;
 
245
  abs_thread_cond_signal(&streamStateCond);
 
246
  abs_thread_mutex_unlock(&streamStateMut);
 
247
}
 
248
 
 
249
 
 
250
void DecoderPlugin::decoder_loop() {
 
251
  cout << "direct call decoder loop->plugin not found ???"<<endl;
 
252
  TimeWrapper::usleep(100000);
 
253
}
 
254
 
 
255
 
 
256
void* DecoderPlugin::idleThread() {
 
257
 
 
258
  while(lCreatorLoop) {
 
259
    linDecoderLoop=true;
 
260
    commandPipe->waitForCommand();
 
261
    commandPipe->hasCommand(threadCommand);
 
262
    int id=threadCommand->getID();
 
263
    switch(id) {
 
264
    case _COMMAND_START:
 
265
      lDecoderLoop=true;
 
266
      break;
 
267
    case _COMMAND_PING:
 
268
      break;
 
269
      /*
 
270
        default:
 
271
        threadCommand->print("ignoring non START command in idleThread");
 
272
      */
 
273
    }
 
274
    
 
275
 
 
276
    if (lDecoderLoop) {
 
277
      setStreamState(_STREAM_STATE_FIRST_INIT);
 
278
      linDecoderLoop=false;
 
279
      decode_loopCounter++;
 
280
      runCheck_Counter=0;
 
281
      shutdownLock();
 
282
      decoder_loop();
 
283
      lDecode=false;
 
284
      lDecoderLoop=false;
 
285
      lhasLength=false;     
 
286
      setStreamState(_STREAM_STATE_EOF);
 
287
      shutdownUnlock();
 
288
    } 
 
289
  }
 
290
  return NULL;
 
291
}
 
292
 
 
293
 
 
294
PluginInfo* DecoderPlugin::getPluginInfo() {
 
295
  return pluginInfo;
 
296
}
 
297
 
 
298
 
 
299
int DecoderPlugin::runCheck() {
 
300
  if (runCheck_Counter==0) {
 
301
    shutdownUnlock();
 
302
  }
 
303
  runCheck_Counter++;
 
304
  while (lDecoderLoop && lCreatorLoop) {
 
305
 
 
306
    // if we have an eof this always leads to 
 
307
    // a shutdown of the decode_loop thread
 
308
    // it has more priority than the resyn request
 
309
    if (input->eof()) {
 
310
      setStreamState(_STREAM_STATE_WAIT_FOR_END);
 
311
    }  
 
312
    //
 
313
    // if we are in _STREAM_STATE_RESYNC_COMMIT
 
314
    // we only leave it if command is _COMMAND_RESYNC_END  
 
315
    // (or close)
 
316
 
 
317
    //
 
318
    // check user commands
 
319
    // 
 
320
    if (lDecode==false) {
 
321
      commandPipe->waitForCommand();
 
322
      commandPipe->hasCommand(threadCommand);
 
323
    } else {
 
324
      if (commandPipe->hasCommand(threadCommand)==false) {
 
325
        // no commands and lDecode=true
 
326
        return true;
 
327
      }
 
328
    }
 
329
 
 
330
    // here we forward the command to a special
 
331
    // method who can handle everything
 
332
    // (the default method should work fine);
 
333
    int nextCheck= processThreadCommand(threadCommand);
 
334
    switch(nextCheck) {
 
335
    case _RUN_CHECK_CONTINUE:
 
336
      break;
 
337
    case _RUN_CHECK_FALSE:
 
338
      return false;
 
339
    case _RUN_CHECK_TRUE:
 
340
      return true;
 
341
    default:
 
342
      cout << "unknown runCheck return command"<<endl;
 
343
      exit(0);
 
344
    }
 
345
        
 
346
 
 
347
  }
 
348
 
 
349
  shutdownLock();
 
350
  return false;
 
351
}
 
352
 
 
353
int DecoderPlugin::processThreadCommand(Command* command) {
 
354
 
 
355
  
 
356
  int id=command->getID();
 
357
  int intArg;
 
358
 
 
359
  //
 
360
  // if we are in _STREAM_STATE_RESYNC_COMMIT
 
361
  // we only leave it if command is _COMMAND_RESYNC_END  
 
362
  //
 
363
  if (streamState==_STREAM_STATE_RESYNC_COMMIT) {
 
364
    switch(id) {
 
365
    case _COMMAND_RESYNC_END:
 
366
      setStreamState(_STREAM_STATE_INIT);
 
367
      input->clear();
 
368
      break; 
 
369
    case _COMMAND_CLOSE:
 
370
      //
 
371
      // we return false so that the plugin clears
 
372
      // all its allocated classes
 
373
      // its a _must_ !!
 
374
      // in the next call we exit immediately
 
375
      return _RUN_CHECK_FALSE;
 
376
 
 
377
      /*  
 
378
    default:
 
379
      command->print("ignore command in _STREAM_STATE_RESYNC_COMMIT");
 
380
      */
 
381
    }
 
382
    return _RUN_CHECK_CONTINUE;
 
383
  }
 
384
 
 
385
 
 
386
  switch(id) {
 
387
  case _COMMAND_NONE:
 
388
    break;
 
389
  case _COMMAND_PING:
 
390
    break;
 
391
  case _COMMAND_PAUSE:
 
392
    lDecode=false;
 
393
    break;
 
394
  case _COMMAND_PLAY:
 
395
    lDecode=true;
 
396
    break;
 
397
  case _COMMAND_SEEK: {
 
398
    if (streamState==_STREAM_STATE_FIRST_INIT) {
 
399
      command->print("ignore command seek in _STREAM_STATE_FIRST_INIT");
 
400
    } else {
 
401
      intArg=command->getIntArg();
 
402
      seek_impl(intArg);
 
403
    }
 
404
    break;
 
405
  }
 
406
  case _COMMAND_CLOSE:
 
407
    //
 
408
    // we return false so that the plugin clears
 
409
    // all its allocated classes
 
410
    // its a _must_ !!
 
411
    // in the next call we exit immediately
 
412
    return _RUN_CHECK_FALSE;
 
413
  case _COMMAND_RESYNC_START:
 
414
    setStreamState(_STREAM_STATE_RESYNC_COMMIT);
 
415
    input->clear();
 
416
    break;
 
417
    /*
 
418
  default:
 
419
    cout << "unknown command id in Command::print"<<endl;
 
420
    */
 
421
  }
 
422
  return _RUN_CHECK_CONTINUE;
 
423
}
 
424
 
 
425