5 ** $VER: mpegamiga.c 1.11 (2.11.97)
6 ** mpegvideo.datatype 1.11
8 ** amiga support functions
10 ** Written 1996/1997 by Roland 'Gizzy' Mainz
17 #include <aros/debug.h>
19 /* project includes */
20 #include "mpegmyassert.h"
21 #include "mpegproto.h"
27 /* local prototypes */
28 static void InitStoreFrame( struct MPEGVideoInstData
*mvid
);
29 static void WritePixelArray8Fast( struct BitMap
*, UBYTE
* );
32 void mpeg_closedown( struct MPEGVideoInstData
*mvid
)
34 D(bug("[mpegvideo.datatype] %s()\n", __PRETTY_FUNCTION__
));
36 if( mvid
-> mvid_MPPool
)
38 DeletePool( (mvid
-> mvid_MPPool
) );
39 mvid
-> mvid_MPPool
= NULL
;
45 void InitStoreFrame( struct MPEGVideoInstData
*mvid
)
47 D(bug("[mpegvideo.datatype] %s()\n", __PRETTY_FUNCTION__
));
49 /* Alloc bitmap as key bitmap */
50 if( mvid
-> mvid_UseChunkyMap
)
52 mvid
-> mvid_KeyBitMap
= AllocBitMap( (ULONG
)anim_width
, (ULONG
)anim_height
, (ULONG
)anim_depth
, (BMF_CLEAR
| BMF_SPECIALFMT
| SHIFT_PIXFMT( pixfmt
)), NULL
);
56 mvid
-> mvid_KeyBitMap
= AllocBitMap( (ULONG
)anim_width
, (ULONG
)anim_height
, (ULONG
)anim_depth
, (BMF_CLEAR
| BMF_MINPLANES
), NULL
);
59 if( (mvid
-> mvid_KeyBitMap
) == NULL
)
61 myexit( mvid
, RETURN_FAIL
, ERROR_NO_FREE_STORE
);
66 void StoreFrame( struct MPEGVideoInstData
*mvid
, UBYTE
*data
)
68 D(bug("[mpegvideo.datatype] %s()\n", __PRETTY_FUNCTION__
));
70 /* All ready to store the frames ? */
71 if( (mvid
-> mvid_KeyBitMap
) == NULL
)
73 InitStoreFrame( mvid
);
78 #if !defined(__AROS__)
81 ULONG
*src
= (ULONG
*)data
;
85 ULONG height
= anim_height
;
87 dest
= tmp
= (UBYTE
*)mymalloc( mvid
, (size_t)((anim_width
+ 15UL) * anim_height
) );
91 UBYTE
*xrgb
= (UBYTE
*)src
;
96 CreateHAM8Line( (xrgb
+ 1), (xrgb
+ 2), (xrgb
+ 3), dest
, sizeof( ULONG
), anim_width
);
100 CreateHAM6Line( (xrgb
+ 1), (xrgb
+ 2), (xrgb
+ 3), dest
, sizeof( ULONG
), anim_width
);
108 AddFrame( mvid
, tmp
, NULL
);
114 case FULL_COLOR_DITHER
:
115 case FULL_COLOR_DITHER16
:
117 AddFrame( mvid
, data
, NULL
);
123 struct ColorMap
*cm
= NULL
;
125 if( mvid
-> mvid_PalettePerFrame
)
127 if ((cm
= GetColorMap( (1UL << anim_depth
) ) ) != NULL
)
132 /* Copy colors into colormap... */
133 for( i
= 0UL ; i
< used_cnt
; i
++ )
135 /* Bump colors from 8 to 32 bits-per-gun */
136 r
= ((ULONG
)used_colors
[ i
] . red
) * 0x01010101UL
;
137 g
= ((ULONG
)used_colors
[ i
] . green
) * 0x01010101UL
;
138 b
= ((ULONG
)used_colors
[ i
] . blue
) * 0x01010101UL
;
140 SetRGB32CM( cm
, i
, r
, g
, b
);
143 /* Fill remaining colors with "black" */
144 for( ; i
< (1UL << anim_depth
) ; i
++ )
146 SetRGB32CM( cm
, i
, 0UL, 0UL, 0UL );
151 AddFrame( mvid
, data
, cm
);
158 void AddFrame( struct MPEGVideoInstData
*mvid
, UBYTE
*data
, struct ColorMap
*cm
)
160 ULONG timestamp
= totNumFrames
++; /* timestamp of this frame */
161 struct FrameNode
*fn
;
163 D(bug("[mpegvideo.datatype] %s()\n", __PRETTY_FUNCTION__
));
168 BOOL created
= FALSE
;
170 /* Does we have already a frame with this timestamp ? ... */
171 if ((fn
= FindFrameNode( (&(mvid
-> mvid_FrameList
)), timestamp
) ) != NULL
)
174 if( (fn
-> fn_TimeStamp
) != timestamp
)
182 if( mvid
-> mvid_IndexScan
)
186 fn
= AllocFrameNode( classbase
, (mvid
-> mvid_Pool
) );
188 if( fn
&& (data
!= (UBYTE
*)~0UL) )
190 /* Create a locked frame here if new HAD to create the fn and if we have data.
191 * This is TRUE for the keyframe and/or of the mvid_LoadAll flag is TRUE
193 fn
-> fn_IsKeyFrame
= TRUE
; /* lock this bitmap that ADTM_UNLOADFRAME won't free it */
198 myexit( mvid
, RETURN_ERROR
, ERROR_INVALID_LOCK
);
206 /* Store frame count */
208 fn
-> fn_Frame
= timestamp
;
209 fn
-> fn_BMOffset
= mvid
-> mvid_Last_PIC_SC_Pos
;
210 fn
-> fn_IFrame
= mvid
-> mvid_LastIFrameNode
;
212 AddTail( (struct List
*)(&(mvid
-> mvid_FrameList
)), (struct Node
*)(&(fn
-> fn_Node
)) );
215 /* Does someone wants only to create an empty framenode here (e.g. data == (UBYTE *)~0UL) ? */
216 if( data
!= (UBYTE
*)~0UL )
218 if( (fn
-> fn_BitMap
) == NULL
)
220 if ((fn
-> fn_BitMap
= AllocFrameBitMap( mvid
) ) != NULL
)
227 case FAST_COLOR_DITHER
:
231 WritePixelArray8Fast( (fn
-> fn_BitMap
), data
);
238 case FULL_COLOR_DITHER
:
239 case FULL_COLOR_DITHER16
:
241 if( mvid
-> mvid_UseChunkyMap
)
244 APTR plane
= NULL
; /* be safe ! (CyberGFX has some problems with tag parsing...) */
245 ULONG bpr
= 0UL, /* be safe ! (CyberGFX has some problems with tag parsing...) */
246 height
= 0UL; /* be safe ! (CyberGFX has some problems with tag parsing...) */
248 if( handle
= LockBitMapTags( (fn
-> fn_BitMap
),
249 LBMI_BASEADDRESS
, (&plane
),
250 LBMI_BYTESPERROW
, (&bpr
),
251 LBMI_HEIGHT
, (&height
),
254 CopyMem( data
, plane
, (bpr
* height
) );
256 UnLockBitMap( handle
);
260 error_printf( mvid
, "LockBitMapTags failed for bitmap @ 0x%p\n", fn
->fn_BitMap
);
265 if( anim_depth
== 24UL )
273 ULONG size
= anim_width
* anim_height
;
275 InitBitMap( (&red
), 8, (ULONG
)anim_width
, (ULONG
)anim_height
);
276 InitBitMap( (&green
), 8, (ULONG
)anim_width
, (ULONG
)anim_height
);
277 InitBitMap( (&blue
), 8, (ULONG
)anim_width
, (ULONG
)anim_height
);
279 for( i
= 0UL ; i
< 24UL ; i
++ )
281 if( i
< 8 ) red
. Planes
[ i
] = fn
-> fn_BitMap
-> Planes
[ i
]; else
282 if( i
< 16 ) green
. Planes
[ i
- 8 ] = fn
-> fn_BitMap
-> Planes
[ i
]; else
283 blue
. Planes
[ i
- 16 ] = fn
-> fn_BitMap
-> Planes
[ i
];
286 /* Alloc temp memory for XRGB to RRR..., GGG..., BBB... array conversion */
287 tmp
= mymalloc( mvid
, (size_t)(size
+ 15UL) );
289 for( i
= 0 ; i
< 3 ; i
++ )
292 j_size
= (size
* 4UL) + i
;
294 for( j
= i
, tmp_run
= tmp
; j
< j_size
; j
+= 4UL )
296 *tmp_run
++ = data
[ j
];
301 case 0: WritePixelArray8Fast( (&red
), tmp
); break;
302 case 1: WritePixelArray8Fast( (&green
), tmp
); break;
303 case 2: WritePixelArray8Fast( (&blue
), tmp
); break;
311 error_printf( mvid
, "%dbit planar direct-RGB unsupported\n", anim_depth
);
321 myexit( mvid
, RETURN_ERROR
, ERROR_NO_FREE_STORE
);
328 /* can't alloc struct FrameNode */
329 myexit( mvid
, RETURN_ERROR
, ERROR_NO_FREE_STORE
);
334 if( mvid
-> mvid_IndexScan
)
336 /* Find the nearest frame */
337 if ((fn
= FindFrameNode( (&(mvid
-> mvid_FrameList
)), timestamp
) ) != NULL
)
339 /* Bump the duration time of the predecessor (frame) */
340 fn
-> fn_Duration
= timestamp
- (fn
-> fn_TimeStamp
);
348 /***************************************************************/
350 #if !defined(__AROS__)
351 static APTR
AllocPooledVec( struct MPEGVideoInstData
*mvid
, APTR
, ULONG
);
352 static void FreePooledVec( struct MPEGVideoInstData
*mvid
, APTR
, APTR
);
354 #define AllocPooledVec(mvid, pool, size) AllocVecPooled(pool, size)
355 #define FreePooledVec(mvid, pool, mem) FreeVecPooled(pool, mem)
357 static ULONG
VecSize( APTR
);
359 void *mymalloc( struct MPEGVideoInstData
*mvid
, size_t s
)
363 if( (mvid
-> mvid_MPPool
) == NULL
)
365 if( (mvid
-> mvid_MPPool
= CreatePool( (MEMF_PUBLIC
| MEMF_CLEAR
), 16384UL, 16384UL )) == NULL
)
367 myexit( mvid
, RETURN_FAIL
, ERROR_NO_FREE_STORE
);
371 if( (mem
= (void *)AllocPooledVec( mvid
, (mvid
-> mvid_MPPool
), (ULONG
)s
)) == NULL
)
373 myexit( mvid
, RETURN_ERROR
, ERROR_NO_FREE_STORE
);
380 void myfree( struct MPEGVideoInstData
*mvid
, void *mem
)
382 FreePooledVec( mvid
, (mvid
-> mvid_MPPool
), mem
);
386 void *myrealloc( struct MPEGVideoInstData
*mvid
, void *oldmem
, size_t newsize
)
393 oldsize
= VecSize( oldmem
);
396 if( newsize
== oldsize
)
403 if ((newmem
= AllocPooledVec( mvid
, (mvid
-> mvid_MPPool
), (ULONG
)newsize
) ) != NULL
)
407 memcpy( newmem
, oldmem
, (size_t)MIN( oldsize
, newsize
) );
410 FreePooledVec( mvid
, (mvid
-> mvid_MPPool
), oldmem
);
414 myexit( mvid
, RETURN_FAIL
, ERROR_NO_FREE_STORE
);
421 #if !defined(__AROS__)
423 APTR
AllocPooledVec( struct MPEGVideoInstData
*mvid
, APTR pool
, ULONG memsize
)
425 ULONG
*memory
= NULL
;
427 if( pool
&& memsize
)
429 memsize
+= (ULONG
)sizeof( ULONG
);
431 if( memory
= (ULONG
*)AllocPooled( pool
, memsize
) )
439 error_printf( mvid
, "AllocPooledVec: illegal args %lx %lx\n", pool
, memsize
);
442 return( (APTR
)memory
);
447 void FreePooledVec( struct MPEGVideoInstData
*mvid
, APTR pool
, APTR mem
)
453 memory
= (ULONG
*)mem
;
457 FreePooled( pool
, memory
, (*memory
) );
461 error_printf( mvid
, "FreePooledVec: illegal args %lx %lx\n", pool
, mem
);
466 /* get size of an AllocPooledVec memory */
468 ULONG
VecSize( APTR mem
)
470 return( *(((ULONG
*)mem
) - 1) );
474 ULONG
SearchColor( struct MPEGVideoInstData
*mvid
, struct ColorRegister
*colortable
, ULONG
*numcolors
, ULONG maxcount
, struct ColorRegister
*color
)
477 LONG error
, minerror
=
478 #if !defined(__AROS__)
483 ULONG minerrorindex
= 0UL;
484 const ULONG nc
= *numcolors
; /* short cut to (*numcolors) (read only) */
487 D(bug("[mpegvideo.datatype] %s()\n", __PRETTY_FUNCTION__
));
489 /* Check for a color in the specified range */
490 for( i
= 0UL ; i
< nc
; i
++, colortable
++ )
492 er
= ABS( ((WORD
)(colortable
-> red
) - (WORD
)(color
-> red
)) );
493 eg
= ABS( ((WORD
)(colortable
-> green
) - (WORD
)(color
-> green
)) );
494 eb
= ABS( ((WORD
)(colortable
-> blue
) - (WORD
)(color
-> blue
)) );
496 error
= er
+ eg
+ eb
;
498 if( error
< minerror
)
500 if( error
< (mvid
-> mvid_ColorError
) )
510 /* Any color entry free for this frame ? */
513 *colortable
= *color
;
520 return( minerrorindex
);
525 void WritePixelArray8Fast( struct BitMap
*dest
, UBYTE
*source
)
527 ULONG
*plane
[ 8 ] = { 0 },
528 *chunky
= (ULONG
*)source
; /* fetch 32 bits per cycle */
530 ULONG numcycles
= ((dest
-> Rows
) * (dest
-> BytesPerRow
)) / sizeof( ULONG
);
532 D(bug("[mpegvideo.datatype] %s()\n", __PRETTY_FUNCTION__
));
534 /* Copy plane ptrs */
535 for( i
= 0UL ; i
< (dest
-> Depth
) ; i
++ )
537 plane
[ i
] = (ULONG
*)(dest
-> Planes
[ i
]);
540 /* Fill unused planes with plane 0, which will be written last, all prevoius accesses
541 * will be droped (assumes that a cache hides this "dummy" writes)
543 for( ; i
< 8UL ; i
++ )
545 plane
[ i
] = (ULONG
*)(dest
-> Planes
[ 0 ]);
548 /* Process bitmaps */
549 for( i
= 0UL ; i
< numcycles
; i
++ )
552 b0
, b1
, b2
, b3
, b4
, b5
, b6
, b7
;
554 /* process 32 pixels */
555 b0
= *chunky
++; b4
= *chunky
++;
556 b1
= *chunky
++; b5
= *chunky
++;
557 b2
= *chunky
++; b6
= *chunky
++;
558 b3
= *chunky
++; b7
= *chunky
++;
560 #define merge( a, b, mask, shift ) \
561 tmp = mask & (a ^ (b >> shift)); \
565 merge( b0
, b2
, 0x0000ffff, 16 );
566 merge( b1
, b3
, 0x0000ffff, 16 );
567 merge( b4
, b6
, 0x0000ffff, 16 );
568 merge( b5
, b7
, 0x0000ffff, 16 );
570 merge( b0
, b1
, 0x00ff00ff, 8 );
571 merge( b2
, b3
, 0x00ff00ff, 8 );
572 merge( b4
, b5
, 0x00ff00ff, 8 );
573 merge( b6
, b7
, 0x00ff00ff, 8 );
575 merge( b0
, b4
, 0x0f0f0f0f, 4 );
576 merge( b1
, b5
, 0x0f0f0f0f, 4 );
577 merge( b2
, b6
, 0x0f0f0f0f, 4 );
578 merge( b3
, b7
, 0x0f0f0f0f, 4 );
580 merge( b0
, b2
, 0x33333333, 2 );
581 merge( b1
, b3
, 0x33333333, 2 );
582 merge( b4
, b6
, 0x33333333, 2 );
583 merge( b5
, b7
, 0x33333333, 2 );
585 merge( b0
, b1
, 0x55555555, 1 );
586 merge( b2
, b3
, 0x55555555, 1 );
587 merge( b4
, b5
, 0x55555555, 1 );
588 merge( b6
, b7
, 0x55555555, 1 );