Esempio n. 1
0
int main(int argc, char *argv []){

	//======================================================================================================================================================
	//	VARIABLES
	//======================================================================================================================================================

	// counters
	int i;
	int frames_processed;

	// parameters
	public_struct public;
	private_struct private[ALL_POINTS];

	//======================================================================================================================================================
	// 	FRAMES
	//======================================================================================================================================================

 	
	
	if(argc!=4){
		printf("ERROR: usage: heartwall <inputfile> <num of frames> <num of threads>\n");
		exit(1);
	}
	
	char* video_file_name;
	video_file_name = argv[1];
	
	avi_t* d_frames = (avi_t*)AVI_open_input_file(video_file_name, 1);														// added casting
	if (d_frames == NULL)  {
		   AVI_print_error((char *) "Error with AVI_open_input_file");
		   return -1;
	}

	public.d_frames = d_frames;
Esempio n. 2
0
/* for supported audio formats */
static int AV_synch_avi2avi(AVIData *data,
                            double vid_ms, double *aud_ms,
                            avi_t *in, avi_t *out)
{
    long bytes = 0;

    while (*aud_ms < vid_ms) {
        bytes = AVI_read_audio_chunk(in, data->data);
        if (bytes < 0) {
            AVI_print_error("AVI audio read frame");
            return -2;
        }

        if (out) {
            if (AVI_write_audio(out, data->data, bytes) < 0) {
                AVI_print_error("AVI write audio frame");
                return -1;
            }
        }

        // pass-through null frames (!?)
        if (bytes == 0) {
            *aud_ms = vid_ms;
            break; // !?
        }

        if (data->vbr
         && tc_get_audio_header(data->data, bytes, data->format,
                                NULL, NULL, &(data->mp3rate)) < 0) {
            // if this is the last frame of the file, slurp in audio chunks
            //if (n == frames-1) continue;
            *aud_ms = vid_ms;
        } else  {
            if (data->vbr)
                data->mp3rate *= 1000;
            *aud_ms += (bytes*8.0*1000.0)/(double)data->mp3rate;
        }
    }
    return 0;
}
Esempio n. 3
0
/* for UNsupported audio formats */
static int AV_synch_avi2avi_raw(AVIData *data,
                                avi_t *in, avi_t *out)
{
    long bytes = 0;

    do {
        bytes = AVI_read_audio_chunk(in, data->data);
        if (bytes < 0) {
            AVI_print_error("AVI audio read frame");
            return -2;
        }

        if (out) {
            if (AVI_write_audio(out, data->data, bytes) < 0) {
                AVI_print_error("AVI write audio frame");
                return -1;
            }
        }
    } while (AVI_can_read_audio(in));

    return 0;
}
Esempio n. 4
0
int main(int argc, char *argv[])
{
    struct common_struct rtf;
    struct AVIStreamHeader ash, vsh;
    avi_t *avifile;
    int err, fd, id = 0, track_num = 0, n, ch, debug = TC_FALSE;
    int brate = 0, val1 = 0, val2 = 1, a_rate, a_chan, a_bits;
    long ah_off = 0, af_off = 0, vh_off = 0, vf_off = 0;
    char codec[5], *str = NULL, *filename = NULL;
    uint32_t change = CHANGE_NOTHING;

    ac_init(AC_ALL);

    if (argc==1) usage(EXIT_FAILURE);

    while ((ch = getopt(argc, argv, "df:i:N:F:vb:e:a:?h")) != -1) {
        switch (ch) {
          case 'N':
            VALIDATE_OPTION;
            id = strtol(optarg, NULL, 16);
            if (id <  0) {
                tc_log_error(EXE, "invalid parameter set for option -N");
            } else {
                change |= CHANGE_AUDIO_FMT;
            }
            break;

          case 'a':
            VALIDATE_OPTION;
            track_num = atoi(optarg);
            if (track_num < 0)
                usage(EXIT_FAILURE);
            break;

          case 'f':
            VALIDATE_OPTION;
	        n = sscanf(optarg,"%d,%d", &val1, &val2);
            if (n != 2 || val1 < 0 || val2 < 0) {
                tc_log_error(EXE, "invalid parameter set for option -f");
            } else {
                change |= CHANGE_VIDEO_FPS;
            }
            break;

          case 'F':
            VALIDATE_OPTION;
            str = optarg;
            if(strlen(str) > 4 || strlen(str) == 0) {
                tc_log_error(EXE, "invalid parameter set for option -F");
            } else {
                change |= CHANGE_VIDEO_FOURCC;
            }
            break;

          case 'i':
            VALIDATE_OPTION;
            filename = optarg;
            break;

          case 'b':
            VALIDATE_OPTION;
            brate = atoi(optarg);
            change |= CHANGE_AUDIO_BR;
            break;

          case 'v':
            version();
            exit(0);

          case 'e':
            VALIDATE_OPTION;
            n = sscanf(optarg,"%d,%d,%d", &a_rate, &a_bits, &a_chan);
            switch (n) {
              case 3:
                change |= CHANGE_AUDIO_RATE;
              case 2:
                change |= CHANGE_AUDIO_BITS;
              case 1:
                change |= CHANGE_AUDIO_CHANS;
                break;
              default:
                tc_log_error(EXE, "invalid parameter set for option -e");
            }
            break;

          case 'd':
            debug = TC_TRUE;
            break;
          case 'h':
            usage(EXIT_SUCCESS);
          default:
            usage(EXIT_FAILURE);
        }
    }

    if (!filename)
        usage(EXIT_FAILURE);

    tc_log_info(EXE, "scanning AVI-file %s for header information", filename);

    avifile = AVI_open_input_file(filename, 1);
    if (!avifile) {
        AVI_print_error("AVI open");
        exit(1);
    }

    AVI_info(avifile);

    if (AVI_set_audio_track(avifile, track_num) < 0) {
        tc_log_error(EXE, "invalid audio track");
    }

    ah_off = AVI_audio_codech_offset(avifile);
    af_off = AVI_audio_codecf_offset(avifile);
    vh_off = AVI_video_codech_offset(avifile);
    vf_off = AVI_video_codecf_offset(avifile);

    if (debug) {
        tc_log_info(EXE,
                    "offsets: ah=%li af=%li vh=%li vf=%li",
                    ah_off, af_off, vh_off, vf_off);
    }

    AVI_close(avifile);

    fd = open(filename, O_RDWR);
    if (fd < 0) {
        perror("open");
        exit(1);
    }

    lseek(fd, vh_off, SEEK_SET);
    hdr_read("video codec [h]", fd, codec, 4);
    codec[4] = 0;

    lseek(fd, vf_off, SEEK_SET);
    hdr_read("video codec [f]", fd, codec, 4);
    codec[4] = 0;

    if (change & CHANGE_VIDEO_FPS) {
        lseek(fd, vh_off-4, SEEK_SET);
        hdr_read("video fps", fd, &vsh, sizeof(vsh));

	    vsh.dwRate  = (long)val1;
	    vsh.dwScale = (long)val2;

        lseek(fd, vh_off-4, SEEK_SET);
        hdr_write("video fps", fd, &vsh, sizeof(vsh));
    }

    if (change & CHANGE_VIDEO_FOURCC) {
        lseek(fd,vh_off,SEEK_SET);

        if (strncmp(str,"RGB",3) == 0) {
            hdr_write("video 4cc", fd, codec, 4);
        } else {
            hdr_write("video 4cc", fd, str, 4);
        }

        lseek(fd,vf_off,SEEK_SET);

        if(strncmp(str,"RGB",3)==0) {
	        memset(codec, 0, 4);
            hdr_write("video 4cc", fd, codec, 4);
        } else {
            hdr_write("video 4cc", fd, str, 4);
        }
    }

    if (NEED_AUDIO_CHANGE(change)) {
        lseek(fd, ah_off, SEEK_SET);
        hdr_read("audio header [h]", fd, &ash, sizeof(ash));

        lseek(fd, af_off, SEEK_SET);
        hdr_read("audio header [f]", fd, &rtf, sizeof(rtf));

        if (change & CHANGE_AUDIO_FMT) {
            rtf.wFormatTag = (unsigned short) id;
        }
        if (change & CHANGE_AUDIO_BR) {
	        rtf.dwAvgBytesPerSec = (long) 1000*brate/8;
        	ash.dwRate = (long) 1000*brate/8;
	        ash.dwScale = 1;
        }
        if (change & CHANGE_AUDIO_CHANS) {
            rtf.wChannels = (short) a_chan;
        }
        if (change & CHANGE_AUDIO_BITS) {
            rtf.wBitsPerSample = (short) a_bits;
        }
        if (change & CHANGE_AUDIO_RATE) {
            rtf.dwSamplesPerSec = (long) a_rate;
        }

        lseek(fd, ah_off ,SEEK_SET);
        hdr_write("audio header [h]", fd, &ash, sizeof(ash));
        lseek(fd, af_off ,SEEK_SET);
        hdr_write("audio header [f]", fd, &rtf, sizeof(rtf));
    }

    err = close(fd);
    if (err) {
        perror("close");
        exit(1);
    }

    avifile = AVI_open_input_file(filename, 1);
    if (!avifile) {
        AVI_print_error("AVI open");
        exit(1);
    }

    tc_log_info(EXE, "updated AVI file %s", filename);

    AVI_info(avifile);

    AVI_close(avifile);

    return 0;
}
Esempio n. 5
0
// Main
int main(int argc, char ** argv) {

	// Choose the best GPU in case there are multiple available
	choose_GPU();

	// Keep track of the start time of the program
	long long program_start_time = get_time();
	
	if (argc !=3){
	fprintf(stderr, "usage: %s <input file> <number of frames to process>", argv[0]);
	exit(1);
	}
	
	// Let the user specify the number of frames to process
	int num_frames = atoi(argv[2]);
	
	// Open video file
	char *video_file_name = argv[1];
	
	avi_t *cell_file = AVI_open_input_file(video_file_name, 1);
	if (cell_file == NULL)	{
		AVI_print_error("Error with AVI_open_input_file");
		return -1;
	}
	
	int i, j, *crow, *ccol, pair_counter = 0, x_result_len = 0, Iter = 20, ns = 4, k_count = 0, n;
	MAT *cellx, *celly, *A;
	double *GICOV_spots, *t, *G, *x_result, *y_result, *V, *QAX_CENTERS, *QAY_CENTERS;
	double threshold = 1.8, radius = 10.0, delta = 3.0, dt = 0.01, b = 5.0;
	
	// Extract a cropped version of the first frame from the video file
	MAT *image_chopped = get_frame(cell_file, 0, 1, 0);
	printf("Detecting cells in frame 0\n");
	
	// Get gradient matrices in x and y directions
	MAT *grad_x = gradient_x(image_chopped);
	MAT *grad_y = gradient_y(image_chopped);
	
	// Allocate for gicov_mem and strel
	gicov_mem = (float*) malloc(sizeof(float) * grad_x->m * grad_y->n);
	strel = (float*) malloc(sizeof(float) * strel_m * strel_n);

	m_free(image_chopped);

	int grad_m = grad_x->m;
	int grad_n = grad_y->n;
	
#pragma acc data create(sin_angle,cos_angle,theta,tX,tY) \
	create(gicov_mem[0:grad_x->m*grad_y->n])
{
	// Precomputed constants on GPU
	compute_constants();

	// Get GICOV matrices corresponding to image gradients
	long long GICOV_start_time = get_time();
	MAT *gicov = GICOV(grad_x, grad_y);
	long long GICOV_end_time = get_time();

	// Dilate the GICOV matrices
	long long dilate_start_time = get_time();
	MAT *img_dilated = dilate(gicov);
	long long dilate_end_time = get_time();
} /* end acc data */
	
	// Find possible matches for cell centers based on GICOV and record the rows/columns in which they are found
	pair_counter = 0;
	crow = (int *) malloc(gicov->m * gicov->n * sizeof(int));
	ccol = (int *) malloc(gicov->m * gicov->n * sizeof(int));
	for(i = 0; i < gicov->m; i++) {
		for(j = 0; j < gicov->n; j++) {
			if(!double_eq(m_get_val(gicov,i,j), 0.0) && double_eq(m_get_val(img_dilated,i,j), m_get_val(gicov,i,j)))
			{
				crow[pair_counter]=i;
				ccol[pair_counter]=j;
				pair_counter++;
			}
		}
	}

	GICOV_spots = (double *) malloc(sizeof(double) * pair_counter);
	for(i = 0; i < pair_counter; i++)
		GICOV_spots[i] = sqrt(m_get_val(gicov, crow[i], ccol[i]));
	
	G = (double *) calloc(pair_counter, sizeof(double));
	x_result = (double *) calloc(pair_counter, sizeof(double));
	y_result = (double *) calloc(pair_counter, sizeof(double));
	
	x_result_len = 0;
	for (i = 0; i < pair_counter; i++) {
		if ((crow[i] > 29) && (crow[i] < BOTTOM - TOP + 39)) {
			x_result[x_result_len] = ccol[i];
			y_result[x_result_len] = crow[i] - 40;
			G[x_result_len] = GICOV_spots[i];
			x_result_len++;
		}
	}
	
	// Make an array t which holds each "time step" for the possible cells
	t = (double *) malloc(sizeof(double) * 36);
	for (i = 0; i < 36; i++) {
		t[i] = (double)i * 2.0 * PI / 36.0;
	}
	
	// Store cell boundaries (as simple circles) for all cells
	cellx = m_get(x_result_len, 36);
	celly = m_get(x_result_len, 36);
	for(i = 0; i < x_result_len; i++) {
		for(j = 0; j < 36; j++) {
			m_set_val(cellx, i, j, x_result[i] + radius * cos(t[j]));
			m_set_val(celly, i, j, y_result[i] + radius * sin(t[j]));
		}
	}
	
	A = TMatrix(9,4);
	V = (double *) malloc(sizeof(double) * pair_counter);
	QAX_CENTERS = (double * )malloc(sizeof(double) * pair_counter);
	QAY_CENTERS = (double *) malloc(sizeof(double) * pair_counter);
	memset(V, 0, sizeof(double) * pair_counter);
	memset(QAX_CENTERS, 0, sizeof(double) * pair_counter);
	memset(QAY_CENTERS, 0, sizeof(double) * pair_counter);

	// For all possible results, find the ones that are feasibly leukocytes and store their centers
	k_count = 0;
	for (n = 0; n < x_result_len; n++) {
		if ((G[n] < -1 * threshold) || G[n] > threshold) {
			MAT * x, *y;
			VEC * x_row, * y_row;
			x = m_get(1, 36);
			y = m_get(1, 36);

			x_row = v_get(36);
			y_row = v_get(36);

			// Get current values of possible cells from cellx/celly matrices
			x_row = get_row(cellx, n, x_row);
			y_row = get_row(celly, n, y_row);
			uniformseg(x_row, y_row, x, y);

			// Make sure that the possible leukocytes are not too close to the edge of the frame
			if ((m_min(x) > b) && (m_min(y) > b) && (m_max(x) < cell_file->width - b) && (m_max(y) < cell_file->height - b)) {
				MAT * Cx, * Cy, *Cy_temp, * Ix1, * Iy1;
				VEC  *Xs, *Ys, *W, *Nx, *Ny, *X, *Y;
				Cx = m_get(1, 36);
				Cy = m_get(1, 36);
				Cx = mmtr_mlt(A, x, Cx);
				Cy = mmtr_mlt(A, y, Cy);
				
				Cy_temp = m_get(Cy->m, Cy->n);
				
				for (i = 0; i < 9; i++)
					m_set_val(Cy, i, 0, m_get_val(Cy, i, 0) + 40.0);
					
				// Iteratively refine the snake/spline
				for (i = 0; i < Iter; i++) {
					int typeofcell;
					
					if(G[n] > 0.0) typeofcell = 0;
					else typeofcell = 1;
					
					splineenergyform01(Cx, Cy, grad_x, grad_y, ns, delta, 2.0 * dt, typeofcell);
				}
				
				X = getsampling(Cx, ns);
				for (i = 0; i < Cy->m; i++)
					m_set_val(Cy_temp, i, 0, m_get_val(Cy, i, 0) - 40.0);
				Y = getsampling(Cy_temp, ns);
				
				Ix1 = linear_interp2(grad_x, X, Y);
				Iy1 = linear_interp2(grad_x, X, Y);
				Xs = getfdriv(Cx, ns);
				Ys = getfdriv(Cy, ns);
				
				Nx = v_get(Ys->dim);
				for (i = 0; i < Ys->dim; i++)
					v_set_val(Nx, i, v_get_val(Ys, i) / sqrt(v_get_val(Xs, i)*v_get_val(Xs, i) + v_get_val(Ys, i)*v_get_val(Ys, i)));
					
				Ny = v_get(Xs->dim);
				for (i = 0; i < Xs->dim; i++)
					v_set_val(Ny, i, -1.0 * v_get_val(Xs, i) / sqrt(v_get_val(Xs, i)*v_get_val(Xs, i) + v_get_val(Ys, i)*v_get_val(Ys, i)));
					
				W = v_get(Nx->dim);
				for (i = 0; i < Nx->dim; i++)
					v_set_val(W, i, m_get_val(Ix1, 0, i) * v_get_val(Nx, i) + m_get_val(Iy1, 0, i) * v_get_val(Ny, i));
					
				V[n] = mean(W) / std_dev(W);
				
				// Find the cell centers by computing the means of X and Y values for all snaxels of the spline contour
				QAX_CENTERS[k_count] = mean(X);
				QAY_CENTERS[k_count] = mean(Y) + TOP;
				
				k_count++;
				
				// Free memory
				v_free(W);
				v_free(Ny);
				v_free(Nx);
				v_free(Ys);
				v_free(Xs);
				m_free(Iy1);
				m_free(Ix1);
				v_free(Y);
				v_free(X);
				m_free(Cy_temp);
				m_free(Cy);
				m_free(Cx);				
			}

			// Free memory
			v_free(y_row);
			v_free(x_row);
			m_free(y);
			m_free(x);
		}
	}
	
	// Free memory
	free(gicov_mem);
	free(strel);
	free(V);
	free(ccol);
	free(crow);
	free(GICOV_spots);
	free(t);
	free(G);
	free(x_result);
	free(y_result);
	m_free(A);
	m_free(celly);
	m_free(cellx);
	m_free(img_dilated);
	m_free(gicov);
	m_free(grad_y);
	m_free(grad_x);
	
	// Report the total number of cells detected
	printf("Cells detected: %d\n\n", k_count);
	
	// Report the breakdown of the detection runtime
	printf("Detection runtime\n");
	printf("-----------------\n");
	printf("GICOV computation: %.5f seconds\n", ((float) (GICOV_end_time - GICOV_start_time)) / (1000*1000));
	printf("   GICOV dilation: %.5f seconds\n", ((float) (dilate_end_time - dilate_start_time)) / (1000*1000));
	printf("            Total: %.5f seconds\n", ((float) (get_time() - program_start_time)) / (1000*1000));
	
	// Now that the cells have been detected in the first frame,
	//  track the ellipses through subsequent frames
	if (num_frames > 1) printf("\nTracking cells across %d frames\n", num_frames);
	else                printf("\nTracking cells across 1 frame\n");
	long long tracking_start_time = get_time();
	int num_snaxels = 20;
	ellipsetrack(cell_file, QAX_CENTERS, QAY_CENTERS, k_count, radius, num_snaxels, num_frames);
	printf("           Total: %.5f seconds\n", ((float) (get_time() - tracking_start_time)) / (float) (1000*1000*num_frames));	
	
	// Report total program execution time
    printf("\nTotal application run time: %.5f seconds\n", ((float) (get_time() - program_start_time)) / (1000*1000));

	return 0;
}
Esempio n. 6
0
void extract_rgb(info_t *ipipe)
{
    uint8_t *video;
    avi_t *avifile = NULL;
    int key, error = 0;
    long frames, bytes, n;

    switch (ipipe->magic) {
      case TC_MAGIC_AVI:
	if (ipipe->nav_seek_file) {
            avifile = AVI_open_indexfd(ipipe->fd_in, 0, ipipe->nav_seek_file);
        } else {
            avifile = AVI_open_fd(ipipe->fd_in, 1);
        }
        if (NULL == avifile) {
            AVI_print_error("AVI open");
            import_exit(1);
        }

        frames = AVI_video_frames(avifile);
        if (ipipe->frame_limit[1] < frames) {
            frames = ipipe->frame_limit[1];
        }

        if (ipipe->verbose & TC_STATS) {
            tc_log_msg(__FILE__, "%ld video frames", frames);
        }

        video = tc_bufalloc(SIZE_RGB_FRAME);
        if (!video) {
            error = 1;
            break;
        }

        AVI_set_video_position(avifile, ipipe->frame_limit[0]);
        /* FIXME: should this be < rather than <= ? */
        for (n = ipipe->frame_limit[0]; n <= frames; n++) {
            bytes = AVI_read_frame(avifile, video, &key);
            if (bytes < 0) {
                error = 1;
                break;
            }
            if (tc_pwrite(ipipe->fd_out, video, bytes) != bytes) {
                error = 1;
                break;
            }
        }

        tc_buffree(video);
        break;

      case TC_MAGIC_RAW: /* fallthrough */
      default:
        if (ipipe->magic == TC_MAGIC_UNKNOWN) {
            tc_log_warn(__FILE__, "no file type specified, assuming %s",
			            filetype(TC_MAGIC_RAW));

            error = tc_preadwrite(ipipe->fd_in, ipipe->fd_out);
            break;
        }
    }

    if (error) {
        tc_log_perror(__FILE__, "error while writing data");
      	import_exit(error);
    }
}
Esempio n. 7
0
static int startavi(struct anim *anim)
{

	AviError avierror;
#if defined(_WIN32) && !defined(FREE_WINDOWS)
	HRESULT hr;
	int i, firstvideo = -1;
	int streamcount;
	BYTE abFormat[1024];
	LONG l;
	LPBITMAPINFOHEADER lpbi;
	AVISTREAMINFO avis;

	streamcount = anim->streamindex;
#endif

	anim->avi = MEM_callocN(sizeof(AviMovie), "animavi");

	if (anim->avi == NULL) {
		printf("Can't open avi: %s\n", anim->name);
		return -1;
	}

	avierror = AVI_open_movie(anim->name, anim->avi);

#if defined(_WIN32) && !defined(FREE_WINDOWS)
	if (avierror == AVI_ERROR_COMPRESSION) {
		AVIFileInit();
		hr = AVIFileOpen(&anim->pfile, anim->name, OF_READ, 0L);
		if (hr == 0) {
			anim->pfileopen = 1;
			for (i = 0; i < MAXNUMSTREAMS; i++) {
				if (AVIFileGetStream(anim->pfile, &anim->pavi[i], 0L, i) != AVIERR_OK) {
					break;
				}
				
				AVIStreamInfo(anim->pavi[i], &avis, sizeof(avis));
				if ((avis.fccType == streamtypeVIDEO) && (firstvideo == -1)) {
					if (streamcount > 0) {
						streamcount--;
						continue;
					}
					anim->pgf = AVIStreamGetFrameOpen(anim->pavi[i], NULL);
					if (anim->pgf) {
						firstvideo = i;

						/* get stream length */
						anim->avi->header->TotalFrames = AVIStreamLength(anim->pavi[i]);

						/* get information about images inside the stream */
						l = sizeof(abFormat);
						AVIStreamReadFormat(anim->pavi[i], 0, &abFormat, &l);
						lpbi = (LPBITMAPINFOHEADER)abFormat;
						anim->avi->header->Height = lpbi->biHeight;
						anim->avi->header->Width = lpbi->biWidth;
					}
					else {
						FIXCC(avis.fccHandler);
						FIXCC(avis.fccType);
						printf("Can't find AVI decoder for type : %4.4hs/%4.4hs\n",
						       (LPSTR)&avis.fccType,
						       (LPSTR)&avis.fccHandler);
					}
				}
			}

			/* register number of opened avistreams */
			anim->avistreams = i;

			/*
			 * Couldn't get any video streams out of this file
			 */
			if ((anim->avistreams == 0) || (firstvideo == -1)) {
				avierror = AVI_ERROR_FORMAT;
			}
			else {
				avierror = AVI_ERROR_NONE;
				anim->firstvideo = firstvideo;
			}
		}
		else {
			AVIFileExit();
		}
	}
#endif

	if (avierror != AVI_ERROR_NONE) {
		AVI_print_error(avierror);
		printf("Error loading avi: %s\n", anim->name);
		free_anim_avi(anim);
		return -1;
	}
	
	anim->duration = anim->avi->header->TotalFrames;
	anim->params = NULL;

	anim->x = anim->avi->header->Width;
	anim->y = anim->avi->header->Height;
	anim->interlacing = 0;
	anim->orientation = 0;
	anim->framesize = anim->x * anim->y * 4;

	anim->curposition = 0;
	anim->preseek = 0;

	/*  printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/

	return 0;
}
Esempio n. 8
0
static int merger(avi_t *out, char *file)
{
    avi_t *in;
    long frames, n, bytes;
    int key, j, aud_tracks;
    static int init = 0;
    static int vid_chunks = 0;

    double fps;
    static double vid_ms;
    static double aud_ms[AVI_MAX_TRACKS];
    int have_printed=0;
    int do_drop_video=0;

    if (!init) {
	for (j=0; j<AVI_MAX_TRACKS; j++)
	    aud_ms[j] = 0.0;
	vid_ms = 0;
	vid_chunks = 0;
	init = 1;
    }

    if(indexfile)  {
	if (NULL == (in = AVI_open_input_indexfile(file, 0, indexfile))) {
	    AVI_print_error("AVI open with indexfile");
	    return(-1);
	}
    }
    else if(NULL == (in = AVI_open_input_file(file,1))) {
	AVI_print_error("AVI open");
	return(-1);
    }

    AVI_seek_start(in);
    fps    =  AVI_frame_rate(in);
    frames =  AVI_video_frames(in);
    aud_tracks = AVI_audio_tracks(in);

    for (n=0; n<frames; ++n) {

      ++vid_chunks;
      vid_ms = vid_chunks*1000.0/fps;

      // audio
      for(j=0; j<aud_tracks; ++j) {

	  int ret;
	  double old_ms = aud_ms[j];

	  AVI_set_audio_track(in, j);
	  AVI_set_audio_track(out, j);

	  ret = sync_audio_video_avi2avi (vid_ms, &aud_ms[j], in, out);
	  if (ret<0) {
	      if (ret==-2) {
		  if (aud_ms[j] == old_ms) {
		      do_drop_video = 1;
		      if (!have_printed) {
			  fprintf(stderr, "\nNo audiodata left for track %d->%d (%.2f=%.2f) %s ..\n",
			      AVI_get_audio_track(in), AVI_get_audio_track(out),
			      old_ms, aud_ms[j], (do_drop_video && drop_video)?"breaking (-c)":"continuing");
			  have_printed++;
		      }
		  }
	      } else {
		  fprintf(stderr, "\nAn error happend at frame %ld track %d\n", n, j);
	      }
	  }

      }

      if (do_drop_video && drop_video) {
	  fprintf(stderr, "\n[avimerge] Dropping %ld frames\n", frames-n-1);
	  goto out;
      }

      // video
      bytes = AVI_read_frame(in, data, &key);

      if(bytes < 0) {
	AVI_print_error("AVI read video frame");
	return(-1);
      }

      if(AVI_write_frame(out, data, bytes, key)<0) {
	AVI_print_error("AVI write video frame");
	return(-1);
      }

      // progress
      fprintf(stderr, "[%s] (%06ld-%06ld) (%.2f <-> %.2f)\r", file, sum_frames, sum_frames + n, vid_ms, aud_ms[0]);
    }
out:
    fprintf(stderr, "\n");

    AVI_close(in);

    sum_frames += n;

    return(0);
}
Esempio n. 9
0
int main(int argc, char *argv[])
{
  avi_t *avifile, *avifile1, *avifile2;

  char *outfile=NULL, *infile=NULL, *audfile=NULL;

  long rate, mp3rate;

  int j, ch, cc=0, track_num=0, out_track_num=-1;
  int width, height, format=0, format_add, chan, bits, aud_error=0;

  double fps;

  char *codec;

  long offset, frames, n, bytes, aud_offset=0;

  int key;

  int aud_tracks;

  // for mp3 audio
  FILE *f=NULL;
  int len, headlen, chan_i, rate_i, mp3rate_i;
  unsigned long vid_chunks=0;
  char head[8];
  off_t pos;
  double aud_ms = 0.0, vid_ms = 0.0;
  double aud_ms_w[AVI_MAX_TRACKS];

  ac_init(AC_ALL);

  if(argc==1) usage(EXIT_FAILURE);

  while ((ch = getopt(argc, argv, "A:a:b:ci:o:p:f:x:?hv")) != -1) {

    switch (ch) {

    case 'i':

      if(optarg[0]=='-') usage(EXIT_FAILURE);
      infile = optarg;

      break;

    case 'A':

      if(optarg[0]=='-') usage(EXIT_FAILURE);
      out_track_num = atoi(optarg);

      if(out_track_num<-1) usage(EXIT_FAILURE);

      break;

    case 'a':

      if(optarg[0]=='-') usage(EXIT_FAILURE);
      track_num = atoi(optarg);

      if(track_num<0) usage(EXIT_FAILURE);

      break;

    case 'b':

      if(optarg[0]=='-') usage(EXIT_FAILURE);
      is_vbr = atoi(optarg);

      if(is_vbr<0) usage(EXIT_FAILURE);

      break;

    case 'c':

      drop_video = 1;

      break;

    case 'o':

      if(optarg[0]=='-') usage(EXIT_FAILURE);
      outfile = optarg;

      break;

    case 'p':

      if(optarg[0]=='-') usage(EXIT_FAILURE);
      audfile = optarg;

      break;

    case 'f':

      if(optarg[0]=='-') usage(EXIT_FAILURE);
      comfile = optarg;

      break;


    case 'x':

      if(optarg[0]=='-') usage(EXIT_FAILURE);
      indexfile = optarg;

      break;

    case 'v':
      version();
      exit(EXIT_SUCCESS);
    case 'h':
      usage(EXIT_SUCCESS);
    default:
      usage(EXIT_FAILURE);
    }
  }

  if(outfile == NULL || infile == NULL) usage(EXIT_FAILURE);

  printf("scanning file %s for video/audio parameter\n", infile);

  // open first file for video/audio info read only
  if(indexfile) {
      if (NULL == (avifile1 = AVI_open_input_indexfile(infile,0,indexfile))) {
	  AVI_print_error("AVI open with index file");
      }
  }
  else if(NULL == (avifile1 = AVI_open_input_file(infile,1))) {
      AVI_print_error("AVI open");
      exit(1);
  }

  AVI_info(avifile1);

  // safety checks

  if(strcmp(infile, outfile)==0) {
    printf("error: output filename conflicts with input filename\n");
    exit(1);
  }

  ch = optind;

  while (ch < argc) {

    if(tc_file_check(argv[ch]) != 0) {
      printf("error: file not found\n");
      exit(1);
    }

    if(strcmp(argv[ch++], outfile)==0) {
      printf("error: output filename conflicts with input filename\n");
      exit(1);
    }
  }

  // open output file
  if(NULL == (avifile = AVI_open_output_file(outfile))) {
    AVI_print_error("AVI open");
    exit(1);
  }


  // read video info;

  width  =  AVI_video_width(avifile1);
  height =  AVI_video_height(avifile1);

  fps    =  AVI_frame_rate(avifile1);
  codec  =  AVI_video_compressor(avifile1);

  //set video in outputfile
  AVI_set_video(avifile, width, height, fps, codec);

  if (comfile!=NULL)
    AVI_set_comment_fd(avifile, open(comfile, O_RDONLY));

  //multi audio tracks?
  aud_tracks = AVI_audio_tracks(avifile1);
  if (out_track_num < 0) out_track_num = aud_tracks;

  for(j=0; j<aud_tracks; ++j) {

      if (out_track_num == j) continue;
      AVI_set_audio_track(avifile1, j);

      rate   =  AVI_audio_rate(avifile1);
      chan   =  AVI_audio_channels(avifile1);
      bits   =  AVI_audio_bits(avifile1);

      format =  AVI_audio_format(avifile1);
      mp3rate=  AVI_audio_mp3rate(avifile1);
      //printf("TRACK %d MP3RATE %ld VBR %ld\n", j, mp3rate, AVI_get_audio_vbr(avifile1));

      //set next track of output file
      AVI_set_audio_track(avifile, j);
      AVI_set_audio(avifile, chan, rate, bits, format, mp3rate);
      AVI_set_audio_vbr(avifile, AVI_get_audio_vbr(avifile1));
  }

  if(audfile!=NULL) goto audio_merge;

  // close reopen in merger function
  AVI_close(avifile1);

  //-------------------------------------------------------------

  printf("merging multiple AVI-files (concatenating) ...\n");

  // extract and write to new files

  printf ("file %02d %s\n", ++cc, infile);
  merger(avifile, infile);

  while (optind < argc) {

    printf ("file %02d %s\n", ++cc, argv[optind]);
    merger(avifile, argv[optind++]);
  }

  // close new AVI file

  AVI_close(avifile);

  printf("... done merging %d file(s) in %s\n", cc, outfile);

  // reopen file for video/audio info
  if(NULL == (avifile = AVI_open_input_file(outfile,1))) {
    AVI_print_error("AVI open");
    exit(1);
  }
  AVI_info(avifile);

  return(0);

  //-------------------------------------------------------------


// *************************************************
// Merge the audio track of an additional AVI file
// *************************************************

 audio_merge:

  printf("merging audio %s track %d (multiplexing) into %d ...\n", audfile, track_num, out_track_num);

  // open audio file read only
  if(NULL == (avifile2 = AVI_open_input_file(audfile,1))) {
    int f=open(audfile, O_RDONLY), ret=0;
    char head[1024], *c;
    c = head;
    if (f>0 && (1024 == read(f, head, 1024)) ) {
      while ((c-head<1024-8) && (ret = tc_probe_audio_header(c, 8))<=0 ) {
	c++;
      }
      close(f);

      if (ret > 0) {
	aud_offset = c-head;
	//printf("found atrack 0x%x off=%ld\n", ret, aud_offset);
	goto merge_mp3;
      }
    }

    AVI_print_error("AVI open");
    exit(1);
  }

  AVI_info(avifile2);

  //switch to requested track

  if(AVI_set_audio_track(avifile2, track_num)<0) {
    fprintf(stderr, "invalid audio track\n");
  }

  rate   =  AVI_audio_rate(avifile2);
  chan   =  AVI_audio_channels(avifile2);
  bits   =  AVI_audio_bits(avifile2);

  format =  AVI_audio_format(avifile2);
  mp3rate=  AVI_audio_mp3rate(avifile2);

  //set next track
  AVI_set_audio_track(avifile, out_track_num);
  AVI_set_audio(avifile, chan, rate, bits, format, mp3rate);
  AVI_set_audio_vbr(avifile, AVI_get_audio_vbr(avifile2));

  AVI_seek_start(avifile1);
  frames =  AVI_video_frames(avifile1);
  offset = 0;

  printf ("file %02d %s\n", ++cc, infile);

  for (n=0; n<AVI_MAX_TRACKS; n++)
    aud_ms_w[n] = 0.0;
  vid_chunks=0;

  for (n=0; n<frames; ++n) {

    // video
    bytes = AVI_read_frame(avifile1, data, &key);

    if(bytes < 0) {
      AVI_print_error("AVI read video frame");
      return(-1);
    }

    if(AVI_write_frame(avifile, data, bytes, key)<0) {
      AVI_print_error("AVI write video frame");
      return(-1);
    }
    ++vid_chunks;
    vid_ms = vid_chunks*1000.0/fps;

    for(j=0; j<aud_tracks; ++j) {

      if (j == out_track_num) continue;
      AVI_set_audio_track(avifile1, j);
      AVI_set_audio_track(avifile, j);
      chan   = AVI_audio_channels(avifile1);

      // audio
      chan = AVI_audio_channels(avifile1);
      if(chan) {
	  sync_audio_video_avi2avi(vid_ms, &aud_ms_w[j], avifile1, avifile);
      }
    }


    // merge additional track

    // audio
    chan = AVI_audio_channels(avifile2);
    AVI_set_audio_track(avifile, out_track_num);

    if(chan) {
	sync_audio_video_avi2avi(vid_ms, &aud_ms, avifile2, avifile);
    }

    // progress
    fprintf(stderr, "[%s] (%06ld-%06ld)\r", outfile, offset, offset + n);

  }

  fprintf(stderr,"\n");

  offset = frames;

  //more files to merge?

  AVI_close(avifile1);

  while (optind < argc) {

    printf ("file %02d %s\n", ++cc, argv[optind]);

    if(NULL == ( avifile1 = AVI_open_input_file(argv[optind++],1))) {
      AVI_print_error("AVI open");
      goto finish;
    }

    AVI_seek_start(avifile1);
    frames =  AVI_video_frames(avifile1);

    for (n=0; n<frames; ++n) {

      // video
      bytes = AVI_read_frame(avifile1, data, &key);

      if(bytes < 0) {
	AVI_print_error("AVI read video frame");
	return(-1);
      }

      if(AVI_write_frame(avifile, data, bytes, key)<0) {
	AVI_print_error("AVI write video frame");
	return(-1);
      }

      ++vid_chunks;
      vid_ms = vid_chunks*1000.0/fps;

      // audio
      for(j=0; j<aud_tracks; ++j) {

	if (j == out_track_num) continue;
	AVI_set_audio_track(avifile1, j);
	AVI_set_audio_track(avifile, j);

	chan   = AVI_audio_channels(avifile1);

	if(chan) {
	  sync_audio_video_avi2avi(vid_ms, &aud_ms_w[j], avifile1, avifile);
	}
      }

      // merge additional track

      chan   = AVI_audio_channels(avifile2);
      AVI_set_audio_track(avifile, out_track_num);

      if(chan) {
	  sync_audio_video_avi2avi(vid_ms, &aud_ms, avifile2, avifile);
      } // chan

      // progress
      fprintf(stderr, "[%s] (%06ld-%06ld)\r", outfile, offset, offset + n);
    }

    fprintf(stderr, "\n");

    offset += frames;
    AVI_close(avifile1);
  }

 finish:

  // close new AVI file

  printf("... done multiplexing in %s\n", outfile);

  AVI_info(avifile);
  AVI_close(avifile);

  return(0);


// *************************************************
// Merge a raw audio file which is either MP3 or AC3
// *************************************************

merge_mp3:

  f = fopen(audfile,"rb");
  if (!f) { perror ("fopen"); exit(1); }

  fseek(f, aud_offset, SEEK_SET);
  len = fread(head, 1, 8, f);
  format_add  = tc_probe_audio_header(head, len);
  headlen = tc_get_audio_header(head, len, format_add, &chan_i, &rate_i, &mp3rate_i);
  fprintf(stderr, "... this looks like a %s track ...\n", (format_add==0x55)?"MP3":"AC3");

  fseek(f, aud_offset, SEEK_SET);

  //set next track
  AVI_set_audio_track(avifile, out_track_num);
  AVI_set_audio(avifile, chan_i, rate_i, 16, format_add, mp3rate_i);
  AVI_set_audio_vbr(avifile, is_vbr);

  AVI_seek_start(avifile1);
  frames =  AVI_video_frames(avifile1);
  offset = 0;

  for (n=0; n<AVI_MAX_TRACKS; ++n)
      aud_ms_w[n] = 0.0;

  for (n=0; n<frames; ++n) {

    // video
    bytes = AVI_read_frame(avifile1, data, &key);

    if(bytes < 0) {
      AVI_print_error("AVI read video frame");
      return(-1);
    }

    if(AVI_write_frame(avifile, data, bytes, key)<0) {
      AVI_print_error("AVI write video frame");
      return(-1);
    }

    vid_chunks++;
    vid_ms = vid_chunks*1000.0/fps;

    for(j=0; j<aud_tracks; ++j) {

      if (j == out_track_num) continue;
      AVI_set_audio_track(avifile1, j);
      AVI_set_audio_track(avifile, j);
      chan   = AVI_audio_channels(avifile1);

      if(chan) {
	sync_audio_video_avi2avi(vid_ms, &aud_ms_w[j], avifile1, avifile);
      }
    }


    // merge additional track

    if(headlen>4 && !aud_error) {
      while (aud_ms < vid_ms) {
	//printf("reading Audio Chunk ch(%ld) vms(%lf) ams(%lf)\n", vid_chunks, vid_ms, aud_ms);
	pos = ftell(f);

	len = fread (head, 1, 8, f);
	if (len<=0) { //eof
	  fprintf(stderr, "EOF in %s; continuing ..\n", audfile);
	  aud_error=1;
	  break;
	}

	if ( (headlen = tc_get_audio_header(head, len, format_add, NULL, NULL, &mp3rate_i))<0) {
	  fprintf(stderr, "Broken %s track #(%d)? skipping\n", (format_add==0x55?"MP3":"AC3"), aud_tracks);
	  aud_ms = vid_ms;
	  aud_error=1;
	} else { // look in import/tcscan.c for explanation
	  aud_ms += (headlen*8.0)/(mp3rate_i);
	}

	fseek (f, pos, SEEK_SET);

	len = fread (data, headlen, 1, f);
	if (len<=0) { //eof
	  fprintf(stderr, "EOF in %s; continuing ..\n", audfile);
	  aud_error=1;
	  break;
	}

	AVI_set_audio_track(avifile, out_track_num);

	if(AVI_write_audio(avifile, data, headlen)<0) {
	  AVI_print_error("AVI write audio frame");
	  return(-1);
	}

      }
    }

    // progress
    fprintf(stderr, "[%s] (%06ld-%06ld)\r", outfile, offset, offset + n);

  }

  fprintf(stderr,"\n");
  offset = frames;

  // more files?
  while (optind < argc) {

    printf ("file %02d %s\n", ++cc, argv[optind]);

    if(NULL == ( avifile1 = AVI_open_input_file(argv[optind++],1))) {
      AVI_print_error("AVI open");
      goto finish;
    }

    AVI_seek_start(avifile1);
    frames =  AVI_video_frames(avifile1);

    for (n=0; n<frames; ++n) {

      // video
      bytes = AVI_read_frame(avifile1, data, &key);

      if(bytes < 0) {
	AVI_print_error("AVI read video frame");
	return(-1);
      }

      if(AVI_write_frame(avifile, data, bytes, key)<0) {
	AVI_print_error("AVI write video frame");
	return(-1);
      }

      vid_chunks++;
      vid_ms = vid_chunks*1000.0/fps;

      for(j=0; j<aud_tracks; ++j) {

	if (j == out_track_num) continue;
	AVI_set_audio_track(avifile1, j);
	AVI_set_audio_track(avifile, j);
	chan   = AVI_audio_channels(avifile1);

	if(chan) {
	  sync_audio_video_avi2avi(vid_ms, &aud_ms_w[j], avifile1, avifile);
	}
      }

      // merge additional track
      // audio

      if(headlen>4 && !aud_error) {
	while (aud_ms < vid_ms) {
	  //printf("reading Audio Chunk ch(%ld) vms(%lf) ams(%lf)\n", vid_chunks, vid_ms, aud_ms);
	  pos = ftell(f);

	  len = fread (head, 8, 1, f);
	  if (len<=0) { //eof
	    fprintf(stderr, "EOF in %s; continuing ..\n", audfile);
	    aud_error=1; break;
	  }

	  if ( (headlen = tc_get_audio_header(head, len, format_add, NULL, NULL, &mp3rate_i))<0) {
	    fprintf(stderr, "Broken %s track #(%d)?\n", (format_add==0x55?"MP3":"AC3"), aud_tracks);
	    aud_ms = vid_ms;
	    aud_error=1;
	  } else { // look in import/tcscan.c for explanation
	    aud_ms += (headlen*8.0)/(mp3rate_i);
	  }

	  fseek (f, pos, SEEK_SET);

	  len = fread (data, headlen, 1, f);
	  if (len<=0) { //eof
	    fprintf(stderr, "EOF in %s; continuing ..\n", audfile);
	    aud_error=1; break;
	  }

	  AVI_set_audio_track(avifile, out_track_num);

	  if(AVI_write_audio(avifile, data, headlen)<0) {
	    AVI_print_error("AVI write audio frame");
	    return(-1);
	  }

	}
      }

      // progress
      fprintf(stderr, "[%s] (%06ld-%06ld)\r", outfile, offset, offset + n);
    }

    fprintf(stderr, "\n");

    offset += frames;
    AVI_close(avifile1);
  }


  if (f) fclose(f);

  printf("... done multiplexing in %s\n", outfile);

  AVI_close(avifile);

  return(0);
}
Esempio n. 10
0
int main(int argc, char *argv[])
{

  avi_t *avifile1=NULL;
  avi_t *avifile2=NULL;
  avi_t *avifile3=NULL;

  char *in_file=NULL, *out_file=NULL;

  long frames, bytes;

  double fps;

  char *codec;

  int track_num=0, aud_tracks;
  int encode_null=0;

  int i, j, n, key, shift=0;

  int ch, preload=0;

  long rate, mp3rate;

  int width, height, format, chan, bits;

  int be_quiet = 0;
  FILE *status_fd = stderr;

  /* for null frame encoding */
  char nulls[32000];
  long nullbytes=0;
  char tmp0[] = "/tmp/nullfile.00.avi"; /* XXX: use mktemp*() */

  buffer_list_t *ptr;

  double vid_ms = 0.0, shift_ms = 0.0, one_vid_ms = 0.0;
  double aud_ms [ AVI_MAX_TRACKS ];
  int aud_bitrate = 0;
  int aud_chunks = 0;

  ac_init(AC_ALL);

  if(argc==1) usage(EXIT_FAILURE);

  while ((ch = getopt(argc, argv, "a:b:vi:o:n:Nq?h")) != -1)
    {

	switch (ch) {

	case 'i':

	     if(optarg[0]=='-') usage(EXIT_FAILURE);
	    in_file=optarg;

	    break;

	case 'a':

	  if(optarg[0]=='-') usage(EXIT_FAILURE);
	  track_num = atoi(optarg);

	  if(track_num<0) usage(EXIT_FAILURE);

	  break;

	case 'b':

	  if(optarg[0]=='-') usage(EXIT_FAILURE);
	  is_vbr = atoi(optarg);

	  if(is_vbr<0) usage(EXIT_FAILURE);

	  break;

	case 'o':

	    if(optarg[0]=='-') usage(EXIT_FAILURE);
	    out_file=optarg;

	    break;

	case 'f':

	    if(optarg[0]=='-') usage(EXIT_FAILURE);
	    comfile = optarg;

	    break;

	case 'n':

	    if(sscanf(optarg,"%d", &shift)!=1) {
		fprintf(stderr, "invalid parameter for option -n\n");
		usage(EXIT_FAILURE);
	    }
	    break;

	case 'N':
	    encode_null=1;
	    break;
	case 'q':
	    be_quiet = 1;
	    break;
	case 'v':
	    version();
	    exit(0);
	    break;
      case 'h':
	usage(EXIT_SUCCESS);
      default:
	usage(EXIT_FAILURE);
      }
    }

  // check
  if(in_file==NULL || out_file == NULL) usage(EXIT_FAILURE);

  if(shift == 0) fprintf(stderr, "no sync requested - exit");

  memset (nulls, 0, sizeof(nulls));


  // open file
  if(NULL == (avifile1 = AVI_open_input_file(in_file,1))) {
      AVI_print_error("AVI open");
      exit(1);
  }

  if(strcmp(in_file, out_file)==0) {
      printf("error: output filename conflicts with input filename\n");
      exit(1);
  }

  if(NULL == (avifile2 = AVI_open_output_file(out_file))) {
    AVI_print_error("AVI open");
    exit(1);
  }

  if (be_quiet) {
    if (!(status_fd = fopen("/dev/null", "w"))) {
      fprintf(stderr, "Can't open /dev/null\n");
      exit(1);
    }
  }

  // read video info;

  AVI_info(avifile1);

  // read video info;

  frames =  AVI_video_frames(avifile1);
   width =  AVI_video_width(avifile1);
  height =  AVI_video_height(avifile1);

  fps    =  AVI_frame_rate(avifile1);
  codec  =  AVI_video_compressor(avifile1);

  //set video in outputfile
  AVI_set_video(avifile2, width, height, fps, codec);

  if (comfile!=NULL)
    AVI_set_comment_fd(avifile2, open(comfile, O_RDONLY));

  aud_tracks = AVI_audio_tracks(avifile1);

  for(j=0; j<aud_tracks; ++j) {

    AVI_set_audio_track(avifile1, j);

    rate   =  AVI_audio_rate(avifile1);
    chan   =  AVI_audio_channels(avifile1);
    bits   =  AVI_audio_bits(avifile1);

    format =  AVI_audio_format(avifile1);
    mp3rate=  AVI_audio_mp3rate(avifile1);

    //set next track of output file
    AVI_set_audio_track(avifile2, j);
    AVI_set_audio(avifile2, chan, rate, bits, format, mp3rate);
    AVI_set_audio_vbr(avifile2, is_vbr);
  }

  //switch to requested audio_channel

  if(AVI_set_audio_track(avifile1, track_num)<0) {
    fprintf(stderr, "invalid auto track\n");
  }

  AVI_set_audio_track(avifile2, track_num);

  if (encode_null) {
      char cmd[1024];

      rate   =  AVI_audio_rate(avifile2);
      chan   =  AVI_audio_channels(avifile2);
      bits   =  AVI_audio_bits(avifile2);
      format =  AVI_audio_format(avifile2);
      mp3rate=  AVI_audio_mp3rate(avifile2);

      if (bits==0) bits=16;
      if (mp3rate%2) mp3rate++;

      fprintf(status_fd, "Creating silent mp3 frame with current parameter\n");
      memset (cmd, 0, sizeof(cmd));
      tc_snprintf(cmd, sizeof(cmd), "transcode -i /dev/zero -o %s -x raw,raw"
	      " -n 0x1 -g 16x16 -y raw,raw -c 0-5 -e %ld,%d,%d -b %ld -q0",
	      tmp0, rate,bits,chan, mp3rate);

      printf(cmd);
      system(cmd);

      if(NULL == (avifile3 = AVI_open_input_file(tmp0,1))) {
	  AVI_print_error("AVI open");
	  exit(1);
      }

      nullbytes = AVI_audio_size(avifile3, 3);

      /* just read a few frames */
      if(AVI_read_audio(avifile3, nulls, nullbytes) < 0) {
	  AVI_print_error("AVI audio read frame");
	  return(-1);
      }
      memset (nulls, 0, sizeof(nulls));
      if(AVI_read_audio(avifile3, nulls, nullbytes) < 0) {
	  AVI_print_error("AVI audio read frame");
	  return(-1);
      }
      memset (nulls, 0, sizeof(nulls));
      if(AVI_read_audio(avifile3, nulls, nullbytes) < 0) {
	  AVI_print_error("AVI audio read frame");
	  return(-1);
      }


      /*
      printf("\nBytes (%ld): \n", nullbytes);
      {
	  int asd=0;
	  for (asd=0; asd<nullbytes; asd++){
	      printf("%x ",(unsigned char)nulls[asd]);
	  }
	  printf("\n");
      }
      */



  }

  vid_ms   = 0.0;
  shift_ms = 0.0;
  for (n=0; n<AVI_MAX_TRACKS; ++n)
      aud_ms[n] = 0.0;

  // ---------------------------------------------------------------------

  for (n=0; n<frames; ++n) {

    // video unchanged
    bytes = AVI_read_frame(avifile1, data, &key);

    if(bytes < 0) {
      AVI_print_error("AVI read video frame");
      return(-1);
    }

    if(AVI_write_frame(avifile2, data, bytes, key)<0) {
      AVI_print_error("AVI write video frame");
      return(-1);
    }

    vid_ms = (n+1)*1000.0/fps;


    // Pass-through all other audio tracks.
    for(j=0; j<aud_tracks; ++j) {

	// skip track we want to modify
	if (j == track_num) continue;

	// switch to track
	AVI_set_audio_track(avifile1, j);
	AVI_set_audio_track(avifile2, j);
	sync_audio_video_avi2avi(vid_ms, &aud_ms[j], avifile1, avifile2);
    }

    //switch to requested audio_channel
    if(AVI_set_audio_track(avifile1, track_num)<0) {
	fprintf(stderr, "invalid auto track\n");
    }
    AVI_set_audio_track(avifile2, track_num);
    shift_ms = (double)shift*1000.0/fps;
    one_vid_ms = 1000.0/fps;
    format = AVI_audio_format(avifile1);
    rate   = AVI_audio_rate(avifile1);
    chan   = AVI_audio_channels(avifile1);
    bits   = AVI_audio_bits(avifile1);
    bits   = bits==0?16:bits;
    mp3rate= AVI_audio_mp3rate(avifile1);


    if(shift>0) {

      // for n < shift, shift audio frames are discarded

      if(!preload) {

	if (tc_format_ms_supported(format)) {
	  for(i=0;i<shift;++i) {
	      //fprintf (stderr, "shift (%d) i (%d) n (%d) a (%d)\n", shift, i, n, aud_chunks);
	    while (aud_ms[track_num] < vid_ms + one_vid_ms*(double)i) {

		aud_bitrate = (format==0x1||format==0x2000)?1:0;
		aud_chunks++;
		if( (bytes = AVI_read_audio_chunk(avifile1, data)) <= 0) {
		    aud_ms[track_num] = vid_ms + one_vid_ms*i;
		    if (bytes == 0) continue;
		    AVI_print_error("AVI 2 audio read frame");
		    break;
		}

		if ( !aud_bitrate && tc_get_audio_header(data, bytes, format, NULL, NULL, &aud_bitrate)<0) {
		    // if this is the last frame of the file, slurp in audio chunks
		    if (n == frames-1) continue;
		    aud_ms[track_num] = vid_ms + one_vid_ms*i;
		} else
		    aud_ms[track_num] += (bytes*8.0)/(format==0x1?((double)(rate*chan*bits)/1000.0):
				       (format==0x2000?(double)(mp3rate):aud_bitrate));
	    }
	  }

	} else { // fallback
	    bytes=0;
	    for(i=0;i<shift;++i) {
		do {
		    if( (bytes = AVI_read_audio_chunk(avifile1, data)) < 0) {
			AVI_print_error("AVI audio read frame");
			return(-1);
		    }
		} while (AVI_can_read_audio(avifile1));
	    }
	}
	preload=1;
      }


      // copy rest of the track
      if(n<frames-shift) {
	if (tc_format_ms_supported(format)) {

	    while (aud_ms[track_num] < vid_ms + shift_ms) {

		aud_chunks++;
		aud_bitrate = (format==0x1||format==0x2000)?1:0;

		if( (bytes = AVI_read_audio_chunk(avifile1, data)) < 0) {
		    aud_ms[track_num] = vid_ms + shift_ms;
		    AVI_print_error("AVI 3 audio read frame");
		    break;
		}

		if(AVI_write_audio(avifile2, data, bytes) < 0) {
		    AVI_print_error("AVI 3 write audio frame");
		    return(-1);
		}

		fprintf(status_fd, "V [%05d][%08.2f] | A [%05d][%08.2f] [%05ld]\r", n, vid_ms, aud_chunks, aud_ms[track_num], bytes);

		if (bytes == 0) {
		    aud_ms[track_num] = vid_ms + shift_ms;
		    continue;
		}

		if(n>=frames-2*shift) {

		    // save audio frame for later
		    ptr = buffer_register(n);

		    if(ptr==NULL) {
			fprintf(stderr,"buffer allocation failed\n");
			break;
		    }

		    ac_memcpy(ptr->data, data, bytes);
		    ptr->size = bytes;
		    ptr->status = BUFFER_READY;
		}


		if ( !aud_bitrate && tc_get_audio_header(data, bytes, format, NULL, NULL, &aud_bitrate)<0) {
		    if (n == frames-1) continue;
		    aud_ms[track_num] = vid_ms + shift_ms;
		} else
		    aud_ms[track_num] += (bytes*8.0)/(format==0x1?((double)(rate*chan*bits)/1000.0):
				       (format==0x2000?(double)(mp3rate):aud_bitrate));
	    }

	} else { // fallback
	bytes = AVI_audio_size(avifile1, n+shift-1);

	do {
	    if( (bytes = AVI_read_audio_chunk(avifile1, data)) < 0) {
		AVI_print_error("AVI audio read frame");
		return(-1);
	    }

	    if(AVI_write_audio(avifile2, data, bytes) < 0) {
		AVI_print_error("AVI write audio frame");
		return(-1);
	    }

	    fprintf(status_fd, "V [%05d] | A [%05d] [%05ld]\r", n, n+shift, bytes);

	    if(n>=frames-2*shift) {

		// save audio frame for later
		ptr = buffer_register(n);

		if(ptr==NULL) {
		    fprintf(stderr,"buffer allocation failed\n");
		    break;
		}

		ac_memcpy(ptr->data, data, bytes);
		ptr->size = bytes;
		ptr->status = BUFFER_READY;
	    }
	} while (AVI_can_read_audio(avifile1));
	}
      }

      // padding at the end
      if(n>=frames-shift) {

	if (!ptrlen) {
	    ptr = buffer_retrieve();
	    ac_memcpy (ptrdata, ptr->data, ptr->size);
	    ptrlen = ptr->size;
	}

	if (tc_format_ms_supported(format)) {

	    while (aud_ms[track_num] < vid_ms + shift_ms) {

		aud_bitrate = (format==0x1||format==0x2000)?1:0;

		// mute this -- check if can mute (valid A header)!
		if (tc_probe_audio_header(ptrdata, ptrlen) > 0)
		    tc_format_mute(ptrdata, ptrlen, format);

		if(AVI_write_audio(avifile2, ptrdata, ptrlen) < 0) {
		    AVI_print_error("AVI write audio frame");
		    return(-1);
		}

		fprintf(status_fd, " V [%05d][%08.2f] | A [%05d][%08.2f] [%05ld]\r", n, vid_ms, n+shift, aud_ms[track_num], bytes);

		if ( !aud_bitrate && tc_get_audio_header(ptrdata, ptrlen, format, NULL, NULL, &aud_bitrate)<0) {
		    //if (n == frames-1) continue;
		    aud_ms[track_num] = vid_ms + shift_ms;
		} else
		    aud_ms[track_num] += (ptrlen*8.0)/(format==0x1?((double)(rate*chan*bits)/1000.0):
				       (format==0x2000?(double)(mp3rate):aud_bitrate));
	    }

	} else { // fallback

	// get next audio frame
	ptr = buffer_retrieve();

	while (1) {
	    printf("ptr->id (%d) ptr->size (%d)\n", ptr->id, ptr->size);

	    if(ptr==NULL) {
		fprintf(stderr,"no buffer found\n");
		break;
	    }

	    if (encode_null) {
		if(AVI_write_audio(avifile2, nulls, nullbytes)<0) {
		    AVI_print_error("AVI write audio frame");
		    return(-1);
		}
	    } else {
		// simple keep old frames to force exact time delay
		if(AVI_write_audio(avifile2, ptr->data, ptr->size)<0) {
		    AVI_print_error("AVI write audio frame");
		    return(-1);
		}
	    }

	    fprintf(status_fd, "V [%05d] | padding\r", n);

	    if (ptr->next && ptr->next->id == ptr->id) {
		buffer_remove(ptr);
		ptr = buffer_retrieve();
		continue;
	    }

	    buffer_remove(ptr);
	    break;
	}  // 1
      }
      }


// *************************************
// negative shift (pad audio at start)
// *************************************

    } else {

      if (tc_format_ms_supported(format)) {
	/*
	fprintf(status_fd, "n(%d) -shift(%d) shift_ms (%.2lf) vid_ms(%.2lf) aud_ms[%d](%.2lf) v-s(%.2lf)\n",
	    n, -shift, shift_ms, vid_ms, track_num, aud_ms[track_num], vid_ms + shift_ms);
	    */

	// shift<0 -> shift_ms<0 !
	while (aud_ms[track_num] < vid_ms) {
	    /*
	  fprintf(stderr, " 1 (%02d) %s frame_read len=%4ld (A/V) (%8.2f/%8.2f)\n",
	      n, format==0x55?"MP3":"AC3", bytes, aud_ms[track_num], vid_ms);
	      */

	  aud_bitrate = (format==0x1||format==0x2000)?1:0;

	  if( (bytes = AVI_read_audio_chunk(avifile1, data)) < 0) {
	    AVI_print_error("AVI 2 audio read frame");
	    aud_ms[track_num] = vid_ms;
	    break;
	    //return(-1);
	  }

	  // save audio frame for later
	  ptr = buffer_register(n);

	  if(ptr==NULL) {
	    fprintf(stderr,"buffer allocation failed\n");
	    break;
	  }

	  ac_memcpy(ptr->data, data, bytes);
	  ptr->size = bytes;
	  ptr->status = BUFFER_READY;

	  if(n<-shift) {

	    // mute this -- check if can mute!
	    if (tc_probe_audio_header(data, bytes) > 0)
		tc_format_mute(data, bytes, format);

	    // simple keep old frames to force exact time delay
	    if(AVI_write_audio(avifile2, data, bytes)<0) {
	      AVI_print_error("AVI write audio frame");
	      return(-1);
	    }

	    fprintf(status_fd, "V [%05d] | padding\r", n);

	  } else {
	    if (n==-shift)
		fprintf(status_fd, "\n");

	    // get next audio frame
	    ptr = buffer_retrieve();

	    if(ptr==NULL) {
	      fprintf(stderr,"no buffer found\n");
	      break;
	    }

	    if(AVI_write_audio(avifile2, ptr->data, ptr->size)<0) {
	      AVI_print_error("AVI write audio frame");
	      return(-1);
	    }
	    bytes = ptr->size;
	    ac_memcpy (data, ptr->data, bytes);

	    fprintf(status_fd, "V [%05d] | A [%05d]\r", n, ptr->id);

	    buffer_remove(ptr);
	  }

	  if ( !aud_bitrate && tc_get_audio_header(data, bytes, format, NULL, NULL, &aud_bitrate)<0) {
	    if (n == frames-1) continue;
	    aud_ms[track_num] = vid_ms;
	  } else
	    aud_ms[track_num] += (bytes*8.0)/(format==0x1?((double)(rate*chan*bits)/1000.0):
				       (format==0x2000?(double)(mp3rate):aud_bitrate));

	  /*
	  fprintf(stderr, " 1 (%02d) %s frame_read len=%4ld (A/V) (%8.2f/%8.2f)\n",
	      n, format==0x55?"MP3":"AC3", bytes, aud_ms[track_num], vid_ms);
	      */

	}








      } else { // no supported format

      bytes = AVI_audio_size(avifile1, n);


      if(bytes > SIZE_RGB_FRAME) {
	fprintf(stderr, "invalid frame size\n");
	return(-1);
      }

      if(AVI_read_audio(avifile1, data, bytes) < 0) {
	AVI_print_error("AVI audio read frame");
	return(-1);
      }

      // save audio frame for later
      ptr = buffer_register(n);

      if(ptr==NULL) {
	fprintf(stderr,"buffer allocation failed\n");
	break;
      }

      ac_memcpy(ptr->data, data, bytes);
      ptr->size = bytes;
      ptr->status = BUFFER_READY;


      if(n<-shift) {

	if (encode_null) {
	    if(AVI_write_audio(avifile2, nulls, nullbytes)<0) {
		AVI_print_error("AVI write audio frame");
		return(-1);
	    }
	} else {
	// simple keep old frames to force exact time delay
	    if(AVI_write_audio(avifile2, data, bytes)<0) {
		AVI_print_error("AVI write audio frame");
		return(-1);
	    }
	}

	fprintf(status_fd, "V [%05d] | padding\r", n);

      } else {

	// get next audio frame
	ptr = buffer_retrieve();

	if(ptr==NULL) {
	  fprintf(stderr,"no buffer found\n");
	  break;
	}

	if(AVI_write_audio(avifile2, ptr->data, ptr->size)<0) {
	  AVI_print_error("AVI write audio frame");
	  return(-1);
	}

	fprintf(status_fd, "V [%05d] | A [%05d]\r", n, ptr->id);

	buffer_remove(ptr);
      }
    }
    }
  }

  fprintf(status_fd, "\n");

  if (be_quiet) {
    fclose(status_fd);
  }

  AVI_close(avifile1);
  AVI_close(avifile2);

  if (avifile3) {
      memset(nulls, 0, sizeof(nulls));
      tc_snprintf(nulls, sizeof(nulls), "rm -f %s", tmp0);
      system(nulls);
      AVI_close(avifile3);
  }

  return(0);
}