Skip to content

Commit 0c4105b

Browse files
committed
First parallel version.
Known bugs: No longer gracefully handles files with long dependencies (dies with OutOfFrames) Needs optimization and benchmarks
1 parent f315ab8 commit 0c4105b

11 files changed

+505
-34
lines changed

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
source = ahab.cpp es.cpp mpegheader.cpp bitreader.cpp startfinder.cpp sequence.cpp extensions.cpp exceptions.cpp picture.cpp slice.cpp file.cpp ogl.cpp slicedecode.cpp idct_mmx.cpp motion_comp_mmx.cpp framebuffer.cpp opq.cpp displayop.cpp controller.cpp displayopq.cpp decoder.cpp decoderop.cpp decoderopq.cpp xeventloop.cpp
2-
objects = es.o mpegheader.o bitreader.o startfinder.o sequence.o extensions.o exceptions.o picture.o slice.o file.o ogl.o slicedecode.o idct_mmx.o motion_comp_mmx.o framebuffer.o opq.o displayop.o controller.o displayopq.o decoder.o decoderop.o decoderopq.o xeventloop.o
1+
source = ahab.cpp es.cpp mpegheader.cpp bitreader.cpp startfinder.cpp sequence.cpp extensions.cpp exceptions.cpp picture.cpp slice.cpp file.cpp ogl.cpp slicedecode.cpp idct_mmx.cpp motion_comp_mmx.cpp framebuffer.cpp opq.cpp displayop.cpp controller.cpp displayopq.cpp decoder.cpp decoderop.cpp decoderopq.cpp xeventloop.cpp slicerow.cpp
2+
objects = es.o mpegheader.o bitreader.o startfinder.o sequence.o extensions.o exceptions.o picture.o slice.o file.o ogl.o slicedecode.o idct_mmx.o motion_comp_mmx.o framebuffer.o opq.o displayop.o controller.o displayopq.o decoder.o decoderop.o decoderopq.o xeventloop.o slicerow.o
33
executables = ahab
44

55
CPP = g++

controller.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Controller::Controller( uint s_num_frames )
1818
opq( 0 ),
1919
num_frames( s_num_frames )
2020
{
21+
unixassert( pthread_mutex_init( &mutex, NULL ) );
2122
pthread_create( &thread_handle, NULL, thread_helper, this );
2223
}
2324

@@ -90,4 +91,5 @@ Controller::~Controller()
9091
}
9192
}
9293
unixassert( pthread_join( thread_handle, NULL ) );
94+
unixassert( pthread_mutex_destroy( &mutex ) );
9395
}

decoder.cpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ Decoder::~Decoder() {}
3333
void Decoder::decode_and_display( void )
3434
{
3535
Picture *pic = stream->get_picture_displayed( state.current_picture );
36-
pic->lock_and_decodeall();
36+
pic->start_parallel_decode( true );
37+
pic->get_framehandle()->wait_rendered();
3738
DrawAndUnlockFrame *op = new DrawAndUnlockFrame( pic->get_framehandle() );
3839
state.oglq->flush_type( op );
3940
state.oglq->enqueue( op );
@@ -54,6 +55,16 @@ void Decoder::loop( void )
5455

5556
if ( state.current_picture != picture_displayed ) {
5657
decode_and_display();
58+
59+
/* Also decode a window around current location
60+
for ( int i = state.current_picture - 4;
61+
i < state.current_picture + 4;
62+
i++ ) {
63+
if ( i >= 0 && i < stream->get_num_pictures() && i != state.current_picture ) {
64+
stream->get_picture_displayed( i )->start_parallel_decode( false );
65+
}
66+
}
67+
*/
5768
}
5869

5970
picture_displayed = state.current_picture;

detachattr.hpp

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef DETACH_ATTR_HPP
2+
#define DETACH_ATTR_HPP
3+
4+
#include <pthread.h>
5+
6+
#include "exceptions.hpp"
7+
8+
class DetachAttributes {
9+
public:
10+
pthread_attr_t attr;
11+
12+
DetachAttributes( int detachstate ) {
13+
unixassert( pthread_attr_init( &attr ) );
14+
unixassert( pthread_attr_setdetachstate( &attr, detachstate ) );
15+
}
16+
};
17+
18+
static DetachAttributes DetachedThread( PTHREAD_CREATE_DETACHED );
19+
20+
#endif

es.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ ES::ES( File *s_file, void (*progress)( off_t size, off_t location ) )
5959
hdr->link();
6060
}
6161

62-
pool = new BufferPool( pool_slots, 16 * seq->get_mb_width(),
63-
16 * seq->get_mb_height() );
62+
pool = new BufferPool( pool_slots, seq->get_mb_width(),
63+
seq->get_mb_height() );
6464

6565
/* Figure out the display order of each picture and link each
6666
from the coded_picture and displayed_picture arrays */

framebuffer.cpp

+62-9
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,15 @@ void FrameQueue::remove_specific( Frame *frame )
6464
frame->prev = frame->next = NULL;
6565
}
6666

67-
BufferPool::BufferPool( uint s_num_frames, uint s_width, uint s_height )
67+
BufferPool::BufferPool( uint s_num_frames, uint mb_width, uint mb_height )
6868
{
6969
num_frames = s_num_frames;
70-
width = s_width;
71-
height = s_height;
70+
width = 16 * mb_width;
71+
height = 16 * mb_height;
7272

7373
frames = new Frame *[ num_frames ];
7474
for ( uint i = 0; i < num_frames; i++ ) {
75-
frames[ i ] = new Frame( width, height );
75+
frames[ i ] = new Frame( mb_width, mb_height );
7676
free.add( frames[ i ] );
7777
}
7878

@@ -90,30 +90,51 @@ BufferPool::~BufferPool()
9090
unixassert( pthread_mutex_destroy( &mutex ) );
9191
}
9292

93-
Frame::Frame( uint s_width, uint s_height )
93+
Frame::Frame( uint mb_width, uint mb_height )
9494
{
95-
width = s_width;
96-
height = s_height;
95+
width = 16 * mb_width;
96+
height = 16 * mb_height;
9797
buf = new uint8_t[ sizeof( uint8_t ) * (3 * width * height / 2) ];
9898
state = FREE;
9999
handle = NULL;
100100
unixassert( pthread_mutex_init( &mutex, NULL ) );
101+
unixassert( pthread_cond_init( &activity, NULL ) );
102+
103+
slicerow = new SliceRow *[ mb_height ];
104+
105+
for ( uint i = 0; i < mb_height; i++ ) {
106+
slicerow[ i ] = new SliceRow( i, mb_height );
107+
}
101108
}
102109

103110
Frame::~Frame()
104111
{
105112
delete[] buf;
113+
114+
for ( uint i = 0; i < height / 16; i++ ) {
115+
delete slicerow[ i ];
116+
}
117+
118+
delete[] slicerow;
119+
120+
unixassert( pthread_cond_destroy( &activity ) );
106121
unixassert( pthread_mutex_destroy( &mutex ) );
107122
}
108123

109-
void Frame::lock( FrameHandle *s_handle )
124+
void Frame::lock( FrameHandle *s_handle,
125+
int f_code_fv, int f_code_bv,
126+
Picture *forward, Picture *backward )
110127
{
111128
MutexLock x( &mutex );
112129

113130
ahabassert( handle == NULL );
114131
ahabassert( state == FREE );
115132
handle = s_handle;
116133
state = LOCKED;
134+
135+
for ( uint i = 0; i < height / 16; i++ ) {
136+
slicerow[ i ]->init( f_code_fv, f_code_bv, forward, backward );
137+
}
117138
}
118139

119140
void Frame::set_rendered( void )
@@ -122,6 +143,7 @@ void Frame::set_rendered( void )
122143

123144
ahabassert( state == LOCKED );
124145
state = RENDERED;
146+
pthread_cond_broadcast( &activity );
125147
}
126148

127149
void Frame::relock( void )
@@ -130,6 +152,7 @@ void Frame::relock( void )
130152

131153
ahabassert( state == FREEABLE );
132154
state = RENDERED;
155+
pthread_cond_broadcast( &activity );
133156
}
134157

135158
void Frame::set_freeable( void )
@@ -167,6 +190,13 @@ FrameHandle::FrameHandle( BufferPool *s_pool, Picture *s_pic )
167190
frame = NULL;
168191
locks = 0;
169192
unixassert( pthread_mutex_init( &mutex, NULL ) );
193+
unixassert( pthread_cond_init( &activity, NULL ) );
194+
}
195+
196+
FrameHandle::~FrameHandle()
197+
{
198+
unixassert( pthread_cond_destroy( &activity ) );
199+
unixassert( pthread_mutex_destroy( &mutex ) );
170200
}
171201

172202
void FrameHandle::increment_lockcount( void )
@@ -183,8 +213,10 @@ void FrameHandle::increment_lockcount( void )
183213
} else {
184214
ahabassert( locks == 0 );
185215
frame = pool->get_free_frame();
186-
frame->lock( this );
216+
frame->lock( this, pic->get_f_code_fv(), pic->get_f_code_bv(),
217+
pic->get_forward(), pic->get_backward() );
187218
locks++;
219+
pthread_cond_broadcast( &activity );
188220
}
189221
}
190222

@@ -249,4 +281,25 @@ void FrameHandle::set_frame( Frame *s_frame )
249281
MutexLock x( &mutex );
250282
ahabassert( locks == 0 );
251283
frame = s_frame;
284+
pthread_cond_broadcast( &activity );
285+
}
286+
287+
void Frame::wait_rendered( void )
288+
{
289+
MutexLock x( &mutex );
290+
while ( state != RENDERED ) {
291+
pthread_cond_wait( &activity, &mutex );
292+
}
293+
}
294+
295+
void FrameHandle::wait_rendered( void )
296+
{
297+
MutexLock x( &mutex );
298+
299+
while ( !frame ) {
300+
pthread_cond_wait( &activity, &mutex );
301+
}
302+
/* now we have a frame and our mutex is locked so it can't be taken away */
303+
304+
frame->wait_rendered();
252305
}

framebuffer.hpp

+18-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "mpegheader.hpp"
55
#include "exceptions.hpp"
6+
#include "slicerow.hpp"
67

78
#include <stdint.h>
89
#include <pthread.h>
@@ -21,18 +22,21 @@ class FrameHandle
2122
int locks;
2223

2324
pthread_mutex_t mutex;
25+
pthread_cond_t activity;
2426

2527
void set_frame( Frame *s_frame );
2628

2729
public:
2830
void increment_lockcount( void );
2931
void decrement_lockcount( void );
3032

31-
Frame *get_frame( void ) { return frame; }
33+
Frame *get_frame( void ) { ahabassert( frame ); return frame; }
3234
Picture *get_picture( void ) { return pic; }
3335

3436
FrameHandle( BufferPool *s_pool, Picture *s_pic );
35-
~FrameHandle() { unixassert( pthread_mutex_destroy( &mutex ) ); }
37+
~FrameHandle();
38+
39+
void wait_rendered( void );
3640
};
3741

3842
class FrameQueue
@@ -62,7 +66,7 @@ class BufferPool
6266
pthread_mutex_t mutex;
6367

6468
public:
65-
BufferPool( uint s_num_frames, uint s_width, uint s_height );
69+
BufferPool( uint s_num_frames, uint mb_width, uint mb_height );
6670
~BufferPool();
6771

6872
FrameHandle *make_handle( Picture *pic ) { return new FrameHandle( this, pic ); }
@@ -88,24 +92,33 @@ class Frame
8892
Frame *prev, *next;
8993

9094
pthread_mutex_t mutex;
95+
pthread_cond_t activity;
96+
97+
SliceRow **slicerow;
9198

9299
public:
93-
Frame( uint s_width, uint s_height );
100+
Frame( uint mb_width, uint mb_height );
94101
~Frame();
95102

96103
uint8_t *get_buf( void ) { return buf; }
97104
uint8_t *get_y( void ) { return buf; }
98105
uint8_t *get_cb( void ) { return buf + width * height; }
99106
uint8_t *get_cr( void ) { return buf + width * height + width * height / 4; }
100107

101-
void lock( FrameHandle *s_handle );
108+
void lock( FrameHandle *s_handle,
109+
int f_code_fv, int f_code_bv,
110+
Picture *forward, Picture *backward );
102111
void set_rendered( void );
103112
void set_freeable( void );
104113
void relock( void );
105114
void free( void );
106115
void free_locked( void );
107116

108117
FrameState get_state( void ) { return state; }
118+
119+
void wait_rendered( void );
120+
121+
SliceRow *get_slicerow( uint row ) { return slicerow[ row ]; }
109122
};
110123

111124
#endif

mpegheader.hpp

+23-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "bitreader.hpp"
99
#include "exceptions.hpp"
1010
#include "file.hpp"
11+
#include "mutexobj.hpp"
1112

1213
#include "libmpeg2.h"
1314

@@ -168,9 +169,19 @@ class Slice : public MPEGHeader
168169
};
169170

170171
enum PictureType { I = 1, P, B };
172+
enum DecodeDirection { TOPDOWN, BOTTOMUP };
171173

174+
class Frame;
172175
class FrameHandle;
173176

177+
struct picture_decoder_call_struct
178+
{
179+
Picture *me;
180+
DecodeDirection direction;
181+
mpeg2_decoder_t decoder;
182+
Frame *cur, *fwd, *back;
183+
};
184+
174185
class Picture : public MPEGHeader
175186
{
176187
private:
@@ -194,7 +205,7 @@ class Picture : public MPEGHeader
194205
uint8_t *intra_quantiser_matrix,
195206
*non_intra_quantiser_matrix;
196207

197-
Slice **slicerow;
208+
Slice **first_slice_in_row;
198209

199210
Picture *forward_reference, *backward_reference;
200211

@@ -207,6 +218,9 @@ class Picture : public MPEGHeader
207218

208219
FrameHandle *fh;
209220

221+
pthread_mutex_t decoding_mutex;
222+
bool decoding;
223+
210224
public:
211225
int get_coded( void ) { return coded_order; }
212226
void set_coded( int s_coded ) { coded_order = s_coded; }
@@ -271,7 +285,10 @@ class Picture : public MPEGHeader
271285
Picture *get_forward( void ) { return forward_reference; }
272286
Picture *get_backward( void ) { return backward_reference; }
273287

274-
Slice *get_slicerow( uint row ) { return slicerow[ row ]; }
288+
Slice *get_first_slice_in_row( uint row ) { return first_slice_in_row[ row ]; }
289+
290+
int get_f_code_fv( void ) { return get_extension()->f_code_fv; }
291+
int get_f_code_bv( void ) { return get_extension()->f_code_bv; }
275292

276293
FrameHandle *get_framehandle( void ) { return fh; }
277294

@@ -284,6 +301,10 @@ class Picture : public MPEGHeader
284301
virtual void link( void );
285302

286303
void lock_and_decodeall();
304+
void start_parallel_decode( bool leave_locked );
305+
306+
void parallel_decode_internal( bool leave_locked );
307+
void decoder_internal( picture_decoder_call_struct *args );
287308
};
288309

289310
class SequenceEnd : public MPEGHeader

0 commit comments

Comments
 (0)