You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

361 lines
13 KiB

/*
* probe_xml.c
*
* Copyright (C) Marzio Malanchini - March 2003
*
* This file is part of transcode, a video stream processing tool
*
* transcode is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* transcode is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "transcode.h"
#include "tcinfo.h"
#include "ioaux.h"
#include "tc.h"
#include "libtc/libtc.h"
#include <sys/types.h>
#ifdef HAVE_LIBXML2
#include "ioxml.h"
#include "probe_xml.h"
#define MAX_BUF 1024
extern int binary_dump;
static int f_check_video_H_W(audiovideo_t *p_audio_video)
{
audiovideo_t *p_temp;
int s_rc=0,s_video_tg_height=0,s_video_tg_width=0,s_v_height=0,s_v_width=0;
for (p_temp=p_audio_video;p_temp != NULL;p_temp=p_temp->p_next)
{
if (s_v_height == 0)
s_v_height=p_temp->s_v_height;
else if (s_v_height != p_temp->s_v_height)
s_rc|=0x01;
if (s_v_width == 0)
s_v_width=p_temp->s_v_width;
else if (s_v_width != p_temp->s_v_width)
s_rc|=0x02;
if ((p_temp->s_v_tg_height != 0) && (s_video_tg_height==0))
s_video_tg_height=p_temp->s_v_tg_height;
else if (p_temp->s_v_tg_height != 0)
{
if (p_temp->s_v_tg_height != s_video_tg_height)
{
tc_log_warn(__FILE__,"setting target height to %d (the target must be the same for all statements)",s_video_tg_height);
p_temp->s_v_tg_height=s_video_tg_height;
}
}
if ((p_temp->s_v_tg_width != 0) && (s_video_tg_width==0))
s_video_tg_width=p_temp->s_v_tg_width;
else if (p_temp->s_v_tg_width != 0)
{
if (p_temp->s_v_tg_width != s_video_tg_width)
{
tc_log_warn(__FILE__,"setting target width to %d (the target must be the same for all statements)",s_video_tg_width);
p_temp->s_v_tg_width=s_video_tg_width;
}
}
}
if (s_rc !=0)
{
if ((s_rc == 0x03) && (s_video_tg_height == 0) && (s_video_tg_width == 0))
{
tc_log_error(__FILE__,"the height and the width of the video tracks are different. Please specify target-width and target-height if you want to process the xml file");
return(1);
}
else if ((s_rc == 0x01) && (s_video_tg_height == 0))
{
tc_log_error(__FILE__,"the height of the video tracks are different. Please specify target-height if you want to process the xml file");
return(1);
}
else if ((s_rc == 0x02) && (s_video_tg_width == 0))
{
tc_log_error(__FILE__,"the width of the video tracks are different. Please specify target-height if you want to process the xml file");
return(1);
}
}
for (p_temp=p_audio_video;p_temp != NULL;p_temp=p_temp->p_next) //initialize all unset codec
{
if (s_video_tg_height!=0)
p_temp->s_v_tg_height=s_video_tg_height;
if (s_video_tg_width!=0)
p_temp->s_v_tg_width=s_video_tg_width;
}
return(0);
}
static void f_det_totale_video_frame(audiovideo_t *p_audio_video)
{
if ((p_audio_video->s_video_smpte==smpte)||(p_audio_video->s_video_smpte==smpte25))
p_audio_video->s_fps=25.00;
else if (p_audio_video->s_video_smpte==smpte30drop)
p_audio_video->s_fps=29.97;
p_audio_video->s_start_video+=(long)p_audio_video->s_start_v_time * p_audio_video->s_fps;
p_audio_video->s_end_video+=(long)p_audio_video->s_end_v_time * p_audio_video->s_fps;
}
static void f_det_totale_audio_frame(audiovideo_t *p_audio_video)
{
if ((p_audio_video->s_audio_smpte==smpte)||(p_audio_video->s_audio_smpte==smpte25))
p_audio_video->s_fps=25.00;
else if (p_audio_video->s_audio_smpte==smpte30drop)
p_audio_video->s_fps=29.97;
p_audio_video->s_start_audio+=(long)p_audio_video->s_start_a_time * p_audio_video->s_fps;
p_audio_video->s_end_audio+=(long)p_audio_video->s_end_a_time * p_audio_video->s_fps;
}
int f_build_xml_tree(info_t *ipipe,audiovideo_t *p_audiovideo,ProbeInfo *p_first_audio,ProbeInfo *p_first_video,long *s_tot_frames_audio, long *s_tot_frames_video)
{
audiovideo_t *p_audio_video;
char s_probe_cmd_buf[MAX_BUF+1];
FILE *p_fd;
ProbeInfo s_other_audio;
ProbeInfo s_other_video;
int s_first_element=0;
pid_t tc_probe_pid;
*s_tot_frames_audio=*s_tot_frames_video=0;
ipipe->error=f_manage_input_xml(ipipe->name,1,p_audiovideo);
if (ipipe->error==1)
{
f_manage_input_xml(ipipe->name,0,p_audiovideo);
return(-1);
}
for (p_audio_video=p_audiovideo->p_next;p_audio_video!=NULL;p_audio_video=p_audio_video->p_next)
{
if (p_audio_video->p_nome_video != NULL)
{
if(tc_snprintf(s_probe_cmd_buf, MAX_BUF, "tcprobe -i %s -d %d ",p_audio_video->p_nome_video,ipipe->verbose) < 0)
{
tc_log_error(__FILE__,"Buffer overflow");
ipipe->error=1;
break;
}
if (binary_dump)
{
if(tc_snprintf(s_probe_cmd_buf+strlen(s_probe_cmd_buf), MAX_BUF-strlen(s_probe_cmd_buf), "-B ") < 0)
{
tc_log_error(__FILE__,"Buffer overflow");
ipipe->error=1;
break;
}
if((p_fd = popen(s_probe_cmd_buf, "r"))== NULL)
{
tc_log_error(__FILE__,"Cannot open pipe: %s",strerror(errno));
ipipe->error=1;
break;
}
if (fread(&tc_probe_pid, sizeof(pid_t), 1, p_fd) !=1)
{
tc_log_error(__FILE__,"Cannot read pipe");
ipipe->error=1;
break;
}
if (fread(&s_other_video, sizeof(ProbeInfo), 1, p_fd) !=1)
{
tc_log_error(__FILE__,"Cannot read pipe");
ipipe->error=1;
break;
}
pclose(p_fd);
p_audio_video->s_v_real_codec=s_other_video.codec;
p_audio_video->s_v_width=s_other_video.width;
p_audio_video->s_v_height=s_other_video.height;
p_audio_video->s_a_real_codec=s_other_video.track[0].format;
p_audio_video->s_a_rate=s_other_video.track[0].samplerate;
p_audio_video->s_a_bits=s_other_video.track[0].bits;
p_audio_video->s_a_chan=s_other_video.track[0].chan;
p_audio_video->s_fps=s_other_video.fps;
if(s_other_video.magic == TC_MAGIC_UNKNOWN || s_other_video.magic == TC_MAGIC_PIPE || s_other_video.magic == TC_MAGIC_ERROR)
{
tc_log_error(__FILE__,"this version of transcode supports only");
tc_log_error(__FILE__,"xml file who containing dv avi or mov file type.");
tc_log_error(__FILE__,"Please clean up the %s file and restart.", ipipe->name);
tc_log_error(__FILE__,"file %s with filetype %s is invalid for this operation mode.", p_audio_video->p_nome_video, filetype(s_other_video.magic));
ipipe->error=1;
}
if (p_audio_video->s_v_magic == TC_MAGIC_UNKNOWN) //forced by ioxml.c
{
if (s_other_video.magic == TC_MAGIC_AVI) //if the magic is AVI and the codec is DV -> i need to use DV
if (s_other_video.codec == TC_CODEC_DV)
p_audio_video->s_v_magic=TC_MAGIC_DV_PAL;
else
p_audio_video->s_v_magic=s_other_video.magic;
else
p_audio_video->s_v_magic=s_other_video.magic;
}
if ((s_first_element & 0x02) == 0)
{
s_first_element|=0x02;
ac_memcpy(p_first_video,&s_other_video,sizeof(ProbeInfo));
}
f_det_totale_video_frame(p_audio_video);
if (p_audio_video->s_start_video > p_audio_video->s_end_video)
{
tc_log_error(__FILE__, "error: start frame is greater than end frame in file %s",p_audio_video->p_nome_video);
ipipe->error=1;
}
*s_tot_frames_video+=(p_audio_video->s_end_video - p_audio_video->s_start_video); //selected frames
}
else
system(s_probe_cmd_buf);
}
if (p_audio_video->p_nome_audio != NULL)
{
if(tc_snprintf(s_probe_cmd_buf, MAX_BUF, "tcprobe -i %s -d %d ",p_audio_video->p_nome_audio,ipipe->verbose) < 0)
{
tc_log_error(__FILE__,"Buffer overflow");
ipipe->error=1;
break;
}
if (binary_dump)
{
if(tc_snprintf(s_probe_cmd_buf+strlen(s_probe_cmd_buf), MAX_BUF-strlen(s_probe_cmd_buf), "-B ") < 0)
{
tc_log_error(__FILE__,"Buffer overflow");
ipipe->error=1;
break;
}
if((p_fd = popen(s_probe_cmd_buf, "r"))== NULL)
{
tc_log_error(__FILE__,"Cannot open pipe: %s",strerror(errno));
ipipe->error=1;
break;
}
if (fread(&tc_probe_pid, sizeof(pid_t), 1, p_fd) !=1)
{
tc_log_error(__FILE__,"Cannot read pipe");
ipipe->error=1;
break;
}
if (fread(&s_other_audio, sizeof(ProbeInfo), 1, p_fd) !=1)
{
tc_log_error(__FILE__,"Cannot read pipe");
ipipe->error=1;
break;
}
pclose(p_fd);
p_audio_video->s_a_real_codec=s_other_audio.track[0].format;
p_audio_video->s_a_rate=s_other_video.track[0].samplerate;
p_audio_video->s_a_bits=s_other_video.track[0].bits;
p_audio_video->s_a_chan=s_other_video.track[0].chan;
if(s_other_audio.magic == TC_MAGIC_UNKNOWN || s_other_audio.magic == TC_MAGIC_PIPE || s_other_audio.magic == TC_MAGIC_ERROR)
{
tc_log_error(__FILE__,"this version of transcode supports only");
tc_log_error(__FILE__,"xml file who containing dv avi or mov file type.");
tc_log_error(__FILE__,"Please clean up the %s file and restart.", ipipe->name);
tc_log_error(__FILE__,"file %s with filetype %s is invalid for this operation mode.", p_audio_video->p_nome_audio, filetype(s_other_audio.magic));
ipipe->error=1;
}
if (p_audio_video->s_a_magic == TC_MAGIC_UNKNOWN) //forced by ioxml.c
{
if (s_other_audio.magic == TC_MAGIC_AVI) //if the magic is AVI and the codec is DV -> i need to use DV
if (s_other_audio.track[0].format == CODEC_PCM) //for instant only PCM work
p_audio_video->s_a_magic=TC_MAGIC_AVI;
else
p_audio_video->s_a_magic=s_other_audio.magic;
else
p_audio_video->s_a_magic=s_other_audio.magic;
}
if ((s_first_element & 0x01) == 0)
{
s_first_element|=0x01;
ac_memcpy(p_first_audio,&s_other_audio,sizeof(ProbeInfo));
}
f_det_totale_audio_frame(p_audio_video);
if (p_audio_video->s_start_audio > p_audio_video->s_end_audio)
{
tc_log_error(__FILE__,"start frame is greater than end frame in file %s",p_audio_video->p_nome_video);
ipipe->error=1;
}
*s_tot_frames_audio+=(p_audio_video->s_end_audio - p_audio_video->s_start_audio); //selected frames
}
}
}
if (p_audiovideo->p_next !=NULL)
{
if ((ipipe->error=f_check_video_H_W(p_audiovideo->p_next)) == 0) //check height and width compatibility
{
if (p_audiovideo->p_next->s_v_tg_height !=0)
p_first_video->height=p_audiovideo->p_next->s_v_tg_height; //force height to target-height
if (p_audiovideo->p_next->s_v_tg_width !=0)
p_first_video->width=p_audiovideo->p_next->s_v_tg_width; //force width to target-width
}
}
return(s_first_element);
}
void probe_xml(info_t *ipipe)
{
audiovideo_t s_audiovideo;
ProbeInfo s_first_audio;
ProbeInfo s_first_video;
long s_tot_frames_audio,s_tot_frames_video;
int s_first_element;
if ((s_first_element=f_build_xml_tree(ipipe,&s_audiovideo,&s_first_audio,&s_first_video,&s_tot_frames_audio,&s_tot_frames_video)) == -1)
{
//there's an error during the call of f_build_xml_tree
return;
}
f_manage_input_xml(NULL,0,&s_audiovideo);
if (s_first_element & 0x03) //have video and audio tracks
{
ac_memcpy(ipipe->probe_info,&s_first_video,sizeof(ProbeInfo)); //setup the probe_info structure
ipipe->probe_info->frames=s_tot_frames_video; //Force sum of selected frames
ipipe->probe_info->num_tracks=s_first_audio.num_tracks;
ac_memcpy(ipipe->probe_info->track,&(s_first_audio.track),TC_MAX_AUD_TRACKS*sizeof(ProbeTrackInfo));
}
else if (s_first_element & 0x02) //have only video track
{
ac_memcpy(ipipe->probe_info,&s_first_video,sizeof(ProbeInfo)); //setup the probe_info structure
ipipe->probe_info->frames=s_tot_frames_video; //Force sum of selected frames
}
else if (s_first_element & 0x01) //have only audio tracks
{
ac_memcpy(ipipe->probe_info,&s_first_audio,sizeof(ProbeInfo)); //setup the probe_info structure
ipipe->probe_info->frames=s_tot_frames_audio; //Force sum of selected frames
}
s_first_element=0;
}
#else // HAVE_LIBXML2
void probe_xml(info_t *ipipe)
{
tc_log_error(__FILE__, "no support for XML compiled - exit.");
ipipe->error=1;
return;
}
#endif