]> git.sesse.net Git - mlt/blob - src/modules/core/producer_noise.c
Big modification - switch to macros for parent class access
[mlt] / src / modules / core / producer_noise.c
1 /*
2  * producer_noise.c -- noise generating producer
3  * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
4  * Author: Charles Yates <charles.yates@pandora.be>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #include "producer_noise.h"
22 #include <framework/mlt_frame.h>
23 #include <framework/mlt_pool.h>
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 /** Random number generator
30 */
31
32 static unsigned int seed_x = 521288629;
33 static unsigned int seed_y = 362436069;
34
35 static unsigned inline int fast_rand( )
36 {
37    static unsigned int a = 18000, b = 30903;
38    seed_x = a * ( seed_x & 65535 ) + ( seed_x >> 16 );
39    seed_y = b * ( seed_y & 65535 ) + ( seed_y >> 16 );
40    return ( ( seed_x << 16 ) + ( seed_y & 65535 ) );
41 }
42
43 // Foward declarations
44 static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index );
45 static void producer_close( mlt_producer this );
46
47 /** Initialise.
48 */
49
50 mlt_producer producer_noise_init( void *arg )
51 {
52         // Create a new producer object
53         mlt_producer this = mlt_producer_new( );
54
55         // Initialise the producer
56         if ( this != NULL )
57         {
58                 int is_pal = mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( this ), "normalised_height" ) == 576;
59
60                 // Synthetic - aspect ratio of 1
61                 mlt_properties_set_double( MLT_PRODUCER_PROPERTIES( this ), "aspect_ratio", is_pal ? 59.0/54.0 : 10.0/11.0 );
62
63                 // Callback registration
64                 this->get_frame = producer_get_frame;
65                 this->close = ( mlt_destructor )producer_close;
66         }
67
68         return this;
69 }
70
71 static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
72 {
73         // Obtain properties of frame
74         mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
75
76         // Calculate the size of the image
77         int size = *width * *height * 2;
78
79         // Set the format being returned
80         *format = mlt_image_yuv422;
81
82         // Allocate the image
83         *buffer = mlt_pool_alloc( size );
84
85         // Update the frame
86         mlt_properties_set_data( properties, "image", *buffer, size, mlt_pool_release, NULL );
87         mlt_properties_set_int( properties, "width", *width );
88         mlt_properties_set_int( properties, "height", *height );
89
90         // Before we write to the image, make sure we have one
91         if ( *buffer != NULL )
92         {
93                 // Calculate the end of the buffer
94                 uint8_t *p = *buffer + *width * *height * 2;
95
96                 // Value to hold a random number
97                 uint32_t value;
98
99                 // Generate random noise
100                 while ( p != *buffer )
101                 {
102                         value = fast_rand( ) & 0xff;
103                         *( -- p ) = 128;
104                         *( -- p ) = value < 16 ? 16 : value > 240 ? 240 : value;
105                 }
106         }
107
108         return 0;
109 }
110
111 static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
112 {
113         // Get the frame properties
114         mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
115
116         int size = 0;
117
118         // Correct the returns if necessary
119         *samples = *samples <= 0 ? 1920 : *samples;
120         *channels = *channels <= 0 ? 2 : *channels;
121         *frequency = *frequency <= 0 ? 48000 : *frequency;
122
123         // Calculate the size of the buffer
124         size = *samples * *channels * sizeof( int16_t );
125
126         // Allocate the buffer
127         *buffer = mlt_pool_alloc( size );
128
129         // Make sure we got one and fill it
130         if ( *buffer != NULL )
131         {
132                 int16_t *p = *buffer + size / 2;
133                 while ( p != *buffer ) 
134                         *( -- p ) = fast_rand( ) & 0x0f00;
135         }
136
137         // Set the buffer for destruction
138         mlt_properties_set_data( properties, "audio", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
139
140         return 0;
141 }
142
143 static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
144 {
145         // Generate a frame
146         *frame = mlt_frame_init( );
147
148         // Check that we created a frame and initialise it
149         if ( *frame != NULL )
150         {
151                 // Obtain properties of frame
152                 mlt_properties properties = MLT_FRAME_PROPERTIES( *frame );
153
154                 // Obtain properties of producer
155                 mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( this );
156
157                 // Determine if we're producing PAL or NTSC
158                 int is_pal = mlt_properties_get_double( producer_props, "fps" ) == 25.0;
159
160                 // Aspect ratio is 1?
161                 mlt_properties_set_double( properties, "aspect_ratio", is_pal ? 59.0/54.0 : 10.0/11.0 );
162
163                 // Set producer-specific frame properties
164                 mlt_properties_set_int( properties, "progressive", 1 );
165
166                 // Update timecode on the frame we're creating
167                 mlt_frame_set_position( *frame, mlt_producer_position( this ) );
168
169                 // Push the get_image method
170                 mlt_frame_push_get_image( *frame, producer_get_image );
171
172                 // Specify the audio
173                 ( *frame )->get_audio = producer_get_audio;
174         }
175
176         // Calculate the next timecode
177         mlt_producer_prepare_next( this );
178
179         return 0;
180 }
181
182 static void producer_close( mlt_producer this )
183 {
184         this->close = NULL;
185         mlt_producer_close( this );
186         free( this );
187 }
188