Browse Source

Upload files to ''

master
acheney 1 year ago
parent
commit
7c05d7a56a
  1. 21
      LICENSE
  2. 291
      boot.pixi
  3. 1032
      demo.pixi
  4. 109
      ffmpeg_video_export.pixi
  5. 391
      mjpeg.pixi

21
LICENSE

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Aden Cheney
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

291
boot.pixi

@ -0,0 +1,291 @@ @@ -0,0 +1,291 @@
// pixilang-based music visualizer
// by acheney (with help from nightradio, silent broadcast, and others)
// under mit license
include "demo.pixi"
// - CONFIG BEGIN -
// -- DEMO LIB CONFIG --
// use opengl (could improve performance and make everything look smoother) (0 = false, 1 = true)
demo_opengl = 1
// demo width in pixels
demo_xsize = 1920
// demo height in pixels
demo_ysize = 1080
// demo video export filename, comment it out if you don't want to export
//demo_video_export = "video.mkv"
// demo video export fps (frames per second)
demo_video_export_fps = 60
// demo video export quality (0 - 100)
demo_video_export_q = 100
// -- FFT/VISUALIZER CONFIG --
// fft size (must be a power of 2)
fft_size = 2048
// visualizer minimum midi pitch
vis_min_pitch = 21
// visualizer maximum midi pitch
vis_max_pitch = 135
// visualizer floor in decibels (everything below this is cut out)
vis_floor = 80
// visualizer smoothing factor
vis_smooth = 3
// visualizer horizontal scale
vis_scale = 8
// visualizer enter time delay in ms
vis_delay = 2000
// visualizer enter time in ms
vis_time = 1000
// -- EXIT TIME CONFIG --
// time for everything to fade out in ms (this divided by 3 is the amount of time for each element to fade out)
all_exit = 3000
// -- LOGO CONFIG --
// logo size scale
logo_scale = 0.25
// logo enter time delay in ms
logo_delay = 1000
// logo enter time in ms
logo_time = 1000
// -- ARTIST CONFIG --
// artist size scale
artist_scale = 0.25
// artist enter time in ms
artist_time = 1000
// artist exit time in ms
artist_exit = 1000
// -- COVER CONFIG --
// cover gaussian blur radius
cover_blur_rad = 20
// cover brightness scale
cover_brightness = 0.5
// - END CONFIG -
demo_load_wav( "media/song.wav" )
cover = load( "media/cover.png" )
logo = load("media/logo.png")
artist = load("media/artist.png")
demo_length = 0
fft_im = new( fft_size, 1, FLOAT )
fft_re = new( fft_size, 1, FLOAT )
fft_im2 = new( fft_size, 1, FLOAT )
fft_re2 = new( fft_size, 1, FLOAT )
fft_db = new( fft_size, 1, FLOAT )
cover_xsize = get_xsize(cover)
cover_ysize = get_ysize(cover)
cover_size = cover_xsize * cover_ysize
cover_src = clone(cover)
logo_xsize = get_xsize(logo)
logo_ysize = get_ysize(logo)
artist_xsize = get_xsize(artist)
artist_ysize = get_ysize(artist)
demo_init()
custom_init()
demo_add_scene( 0, 0, 0, view )
demo_add_scene( 0, 0, demo_length, DEMO_STOP )
demo_play()
demo_deinit()
fn view( $t1, $t2, $len )
{
clear( #000000 )
cover_render($t1)
vis_render($t1)
artist_render($t1)
logo_render($t1)
transp(255)
}
fn vis_render($t1)
{
rel_time = max($t1, vis_delay) - vis_delay
exit_point = demo_length - ((2 * all_exit) / 3)
rel_time_end = max($t1, exit_point) - exit_point
speed_enter = 255 / vis_time
speed_exit = 255 / (all_exit / 3)
trans = min(255 - (rel_time_end * speed_exit), min(rel_time * speed_enter, 255))
transp(trans)
t_scale(vis_scale, 1, 1)
width = (vis_max_pitch - vis_min_pitch)
t_translate(-(width / 2), ((demo_ysize / 3) - vis_floor) , 0)
i = 0 while i < fft_size {
v = demo_sound_pcm_stream[ (demo_sound_pcm_stream_ptr + i) * demo_sound_channels ] / 256
win = sin( M_PI * i / fft_size )
fft_re[i] = v * win
fft_im[i] = 0
i = i + 1
}
fft(0, fft_im, fft_re)
i = 0 while i < (fft_size / 2) {
v = fft_re[ i ] * fft_re[ i ] + fft_im[ i ] * fft_im[ i ]
v = sqrt( v )
v = 20 * log10( v )
old_v = fft_db[ i ]
fft_db[ i ] = old_v + (v - old_v) * (1 / vis_smooth)
i = i + 1
}
bin_width = demo_sound_rate / fft_size
p = vis_min_pitch
while p < vis_max_pitch {
f = pow( 2, p / 12) * 8.175799
bin = f / bin_width
idx = floor( bin )
frac = bin - idx
dB = ( 1 - frac ) * fft_db[ idx ] + frac * fft_db[ idx +1 ]
if (dB >= -vis_floor) {
line( (p - vis_min_pitch), vis_floor, (p - vis_min_pitch), -dB, WHITE)
}
p = p + (1 / vis_scale)
}
t_reset()
}
fn cover_render($t1) {
exit_point = demo_length - all_exit
rel_time = max($t1, exit_point) - exit_point
speed = 255 / (all_exit / 3)
trans = min(255 - (rel_time * speed), 255)
transp(trans)
base = 255 * cover_brightness
flash = base * (abs(demo_sound_pcm_stream[demo_sound_pcm_stream_ptr * demo_sound_channels]) + 1)
pixi(cover, 0, 0, get_color(flash, flash, flash), ((demo_xsize / cover_xsize)), ((demo_xsize / cover_xsize)))
}
fn logo_render($t1) {
exit_point = demo_length - (all_exit / 3)
rel_time = max($t1, exit_point) - exit_point
speed = 255 / (all_exit / 3)
trans = min(255 - (rel_time * speed), 255)
transp(trans)
rel_time = max($t1, logo_delay) - logo_delay
speed = demo_ysize / logo_time
perc = min(((rel_time * speed) / demo_ysize), 1)
perc_curved = (atan(((2 * perc) - 1)*10)/(M_PI/2)/2 + 0.5) + 0.032765
pixi(logo, 0, ((1 - perc_curved) * demo_ysize), WHITE, logo_scale, logo_scale)
}
fn artist_render($t1) {
transp(255)
rel_time = max($t1, artist_time) - artist_time
speed = demo_ysize / artist_exit
perc = min(((rel_time * speed) / demo_ysize), 1)
perc_curved = (atan(((2 * perc) - 1)*10)/(M_PI/2)/2 + 0.5) - 0.032765
pixi(artist, 0, perc_curved * -demo_ysize, WHITE, logo_scale, logo_scale)
}
fn custom_init()
{
//gaussian blur
sigma = max((cover_blur_rad / 2), 1)
kernel_width = (2 * cover_blur_rad) + 1
kernel = new(kernel_width, kernel_width, FLOAT)
sum = 0
for (x = -cover_blur_rad ; x <= cover_blur_rad ; x + 1) {
for (y = -cover_blur_rad ; y <= cover_blur_rad ; y + 1) {
exp_num = -(x * x + y * y)
exp_dem = 2 * sigma * sigma
expression = pow(M_E, exp_num / exp_dem)
ker_val = (expression / (2 * M_PI * sigma * sigma))
kernel[(x + cover_blur_rad), (y + cover_blur_rad)] = ker_val
sum = sum + ker_val
}
}
FIXED_POINT_MUL = 32768
for (x = 0 ; x < kernel_width ; x + 1) {
for (y = 0 ; y < kernel_width ; y + 1) {
kernel[x, y] = kernel[x, y] / sum * FIXED_POINT_MUL
}
}
convert_type( kernel, INT )
conv_filter( cover, cover_src, kernel, FIXED_POINT_MUL, 0, CONV_FILTER_COLOR )
demo_length = (demo_sound_len / demo_sound_rate) * 1000
}
fn max($a, $b) {
if ($a >= $b) {
ret($a)
} else {
ret($b)
}
}
fn min($a, $b) {
if ($a < $b) {
ret($a)
} else {
ret($b)
}
}
show_memory_debug_messages( 1 )

1032
demo.pixi

File diff suppressed because it is too large Load Diff

109
ffmpeg_video_export.pixi

@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
//
// ffmpeg/avconv-based video export functions
// (experimental)
//
fn ffmpeg_video_export_thread( $thread_id, $ff )
{
if $ff < 0 { ret( 0 ) }
$ts = ""
$audio = ""
$audio2 = ""
if $ff.audio_file_name > 0
{
sprintf( $audio, "-i \"%s\"", $ff.audio_file_name )
$audio2 = "-acodec pcm_s16le"
}
$vcodec = ""
if $ff.kbits == 0
{
sprintf( $vcodec, "-vcodec libx264 -b:v %uk -preset slow", $ff.kbits )
}
else
{
sprintf( $vcodec, "-vcodec libx264 -b:v 50000k -preset medium" )
}
sprintf(
$ts,
"%s %s -y -pix_fmt bgr32 -s %dx%d -f rawvideo -r %d -i \"%s\" %s %s \"%s\"",
g_avconv,
$audio,
$ff.xsize,
$ff.ysize,
$ff.fps,
$ff.pipe_name,
$vcodec,
$audio2,
$ff.name )
printf( "FFmpeg (output) command: %s\n", $ts )
system( $ts )
}
fn ffmpeg_video_export_open( $filename, $xsize, $ysize, $fps, $kbits, $max_frames, $audio_file_name )
{
g_avconv = -1
while 1
{
if system( "ffmpeg -version" ) == 0 { g_avconv = "ffmpeg" break }
if system( "avconv -version" ) == 0 { g_avconv = "avconv" break }
break
}
if g_avconv == -1
{
logf( "No AV converters detected. Please install ffmpeg or avconv!\n" )
logf( "Please also note that this library is designed for *nix systems (Linux, macOS, BSD, etc.) only.\n" )
ret( -1 )
}
$ff = new( 1, 1, INT )
$ff.xsize = $xsize
$ff.ysize = $ysize
$ff.fps = $fps
$ff.kbits = $kbits
$ff.name = $filename
$ff.pipe_name = new( 1, 1, INT8 )
sprintf( $ff.pipe_name, "/tmp/avconv_vpipe_%d", $ff )
$ff.frame = 0
$ff.max_frames = $max_frames
if $0 >= 7
{
$ff.audio_file_name = $audio_file_name
}
$ts = ""
sprintf( $ts, "mkfifo %s", $ff.pipe_name )
system( $ts )
$ff.th = thread_create( ffmpeg_video_export_thread, $ff )
ret( $ff )
}
fn ffmpeg_video_export_close( $ff )
{
if $ff < 0 { ret( 0 ) }
if $ff.pipe_f
{
fclose( $ff.pipe_f )
}
thread_destroy( $ff.th, INT_MAX )
remove_file( $ff.pipe_name )
remove( $ff.pipe_name )
remove( $ff )
}
fn ffmpeg_video_export_write( $ff, $buf )
{
if $ff < 0 { ret( 0 ) }
if $ff.pipe_f == 0 { $ff.pipe_f = fopen( $ff.pipe_name, "wb" ) }
if $ff.pipe_f
{
fwrite( $buf, get_size( $buf ) * get_esize( $buf ), $ff.pipe_f )
$ff.frame + 1
if $ff.max_frames && $ff.frame >= $ff.max_frames
{
fputs( "FFmpeg export stop\n" )
ret( 1 )
}
}
ret( 0 )
}

391
mjpeg.pixi

@ -0,0 +1,391 @@ @@ -0,0 +1,391 @@
//
// AVI MJPEG encoder
//
include "riff.pixi"
AVIH_FLAG_HASINDEX = 0x00000010 //Index at end of file; NOT RECOGNIZED BY MPLAYER & VLC :(
AVIH_FLAG_MUSTUSEINDEX = 0x00000020
AVIH_FLAG_ISINTERLEAVED = 0x00000100
AVIH_FLAG_TRUSTCKTYPE = 0x00000800 //Use CKType to find key frames
AVIH_FLAG_WASCAPTUREFILE = 0x00010000
AVIH_FLAG_COPYRIGHTED = 0x00020000
MJPEG_ENCODER_FLAG_HASSOUND = ( 1 << 0 )
MJPEG_ENCODER_FLAG_USEINDEX = ( 1 << 1 )
fn mjpeg_fn_error( $fn_name, $pars )
{
logf( "%s() MJPEG error: wrong number of parameters (%d)\n", $fn_name, $pars )
}
fn mjpeg_encoder_open(
$fps,
$width,
$height,
$quality,
$audio_channels,
$audio_frames_per_second,
$audio_sample_type,
$flags,
$output_stream )
{
if $0 != 9 { mjpeg_fn_error( "mjpeg_encoder_open", $0 ) ret( -1 ) }
$mj = new( 1, 1, INT )
$mj.fps = $fps
$mj.frames = 0
$mj.width = $width
$mj.height = $height
$mj.quality = $quality
$mj.audio_ch = $audio_channels
$mj.audio_freq = $audio_frames_per_second
$mj.audio_type = $audio_sample_type
$mj.flags = $flags
$mj.out = $output_stream
$mj.idx = new( 4, 1, INT32 )
$mj.idx_ptr = 0
$mj.jpeg = -1
$mj.silent_chunk = -1
$mj.audio_bits = 0
if $audio_sample_type == INT8 { $mj.audio_bits = 8 }
if $audio_sample_type == INT16 { $mj.audio_bits = 16 }
if $audio_sample_type == FLOAT32 { $mj.audio_bits = 32 }
if $mj.audio_bits == 0
{
logf( "MJPEG encoder error: wrong audio sample type. Possible values: INT8, INT16, FLOAT32\n" )
ret( -1 )
}
//AVI:
$mj.c_avi = riff_chunk_open( -1, "RIFF", $mj.out )
riff_chunk_write_data( $mj.c_avi, "AVI ", 0, 0 )
//Header:
$c_hdrl = riff_chunk_open( $mj.c_avi, "LIST", $mj.out )
riff_chunk_write_data( $c_hdrl, "hdrl", 0, 0 )
$c = riff_chunk_open( $c_hdrl, "avih", $mj.out )
$avih = new( 14, 1, INT32 )
clean( $avih )
$avih[ 0 ] = 1000000 div $mj.fps //microSecPerFrame
$avih[ 1 ] = 10000000 //maxBytesPerSec
$avih[ 3 ] = AVIH_FLAG_ISINTERLEAVED | AVIH_FLAG_TRUSTCKTYPE | AVIH_FLAG_WASCAPTUREFILE //flags
if $flags & MJPEG_ENCODER_FLAG_USEINDEX
{
$avih[ 3 ] | AVIH_FLAG_HASINDEX
}
$avih[ 4 ] = 0 //totalFrames
$mj.fix1_offset = ftell( $mj.out ) + 4 * 4
if $flags & MJPEG_ENCODER_FLAG_HASSOUND { $avih[ 6 ] = 2 } else { $avih[ 6 ] = 1 }
$avih[ 7 ] = 1024 * 1024 //suggestedBufferSize
$avih[ 8 ] = $mj.width
$avih[ 9 ] = $mj.height
riff_chunk_write_data( $c, $avih, 0, 0 )
riff_chunk_close( $c )
remove( $avih )
//Video stream info:
$c_strl = riff_chunk_open( $c_hdrl, "LIST", $mj.out )
riff_chunk_write_data( $c_strl, "strl", 0, 0 )
$c = riff_chunk_open( $c_strl, "strh", $mj.out )
$strh = new( 14, 1, INT32 )
clean( $strh )
$strh[ 0 ] = 'vids' //type
$strh[ 1 ] = 'MJPG' //handler
$strh[ 5 ] = 1 //scale
$strh[ 6 ] = $fps //rate
$strh[ 8 ] = 0 //length
$mj.fix2_offset = ftell( $mj.out ) + 8 * 4
$strh[ 9 ] = 1024 * 1024 //suggestedBufferSize
$strh[ 10 ] = -1 //quality
$strh[ 13 ] = $width | ( $height << 16 )
riff_chunk_write_data( $c, $strh, 0, 0 )
riff_chunk_close( $c )
remove( $strh )
$c = riff_chunk_open( $c_strl, "strf", $mj.out )
$bmph = new( 10, 1, INT32 )
clean( $bmph )
$bmph[ 0 ] = get_size( $bmph ) * get_esize( $bmph ) //size
$bmph[ 1 ] = $width
$bmph[ 2 ] = $height
$bmph[ 3 ] = 1 | ( 24 << 16 ) //planes and bitCount
$bmph[ 4 ] = 'MJPG' //compression
$bmph[ 5 ] = $width * $height * 3 //imgSize
riff_chunk_write_data( $c, $bmph, 0, 0 )
riff_chunk_close( $c )
remove( $bmph )
riff_chunk_close( $c_strl )
if $flags & MJPEG_ENCODER_FLAG_HASSOUND
{
//Audio stream info (uncompressed interleaved):
$c_strl = riff_chunk_open( $c_hdrl, "LIST", $mj.out )
riff_chunk_write_data( $c_strl, "strl", 0, 0 )
$c = riff_chunk_open( $c_strl, "strh", $mj.out )
$strh = new( 14, 1, INT32 )
clean( $strh )
$strh[ 0 ] = 'auds' //type
$strh[ 1 ] = 0 //handler
$strh[ 5 ] = 1 //scale
$strh[ 6 ] = $audio_frames_per_second //rate
$strh[ 8 ] = 0 //length
$mj.fix3_offset = ftell( $mj.out ) + 8 * 4
$strh[ 9 ] = 0 //suggestedBufferSize
$strh[ 10 ] = -1 //quality
$strh[ 11 ] = $audio_channels * ( $mj.audio_bits / 8 ) //sampleSize
riff_chunk_write_data( $c, $strh, 0, 0 )
riff_chunk_close( $c )
remove( $strh )
$c = riff_chunk_open( $c_strl, "strf", $mj.out )
$fmt = new( 4, 1, INT32 )
clean( $fmt )
$audio_format = 1; if $mj.audio_bits == 32 { $audio_format = 3 }
$fmt[ 0 ] = $audio_format | ( $audio_channels << 16 )
$fmt[ 1 ] = $audio_frames_per_second
$fmt[ 2 ] = $audio_frames_per_second * $audio_channels * ( $mj.audio_bits / 8 ) //bytes per second
$fmt[ 3 ] = $audio_channels * ( $mj.audio_bits / 8 ) | ( $mj.audio_bits << 16 ) //block align + bits
riff_chunk_write_data( $c, $fmt, 0, 0 )
riff_chunk_close( $c )
remove( $fmt )
riff_chunk_close( $c_strl )
}
riff_chunk_close( $c_hdrl )
//Video and Audio data:
$mj.c_movi = riff_chunk_open( $mj.c_avi, "LIST", $mj.out )
riff_chunk_write_data( $mj.c_movi, "movi", 0, 0 )
ret( $mj )
}
/*fn mjpeg_encoder_jfif_to_avi1( $jpeg )
{
if $0 != 1 { mjpeg_fn_error( "mjpeg_encoder_jfif_to_avi1", $0 ) ret( 0 ) }
$p = -1
$i = 0 while $i < 256
{
if $jpeg[ $i ] == 'J'
{
if $jpeg[ $i + 1 ] == 'F'
{
if $jpeg[ $i + 2 ] == 'I'
{
if $jpeg[ $i + 3 ] == 'F'
{
$p = $i
break
}
}
}
}
$i + 1
}
if $p >= 0
{
$size = get_size( $jpeg )
$jpeg[ $p ] = 'A' $p + 1
$jpeg[ $p ] = 'V' $p + 1
$jpeg[ $p ] = 'I' $p + 1
$jpeg[ $p ] = '1' $p + 1
$jpeg[ $p ] = 0 $p + 1
$jpeg[ $p ] = 0 $p + 1
$jpeg[ $p ] = $size & 255 $p + 1
$jpeg[ $p ] = ( $size >> 8 ) & 255 $p + 1
$jpeg[ $p ] = ( $size >> 16 ) & 255 $p + 1
$jpeg[ $p ] = ( $size >> 24 ) & 255 $p + 1
$jpeg[ $p ] = $size & 255 $p + 1
$jpeg[ $p ] = ( $size >> 8 ) & 255 $p + 1
$jpeg[ $p ] = ( $size >> 16 ) & 255 $p + 1
$jpeg[ $p ] = ( $size >> 24 ) & 255 $p + 1
}
ret( 0 )
}*/
fn mjpeg_encoder_write_jpeg( $mj, $jpeg, $offset_bytes, $size_bytes )
{
if $0 != 4 { mjpeg_fn_error( "mjpeg_encoder_write_jpeg", $0 ) ret( 0 ) }
if $mj <= 0 { ret( 0 ) }
if $mj.flags & MJPEG_ENCODER_FLAG_USEINDEX
{
mjpeg_encoder_add_index( $mj, '00dc', 0x10, ftell( $mj.out ) - ( $mj.c_movi.size_ptr + 4 ), $size_bytes )
}
$c = riff_chunk_open( $mj.c_movi, "00dc", $mj.out )
riff_chunk_write_data( $c, $jpeg, $offset_bytes, $size_bytes )
riff_chunk_close( $c )
ret( $size_bytes )
}
fn mjpeg_encoder_write_image( $mj, $img )
{
if $0 != 2 { mjpeg_fn_error( "mjpeg_encoder_write_image", $0 ) ret( 0 ) }
if $mj <= 0 { ret( 0 ) }
if $mj.jpeg <= 0
{
$mj.jpeg = new( 1, 1, INT8 )
}
$jpeg = $mj.jpeg
if $img != -999
{
$f = fopen_mem( $jpeg )
fsave( $img, $f, FORMAT_JPEG, $mj.quality )
fclose( $f )
}
if $mj.flags & MJPEG_ENCODER_FLAG_USEINDEX
{
mjpeg_encoder_add_index( $mj, '00dc', 0x10, ftell( $mj.out ) - ( $mj.c_movi.size_ptr + 4 ), get_size( $jpeg ) )
}
$c = riff_chunk_open( $mj.c_movi, "00dc", $mj.out )
riff_chunk_write_data( $c, $jpeg, 0, 0 )
riff_chunk_close( $c )
ret( get_size( $jpeg ) )
}
fn mjpeg_encoder_get_audio_size( $mj ) //Number of audio frames per chunk
{
if $0 != 1 { mjpeg_fn_error( "mjpeg_encoder_get_audio_size", $0 ) ret( 0 ) }
if $mj <= 0 { ret( 0 ) }
$len1 = ( ( $mj.frames - 1 ) * $mj.audio_freq ) div $mj.fps
$len2 = ( $mj.frames * $mj.audio_freq ) div $mj.fps
$len = $len2 - $len1
ret( $len )
}
fn mjpeg_encoder_write_audio( $mj, $audio, $offset_bytes, $size_bytes )
{
if $0 != 4 { mjpeg_fn_error( "mjpeg_encoder_write_audio", $0 ) ret( 0 ) }
if $mj <= 0 { ret( 0 ) }
$bytes = mjpeg_encoder_get_audio_size( $mj ) * $mj.audio_ch * ( $mj.audio_bits div 8 )
if $mj.c_01wb <= 0
{
if $mj.flags & MJPEG_ENCODER_FLAG_USEINDEX
{
mjpeg_encoder_add_index( $mj, '01wb', 0, ftell( $mj.out ) - ( $mj.c_movi.size_ptr + 4 ), $bytes )
}
$mj.c_01wb = riff_chunk_open( $mj.c_movi, "01wb", $mj.out )
}
if $audio <= 0
{
//Silent chunk:
if $mj.silent_chunk <= 0
{
$mj.silent_chunk = new( $bytes, 1, INT8 )
clean( $mj.silent_chunk )
}
$audio = $mj.silent_chunk
}
riff_chunk_write_data( $mj.c_01wb, $audio, $offset_bytes, $size_bytes )
ret( $size_bytes )
}
fn mjpeg_encoder_next_frame( $mj )
{
if $0 != 1 { mjpeg_fn_error( "mjpeg_encoder_next_frame", $0 ) ret( -1 ) }
if $mj <= 0 { ret( -1 ) }
if $mj.c_01wb > 0
{
//Close audio chunk:
riff_chunk_close( $mj.c_01wb )
$mj.c_01wb = -1
}
$mj.frames + 1
ret( 0 )
}
fn mjpeg_encoder_add_index( $mj, $id, $flags, $offset, $size )
{
if $0 != 5 { mjpeg_fn_error( "mjpeg_encoder_add_index", $0 ) ret( -1 ) }
if $mj <= 0 { ret( -1 ) }
$idx = $mj.idx
$idx_ptr = $mj.idx_ptr
$idx[ $idx_ptr * 4 + 0 ] = $id
$idx[ $idx_ptr * 4 + 1 ] = $flags
$idx[ $idx_ptr * 4 + 2 ] = $offset
$idx[ $idx_ptr * 4 + 3 ] = $size
$idx_ptr + 1
if $idx_ptr >= get_size( $idx ) / 4
{
resize( $idx, ( $idx_ptr + 256 ) * 4, 1, INT32 )
}
$mj.idx_ptr = $idx_ptr
ret( 0 )
}
fn mjpeg_encoder_close( $mj )
{
if $0 != 1 { mjpeg_fn_error( "mjpeg_encoder_close", $0 ) ret( -1 ) }
if $mj <= 0 { ret( -1 ) }
if $mj.frames <= 0
{
logf( "MJPEG encoder error: no frames\n" )
}
riff_chunk_close( $mj.c_movi )
//Index:
if $mj.flags & MJPEG_ENCODER_FLAG_USEINDEX
{
$idx = $mj.idx
$idx_ptr = $mj.idx_ptr
$c = riff_chunk_open( $mj.c_avi, "idx1", $mj.out )
riff_chunk_write_data( $c, $idx, 0, $idx_ptr * 4 * 4 )
riff_chunk_close( $c )
}
//Fixup:
fseek( $mj.out, $mj.fix1_offset, SEEK_SET )
riff_write_int32( $mj.frames, $mj.out ) //totalFrames
fseek( $mj.out, $mj.fix2_offset, SEEK_SET )
riff_write_int32( $mj.frames, $mj.out ) //video stream length
if $mj.flags & MJPEG_ENCODER_FLAG_HASSOUND
{
fseek( $mj.out, $mj.fix3_offset, SEEK_SET )
riff_write_int32( ( $mj.frames * $mj.audio_freq ) div $mj.fps, $mj.out ) //audio stream length (number of frames)
}
riff_chunk_close( $mj.c_avi )
remove( $mj.silent_chunk )
remove( $mj.jpeg )
remove( $mj.idx )
remove( $mj )
ret( 0 )
}
Loading…
Cancel
Save