gimp-gap r831 - in trunk: . vid_enc_avi
- From: wolfgangh svn gnome org
- To: svn-commits-list gnome org
- Subject: gimp-gap r831 - in trunk: . vid_enc_avi
- Date: Mon, 13 Apr 2009 12:57:44 +0000 (UTC)
Author: wolfgangh
Date: Mon Apr 13 12:57:43 2009
New Revision: 831
URL: http://svn.gnome.org/viewvc/gimp-gap?rev=831&view=rev
Log:
fixed AVI1 encoder and avilib audio handling
Modified:
trunk/ChangeLog
trunk/README
trunk/vid_enc_avi/avilib.c
trunk/vid_enc_avi/avilib.h
trunk/vid_enc_avi/gap_enc_avi_main.c
Modified: trunk/README
==============================================================================
--- trunk/README (original)
+++ trunk/README Mon Apr 13 12:57:43 2009
@@ -1,4 +1,4 @@
-This is an unstable developers version 2.3.0 of the GIMP Video menu.
+This is an unstable developers version 2.5.0 of the GIMP Video menu.
The GIMP-GAP (GIMP Animation Package) is a collection of Plug-Ins
to extend the GIMP with capabilities to edit and create
@@ -7,12 +7,12 @@
Requires:
=========
- - gimp 2.2 or higher.
- This release was tested with gimp-2.2.11
+ - gimp 2.6.0 or higher.
+ This release was tested with gimp-2.6.6
Note: GIMP-GAP provides some features that are able to call many of the
GIMP standard filters. (plug-in programs that are shiped with
- gimp-2.2.11) Those features depend on the tested PDB interface
+ gimp-2.6.6) Those features depend on the tested PDB interface
versions and may fail if newer version are used.
- glib 2.8 or higher.
@@ -23,8 +23,7 @@
ffmpeg and libmpeg3 are included as sourcecode tarball in this
GIMP-GAP distribution.
- - nasm and the old gcc 3.3 version
- are required only in case when compiling of the
+ - nasm is required only in case when compiling of the
(optional) libmpeg3 is desired.
(nasm for the .asm sources)
@@ -34,15 +33,8 @@
Optional libs for decode/encode videofiles:
- - liba52 0.7.4
- recent ffmpeg libraries do no longer include
- this library that is required to encode/decode
- DVD audio, but ffmpeg supports dynamic linking of the liba52
- library if it is installed and the GPL licence
- configure option is set ( --enable-gpl --enable-liba52 )
- installation of liba52 is Recommanded.
- - xvid 1.0.2
+ - libxvid 1.0.2
The free XVID Codec is used for MPEG4 encoding
with the gimp-gap AVI fileformat encoding plug-in.
(the FFMPEG libs have built in MPEG4 support
@@ -50,6 +42,15 @@
You can get the xvid codec at:
http://www.xvid.org/downloads.html
+
+ Optional libs for decode/encode videofiles based on ffmpeg
+
+ - libbz2
+ - libfaac
+ - libfaad
+ - libmp3lame
+ - libx264
+
For general information about GIMP-GAP concepts
@@ -69,7 +70,7 @@
- ffmpeg
- libmpeg3
-Those libs are built automatically.
+Those libs are built automatically in case their requirements are available.
Configuration options for those libs can be set by editing the
files:
@@ -79,20 +80,20 @@
Those configure_option files are read by the master .configure script
-Installation:
- ./autogen.sh # includes the ./configure call
+Installation from SVN source tree:
+==================================
+
+ ./autogen.sh # includes generation of the configure script ant the ./configure call
make
make install
-
-
A correct installation adds the follwing menu trees to the GIMP:
<Image>/Video
- <Xtns>/Split Video to Frames
+ <Filters>/Split Video to Frames
An overview of all menus can be found at
docs/reference/txt/INTRODUCTION.txt
@@ -102,18 +103,15 @@
Additional notes:
This version of GIMP-GAP is a separated Package since GIMP-1.3.x
- and does not compile/run with GIMP-1.2.x or older GIMP versions than 2.2.
+ and does not compile/run with GIMP-1.2.x or older GIMP versions than 2.4.
Notes:
======
-
- - GIMP 1.1.4 upto GIMP-1.2.x have included older versions of GIMP-GAP
- as standard plug-in (named gap) with no need of extra installation.
-
-
- GIMP-GAP provides frontend dialogs for:
- mplayer 1.0
+
+ OLD frontends:
- xanim 2.80.1 exporting edition (with the extensions from loki
entertainment)
- mpeg_encode (V1.5R2)
@@ -124,17 +122,19 @@
The programs mpeg2encode, mpeg_encode, and xanim
are old and you may not need them at all since GIMP-GAP-2.2
provides improved alternatives for all of them.
+ Note that the old frontends are not bulit by default.
- But it is higly recommanded to install the program mplayer.
- MPlayer does support very much videofileformats.
-
-
- If you like to use that stuff, you should install
- mplayer
+ If you want to use that old stuff, you should install
xanim 2.80.1 (loki)
mpeg_encode and mpeg_play
mpeg2encode and mpeg2decode
- on your system.
+ on your system and configure gimp-gap with the option --enable-unix-frontends
+
+
+
+ It is recommanded to install the program mplayer.
+ MPlayer does support very much videofileformats.
+
- The GIMP-GAP playback module provides audiosupport for audiofiles
in RIFF WAV format. The audiosupport is based on wavplay (tested
@@ -157,6 +157,11 @@
- There is no need to install all those external programs to
compile GIMP-GAP.
+
+ - GIMP 1.1.4 upto GIMP-1.2.x have included older versions of GIMP-GAP
+ as standard plug-in (named gap) with no need of extra installation.
+
+
Bugs
====
Modified: trunk/vid_enc_avi/avilib.c
==============================================================================
--- trunk/vid_enc_avi/avilib.c (original)
+++ trunk/vid_enc_avi/avilib.c Mon Apr 13 12:57:43 2009
@@ -25,6 +25,20 @@
*
*/
+/* hof: 2009.04.12
+ * use "00dc" for compressed video chunks and use "00db"
+ * uncompressed video (where AVI->compressor is 0)
+ *
+ * idx1 offsets are written realtive to data start adress in the movi chunk
+ +
+ * fixes at write/update of the AVI audio stream header related to pcm audiodata
+ * (samplesize, blockAlign and averageBytesPerSec.
+ * incorrect values resultes in video playback that is NOT synchron to the audio).
+ *
+ * avi_sampsize allow samplesize < 4 (that is required for mono samples 8 and 16 bit)
+ */
+
+
#include "avilib.h"
#include "../config.h"
@@ -152,7 +166,8 @@
int s;
s = ((AVI->track[j].a_bits+7)/8)*AVI->track[j].a_chans;
// if(s==0) s=1; /* avoid possible zero divisions */
- if(s<4) s=4; /* avoid possible zero divisions */
+ //if(s<4) s=4; /* avoid possible zero divisions */
+ if(s<1) s=1; /* avoid possible zero divisions */
return s;
}
@@ -510,7 +525,8 @@
OUTLONG(-1); /* Quality */
// ThOe /4
- OUTLONG(sampsize/4); /* SampleSize */
+ ///OUTLONG(sampsize/4); /* SampleSize */
+ OUTLONG(sampsize); /* SampleSize hof: full samplesize */
OUTLONG(0); /* Frame */
OUTLONG(0); /* Frame */
@@ -525,10 +541,17 @@
OUTSHRT(AVI->track[j].a_chans); /* Number of channels */
OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */
// ThOe
- OUTLONG(1000*AVI->track[j].mp3rate/8);
+
+ if(AVI->track[j].a_fmt == 1) {
+ // hof: calculate average bytes per sec for simple PCM encoded data
+ OUTLONG(AVI->track[j].a_rate * sampsize);
+ } else {
+ OUTLONG(1000*AVI->track[j].mp3rate/8);
+ }
//ThOe (/4)
- OUTSHRT(sampsize/4); /* BlockAlign */
+ ///OUTSHRT(sampsize/4); /* BlockAlign */
+ OUTSHRT(sampsize); /* BlockAlign hof: align to full sample size */
OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */
@@ -784,7 +807,8 @@
OUTLONG(-1); /* Quality */
// ThOe /4
- OUTLONG(sampsize/4); /* SampleSize */
+ ///OUTLONG(sampsize/4); /* SampleSize */
+ OUTLONG(sampsize); /* SampleSize hof: full samplesize */
OUTLONG(0); /* Frame */
OUTLONG(0); /* Frame */
@@ -799,10 +823,17 @@
OUTSHRT(AVI->track[j].a_chans); /* Number of channels */
OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */
// ThOe
- OUTLONG(1000*AVI->track[j].mp3rate/8);
+
+ if(AVI->track[j].a_fmt == 1) {
+ // hof: calculate average bytes per sec for simple PCM encoded data
+ OUTLONG(AVI->track[j].a_rate * sampsize);
+ } else {
+ OUTLONG(1000*AVI->track[j].mp3rate/8);
+ }
//ThOe (/4)
- OUTSHRT(sampsize/4); /* BlockAlign */
+ ///OUTSHRT(sampsize/4); /* BlockAlign */
+ OUTSHRT(sampsize); /* BlockAlign hof: align to full sample size */
OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */
@@ -913,6 +944,7 @@
int n;
unsigned char astr[5];
+ unsigned long idx_pos; /* index position relative to the movi chunk in file */
/* Check for maximum file length */
@@ -921,15 +953,24 @@
return -1;
}
+
+ if(AVI->movi_pos == 0)
+ AVI->movi_pos = AVI->pos;
+
+ idx_pos = 4 + (AVI->pos - AVI->movi_pos);
+
/* Add index entry */
//set tag for current audio track
sprintf((char *)astr, "0%1dwb", AVI->aptr+1);
if(audio)
- n = avi_add_index_entry(AVI,astr,0x00,AVI->pos,length);
+ n = avi_add_index_entry(AVI,astr,0x00,idx_pos,length);
else
- n = avi_add_index_entry(AVI,(unsigned char *) "00db",((keyframe)?0x10:0x0),AVI->pos,length);
+ if (AVI->compressor[0] == 0)
+ n = avi_add_index_entry(AVI,(unsigned char *) "00db",((keyframe)?0x10:0x0),idx_pos,length);
+ else
+ n = avi_add_index_entry(AVI,(unsigned char *) "00dc",((keyframe)?0x10:0x0),idx_pos,length);
if(n) return -1;
@@ -938,7 +979,10 @@
if(audio)
n = avi_add_chunk(AVI,(unsigned char *) astr,data,length);
else
- n = avi_add_chunk(AVI,(unsigned char *) "00db",data,length);
+ if (AVI->compressor[0] == 0)
+ n = avi_add_chunk(AVI,(unsigned char *) "00db",data,length);
+ else
+ n = avi_add_chunk(AVI,(unsigned char *) "00dc",data,length);
if (n) return -1;
@@ -963,10 +1007,19 @@
int AVI_dup_frame(avi_t *AVI)
{
+ unsigned long idx_pos; /* index position relative to the movi chunk in file */
+
if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
if(AVI->last_pos==0) return 0; /* No previous real frame */
- if(avi_add_index_entry(AVI,(unsigned char *)"00db",0x10,AVI->last_pos,AVI->last_len)) return -1;
+
+ idx_pos = 4 + (AVI->last_pos - AVI->movi_pos);
+
+ if (AVI->compressor[0] == 0)
+ if(avi_add_index_entry(AVI,(unsigned char *)"00db",0x10,idx_pos,AVI->last_len)) return -1;
+ else
+ if(avi_add_index_entry(AVI,(unsigned char *)"00dc",0x10,idx_pos,AVI->last_len)) return -1;
+
AVI->video_frames++;
AVI->must_use_index = 1;
return 0;
Modified: trunk/vid_enc_avi/avilib.h
==============================================================================
--- trunk/vid_enc_avi/avilib.h (original)
+++ trunk/vid_enc_avi/avilib.h Mon Apr 13 12:57:43 2009
@@ -117,6 +117,8 @@
int anum; // total number of audio tracks
int aptr; // current audio working track
+
+ unsigned long movi_pos; /* position of the movi chunk in file */
} avi_t;
Modified: trunk/vid_enc_avi/gap_enc_avi_main.c
==============================================================================
--- trunk/vid_enc_avi/gap_enc_avi_main.c (original)
+++ trunk/vid_enc_avi/gap_enc_avi_main.c Mon Apr 13 12:57:43 2009
@@ -599,6 +599,7 @@
static gint
p_avi_encode(GapGveAviGlobalParams *gpp)
{
+#define AUDIO_CHUNK_ADVANCE_FRAMES 16
GapGveAviValues *epp;
avi_t *l_avifile;
static GapGveStoryVidHandle *l_vidhand = NULL;
@@ -612,7 +613,6 @@
FILE *l_fp_inwav = NULL;
gint32 l_FRAME_size;
- gint32 datasize;
gint32 audio_size = 0;
gint32 audio_stereo = 0;
long l_sample_rate = 22050;
@@ -629,13 +629,17 @@
gint32 l_cnt_reused_frames;
gint32 l_check_flags;
gint32 l_out_frame_nr;
+
+ gdouble audio_samples_per_frame;
+ gint32 audio_samples_per_frame_gint32;
+ gint32 audio_bytes_per_frame_gint32;
+ gint32 audio_bytes_done_in_advance = 0;
+ gint32 l_frames_to_go;
gint32 wavsize = 0; /* Data size of the wav file */
long audio_margin = 8192; /* The audio chunk size */
- long audio_filled_100 = 0;
- long audio_per_frame_x100 = -1;
- long frames_per_second_x100 = 2500;
- gdouble frames_per_second_x100f = 2500;
+
+
char databuffer[300000]; /* For transferring audio data */
gint32 l_video_frame_chunk_size;
gint32 l_video_frame_chunk_hdr_size;
@@ -735,21 +739,33 @@
/* open WAVE file and set position to the 1.st audio databyte */
l_fp_inwav = gap_audio_wav_open_seek_data(gpp->val.audioname1);
+
+ if(gap_debug)
+ {
+ printf("Audiocheck results for file:%s\n", gpp->val.audioname1);
+ printf(" wavsize:%d\n", (int)wavsize);
+ printf(" l_samples:%d\n", (int)l_samples);
+ printf(" l_bytes_per_sample:%d\n", (int)l_bytes_per_sample);
+ printf(" l_channels:%d\n", (int)l_channels);
+ printf(" l_sample_rate:%d\n", (int)l_sample_rate);
+ printf(" audio_size (in bits):%d\n", (int)audio_size);
+ printf(" audio_stereo:%d\n", (int)audio_stereo);
+ }
}
/* Calculations for encoding the sound into the avi
*/
+ audio_samples_per_frame = l_sample_rate / MAX(1.0, gpp->val.framerate);
+ audio_samples_per_frame_gint32 = (audio_samples_per_frame + 0.5);
+ audio_bytes_per_frame_gint32 = audio_samples_per_frame_gint32 * l_bytes_per_sample;
- /* ORIGINAL CODE:
- * frames_per_second_x100 = (norm == 0) ? 2500 : 2997;
- * audio_per_frame_x100 = (100 * 100 * l_sample_rate * audio_size / 8 *
- * ((audio_stereo == TRUE) ? 2 : 1)) / frames_per_second_x100;
- */
-
- frames_per_second_x100f = (100.0 * gpp->val.framerate) + 0.5;
- frames_per_second_x100 = frames_per_second_x100f;
- audio_per_frame_x100 = (100 * 100 * l_sample_rate * l_bytes_per_sample) / MAX(1,frames_per_second_x100);
+ if(gap_debug)
+ {
+ printf(" audio_samples_per_frame:%f\n", (float)audio_samples_per_frame);
+ printf(" audio_samples_per_frame_gint32:%d\n", (int)audio_samples_per_frame_gint32);
+ printf(" audio_bytes_per_frame_gint32:%d\n", (int)audio_bytes_per_frame_gint32);
+ }
/* build AVI 4 byte codec name
@@ -786,11 +802,20 @@
, l_sample_rate
, (int)l_bits
, (int)WAVE_FORMAT_PCM /* format 1 == pcm */
- , (long)0 /* mp3rate (WHAT else shall i use if NO MP3 is supplied ???) */
+ , (long)((l_sample_rate * 8) / 1000) /* mp3rate,
+ * as seen seen in some AVI files)
+ * note that some mplayer versions freezes on attempt
+ * to playback AVI files with mp3rate 0
+ */
);
+
+ //l_avifile->must_use_index = 1;
}
- if(gap_debug) printf("next is INIT Encoder Instance ?\n");
+ if(gap_debug)
+ {
+ printf("next is INIT Encoder Instance ?\n");
+ }
#ifdef ENABLE_LIBXVIDCORE
if ((strcmp(epp->codec_name, GAP_AVI_CODEC_RGB) != 0)
@@ -810,7 +835,10 @@
printf("ERROR creation of XVID encoder instance FAILED\n");
l_rc = -1;
}
- if(gap_debug) printf("creation of XVID encoder instance DONE OK\n");
+ if(gap_debug)
+ {
+ printf("creation of XVID encoder instance DONE OK\n");
+ }
}
#endif
@@ -831,6 +859,10 @@
l_begin = gpp->val.range_from;
l_end = gpp->val.range_to;
l_max_master_frame_nr = abs(l_end - l_begin) + 1;
+ l_frames_to_go = l_max_master_frame_nr;
+
+
+ l_frames_to_go = l_max_master_frame_nr;
l_cur_frame_nr = l_begin;
while(l_rc >= 0)
@@ -864,7 +896,8 @@
} /* end setup of 1.st frame (l_cur_frame_nr == l_begin) */
- /* calling the frame fetcher */
+
+ /* encode VIDEO PART, call the frame fetcher */
{
gboolean l_fetch_ok;
gboolean l_force_keyframe;
@@ -1005,8 +1038,14 @@
if(buffer)
{
/* store the compressed video frame */
- if (gap_debug) printf("GAP_AVI: Writing frame nr. %d, size %d\n",
- (int)l_cur_frame_nr, (int)l_FRAME_size);
+ if (gap_debug)
+ {
+ printf("GAP_AVI: Writing frame nr. %d, size %d l_keyframe:%d\n"
+ , (int)l_cur_frame_nr
+ , (int)l_FRAME_size
+ , (int)l_keyframe
+ );
+ }
AVI_write_frame(l_avifile, buffer, l_FRAME_size, l_keyframe);
/* free the (un)compressed Frame data buffer */
g_free(buffer);
@@ -1027,48 +1066,90 @@
/* destroy the tmp image */
gimp_image_delete(l_tmp_image_id);
}
+
+
+ } /* end if l_rc == 0 */
+
+
+
+
+
/* encode AUDIO PART */
- /* As long as there is a video frame, "fill" the fake audio buffer */
- if (l_fp_inwav)
+ /* As long as there is a video frame, write audio chunks.
+ * set AUDIO_CHUNK_ADVANCE_FRAMES = 1 triggers writing of an audio chunk for each handled frame.
+ * values > 1 do write one longer audio chunk in advance for duration of the defined number of frames,
+ * in this case the next audio chunk is written after the number of video frames reached.
+ * in case the audio input is shorter than video playtime write the rest
+ * and stop writing audio for all further frame.
+ * in case the audio input is longer than video playtime it is truncated.
+ * (e.g. the remaining audio is not written to the resulting video file).
+ */
+ if ((l_fp_inwav) && (wavsize > 0))
{
- audio_filled_100 += audio_per_frame_x100;
- }
+ gint32 datasize;
+ gint32 l_frames_advance;
+
+
+ l_frames_advance = MIN(AUDIO_CHUNK_ADVANCE_FRAMES, l_frames_to_go);
+ audio_margin = MIN((audio_bytes_per_frame_gint32 * l_frames_advance), sizeof(databuffer) -1);
+
+ if(gap_debug)
+ {
+ printf("audio_bytes_per_frame:%d audio_margin: %d (to_go:%d advance:%d)\n"
+ , (int)audio_bytes_per_frame_gint32
+ , (int)audio_margin
+ , (int)l_frames_to_go
+ , (int)l_frames_advance
+ );
+ }
- /* Now "empty" the fake audio buffer, until it goes under the margin again */
- while ((audio_filled_100 >= (audio_margin * 100)) && (wavsize > 0))
- {
- if (gap_debug) printf("Audio processing: Audio buffer at %ld bytes.\n", audio_filled_100);
- if (wavsize >= audio_margin)
+ datasize = 0;
+ if (audio_bytes_done_in_advance <= 0)
{
- datasize = fread(databuffer, 1, audio_margin, l_fp_inwav);
- if (datasize != audio_margin)
- {
- printf("Warning: Read from wav file failed. (non-critical)\n");
- }
- wavsize -= audio_margin;
+ if (wavsize >= audio_margin)
+ {
+ datasize = fread(databuffer, 1, audio_margin, l_fp_inwav);
+ if (datasize != audio_margin)
+ {
+ printf("Warning: Read %d bytes from wav file failed. (got %d bytes)\n"
+ ,(int)audio_margin
+ ,(int)datasize
+ );
+ }
+ wavsize -= audio_margin;
+ }
+ else
+ {
+ datasize = fread(databuffer, 1, wavsize, l_fp_inwav);
+ if (datasize != wavsize)
+ {
+ printf("Warning: Read rest of %d bytes from wav file failed. (got %d bytes)\n"
+ ,(int)wavsize
+ ,(int)datasize
+ );
+ }
+ wavsize = 0;
+ }
}
- else
+ if (datasize > 0)
{
- datasize = fread(databuffer, 1, wavsize, l_fp_inwav);
- if (datasize != wavsize)
- {
- printf("Warning: Read from wav file failed. (non-critical)\n");
- }
- wavsize = 0;
- }
-
- if (gap_debug) printf("Now saving audio frame datasize:%d\n", (int)datasize);
+ if(gap_debug)
+ {
+ printf("Now saving audio frame datasize:%d\n", (int)datasize);
+ }
+ AVI_write_audio(l_avifile, databuffer, datasize);
- /*XXX ?? - TODO check if write in portions or all at once */
- /* XX - check if we should use write or append Procedure ? */
+ if(gap_debug)
+ {
+ printf("audio chunk written\n");
+ }
+ audio_bytes_done_in_advance = datasize;
+ }
+ audio_bytes_done_in_advance -= audio_bytes_per_frame_gint32;
+ }
- AVI_write_audio(l_avifile, databuffer, datasize);
- /*AVI_append_audio(l_avifile, databuffer, datasize);*/
- audio_filled_100 -= audio_margin * 100;
- }
- } /* end if l_rc == 0 */
l_percentage += l_percentage_step;
@@ -1097,9 +1178,12 @@
break;
}
l_cur_frame_nr += l_step;
+ l_frames_to_go--;
} /* end loop foreach frame */
+
+
if(l_avifile != NULL)
{
AVI_close(l_avifile);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]