1 /***************************************************************************
2                           ADM_edit.cpp  -  description
3                              -------------------
4     begin                : Thu Feb 28 2002
5     copyright            : (C) 2002/2008 by mean
6     email                : fixounet@free.fr
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 #include "ADM_cpp.h"
18 #include "ADM_default.h"
19 #include "A_functions.h"
20 #include "ADM_audioFilterInterface.h"
21 #include "audioEncoderApi.h"
22 #include "ADM_muxerProto.h"
23 #include "GUI_ui.h"
24 #include "avi_vars.h"
25 
26 #include <fcntl.h>
27 #include <errno.h>
28 
29 #include "fourcc.h"
30 #include "ADM_edit.hxx"
31 #include "ADM_edAudioTrackFromVideo.h"
32 #include "DIA_coreToolkit.h"
33 #include "prefs.h"
34 
35 
36 //#include "ADM_outputfmt.h"
37 #include "ADM_edPtsDts.h"
38 #include "ADM_vidMisc.h"
39 #include "ADM_confCouple.h"
40 #include "ADM_videoFilters.h"
41 #include "ADM_videoEncoderApi.h"
42 #include "ADM_videoFilterApi.h"
43 #include "ADM_preview.h"
44 #include "ADM_edAudioTrackExternal.h"
45 #include "ADM_coreVideoFilterFunc.h"
46 #include "ADM_coreVideoFilterFunc.h"
47 
48 extern uint8_t GUI_close(void);
49 extern bool GUI_GoToTime(uint64_t time);
50 extern void GUI_GoToKFrameTime(uint64_t time);
51 extern void GUI_NextFrame(uint32_t frameCount);
52 extern void GUI_PrevFrame(uint32_t frameCount);
53 extern void GUI_PrevBlackFrame(void);
54 extern void GUI_NextBlackFrame(void);;
55 
56 #if 0
57 /**
58     \fn getVideoDecoderName
59 */
60 const char          *ADM_Composer::getVideoDecoderName(void)
61 {
62     if(!_segments.getNbRefVideos()) return "????";
63      _VIDEOS *v=_segments.getRefVideo(0);
64     if(!v) return "????";
65     if(!v->decoder) return "????";
66     return v->decoder->getDecoderName();
67 }
68 #endif
setVideoCodec(const char * codec,CONFcouple * c)69 int ADM_Composer::setVideoCodec(const char *codec, CONFcouple *c)
70 {
71 	int idx = videoEncoder6_GetIndexFromName(codec);
72 
73 	if (idx == -1)
74 	{
75 		ADM_error("No such encoder :%s\n", codec);
76 		return false;
77 	}
78 
79 	// Select by index
80 	videoEncoder6_SetCurrentEncoder(idx);
81 	UI_setVideoCodec(idx);
82 
83 	if (c)
84 	{
85 		bool r = videoEncoder6_SetConfiguration(c, true);
86 		delete c;
87 
88 		return r;
89 	}
90 
91 	return true;
92 }
93 /**
94  * \fn setVideoCodecProfile
95  * \brief set a profile for the given video codec
96  * @param codec
97  * @param profile
98  * @return
99  */
setVideoCodecProfile(const char * codec,const char * profile)100 int         ADM_Composer::setVideoCodecProfile(const char *codec, const char *profile)
101 {
102         int idx = videoEncoder6_GetIndexFromName(codec);
103 
104 	if (idx == -1)
105 	{
106 		ADM_error("No such encoder :%s\n", codec);
107 		return false;
108 	}
109         // Select by index
110 	videoEncoder6_SetCurrentEncoder(idx);
111 	UI_setVideoCodec(idx);
112 
113 	if (profile)
114 	{
115             ADM_info("Setting profile %s\n",profile);
116             return videoEncoder6_SetProfile(profile);
117 	}
118 
119 	return true;
120 }
121 /**
122  * \fn changeVideoParam
123  * \brief same as above but you can only change one param
124  * @param codec
125  * @param c
126  * @return
127  */
changeVideoParam(const char * codec,CONFcouple * c)128 int ADM_Composer::changeVideoParam(const char *codec, CONFcouple *c)
129 {
130    int idx = videoEncoder6_GetIndexFromName(codec);
131 
132 	if (idx == -1)
133 	{
134 		ADM_error("No such encoder :%s\n", codec);
135 		return false;
136 	}
137 
138 	// Select by index
139 	videoEncoder6_SetCurrentEncoder(idx);
140 	UI_setVideoCodec(idx);
141 
142 	if (c)
143 	{
144 		bool r = videoEncoder6_SetConfiguration(c, false);
145 		delete c;
146 
147 		return r;
148 	}
149 
150 	return true;
151 }
addVideoFilter(const char * filter,CONFcouple * c)152 int ADM_Composer::addVideoFilter(const char *filter, CONFcouple *c)
153 {
154 	uint32_t filterTag = ADM_vf_getTagFromInternalName(filter);
155 
156 	printf("Adding Filter %s -> %" PRIu32"... \n", filter, filterTag);
157 
158 	bool r = (ADM_vf_addFilterFromTag(this, filterTag, c, false) != NULL);
159 
160 	if (c)
161 	{
162 		delete c;
163 	}
164 
165 	return r;
166 }
167 
getVideoCodec(void)168 char *ADM_Composer::getVideoCodec(void)
169 {
170 	uint32_t fcc;
171 	aviInfo info;
172 
173 	this->getVideoInfo(&info);
174 	fcc = info.fcc;
175 
176 	return ADM_strdup(fourCC::tostring(fcc));
177 }
178 
appendFile(const char * name)179 int ADM_Composer::appendFile(const char *name)
180 {
181 	return A_appendVideo(name);
182 }
183 /**
184     \fn saveAudio
185 */
saveAudio(int dex,const char * name)186 int ADM_Composer::saveAudio(int dex,const char *name)
187 {
188 	return A_audioSave(name);
189 }
190 
191 
clearFilters()192 void ADM_Composer::clearFilters()
193 {
194 	ADM_vf_clearFilters();
195 }
196 
openFile(const char * name)197 int	ADM_Composer::openFile(const char *name)
198 {
199 	return A_openVideo(name);
200 }
201 
saveFile(const char * name)202 int ADM_Composer::saveFile(const char *name)
203 {
204 	return A_Save(name);
205 }
206 
getCurrentMuxer()207 ADM_dynMuxer* ADM_Composer::getCurrentMuxer()
208 {
209 	return ListOfMuxers[UI_GetCurrentFormat()];
210 }
211 
getCurrentVideoEncoder()212 ADM_videoEncoder6* ADM_Composer::getCurrentVideoEncoder()
213 {
214 	return ListOfEncoders[videoEncoder6_GetIndexFromName(videoEncoder6_GetCurrentEncoderName())];
215 }
216 
setContainer(const char * cont,CONFcouple * c)217 bool ADM_Composer::setContainer(const char *cont, CONFcouple *c)
218 {
219 	int idx = ADM_MuxerIndexFromName(cont);
220 
221 	if (idx == -1)
222 	{
223 		ADM_error("Cannot find muxer for format=%s\n",cont);
224 		return false;
225 	}
226 
227 	ADM_info("setting container as index %d\n",idx);
228 	UI_SetCurrentFormat(idx);
229 	idx = ADM_MuxerIndexFromName(cont);
230 
231 	bool r = false;
232 
233 	if(idx != -1)
234 	{
235 		r = ADM_mx_setExtraConf(idx, c);
236 	}
237 
238 	if (c)
239 		delete c;
240 
241 	return r;
242 }
243 
saveImageBmp(const char * filename)244 int ADM_Composer::saveImageBmp(const char *filename)
245 {
246 	return A_saveImg(filename);
247 }
248 
saveImageJpg(const char * filename)249 int ADM_Composer::saveImageJpg(const char *filename)
250 {
251 	return A_saveJpg(filename);
252 }
253 
saveImagePng(const char * filename)254 int ADM_Composer::saveImagePng(const char *filename)
255 {
256     return A_savePng(filename);
257 }
258 //----------------------------------AUDIO-------------------------
259 /**
260     \fn setAudioMixer
261 */
setAudioMixer(int dex,const char * s)262 int ADM_Composer::setAudioMixer(int dex,const char *s)
263 {
264     EditableAudioTrack *ed=getEditableAudioTrackAt(dex);
265     if(!ed) return false;
266     CHANNEL_CONF c = AudioMuxerStringToId(s);
267     return ed->audioEncodingConfig.audioFilterSetMixer(c);
268 }
269 /**
270     \fn resetAudioFilter
271 */
272 
resetAudioFilter(int dex)273 void ADM_Composer::resetAudioFilter(int dex)
274 {
275     EditableAudioTrack *ed=getEditableAudioTrackAt(dex);
276     if(!ed) return ;
277     ed->audioEncodingConfig.reset();
278 
279 }
280 /**
281     \fn setAudioDrc
282 */
283 
setAudioDrc(int dex,bool mode)284 bool        ADM_Composer::setAudioDrc(int dex, bool mode)
285 {
286     EditableAudioTrack *ed=getEditableAudioTrackAt(dex);
287     if(!ed) return false;
288     return ed->audioEncodingConfig.audioFilterSetDrcMode(mode);
289 }
290 
291 /**
292     \fn getAudioDrc
293 */
294 
getAudioDrc(int dex)295 bool        ADM_Composer::getAudioDrc(int dex)
296 {
297     EditableAudioTrack *ed=getEditableAudioTrackAt(dex);
298     if(!ed) return false;
299     return ed->audioEncodingConfig.audioFilterGetDrcMode();
300 }
301 
302 
303 /**
304     \fn getAudioResample
305 */
getAudioResample(int dex)306 uint32_t ADM_Composer::getAudioResample(int dex)
307 {
308     EditableAudioTrack *ed=getEditableAudioTrackAt(dex);
309     if(!ed) return false;
310     return ed->audioEncodingConfig.audioFilterGetResample();
311 }
312 /**
313     \fn setAudioResample
314 */
setAudioResample(int dex,uint32_t newfq)315 void ADM_Composer::setAudioResample(int dex, uint32_t newfq)
316 {
317     EditableAudioTrack *ed=getEditableAudioTrackAt(dex);
318     if(!ed) return ;
319     ed->audioEncodingConfig.audioFilterSetResample(newfq);
320 }
321 /**
322     \fn setAudioShift
323 */
setAudioShift(int dex,bool mode,int32_t shiftms)324 bool ADM_Composer::setAudioShift(int dex, bool mode, int32_t shiftms)
325 {
326     EditableAudioTrack *ed=getEditableAudioTrackAt(dex);
327     if(!ed) return false;
328     ed->audioEncodingConfig.audioFilterSetShift(mode,shiftms);
329     return true;
330 }
331 /**
332     \fn getAudioShift
333 */
getAudioShift(int dex,bool * mode,int32_t * shiftms)334 bool ADM_Composer::getAudioShift(int dex, bool *mode, int32_t *shiftms)
335 {
336     EditableAudioTrack *ed=getEditableAudioTrackAt(dex);
337     if(!ed) return false;
338     ed->audioEncodingConfig.audioFilterGetShift(mode,shiftms);
339     return true;
340 }
341 /**
342     \fn setAudioCodec
343 */
setAudioCodec(int dex,const char * codec,CONFcouple * c)344 bool ADM_Composer::setAudioCodec(int dex,const char *codec, CONFcouple *c)
345 {
346     if(!audioCodecSetByName(dex,codec))
347     {
348         ADM_warning("Cannot set codec %s, track %d\n",codec,dex);
349         return false;
350     }
351     if(!setAudioExtraConf(dex,c))
352     {
353         ADM_warning("Cannot set configuration for codec %s, track %d\n",codec,dex);
354         return false;
355     }
356 //#warning memleak on *c ?
357     return true;
358 }
359 
360 /**
361     \fn setAudioFilterNormalise
362 */
setAudioFilterNormalise(int dex,ADM_GAINMode mode,int32_t gain,int32_t maxlevel)363 bool ADM_Composer::setAudioFilterNormalise(int dex, ADM_GAINMode mode, int32_t gain, int32_t maxlevel)
364 {
365     EditableAudioTrack *ed=getEditableAudioTrackAt(dex);
366     if(!ed) return false;
367     return ed->audioEncodingConfig.audioFilterSetNormalize(mode,gain,maxlevel);
368 }
369 /**
370     \fn getAudioFilterNormalise
371 */
getAudioFilterNormalise(int dex,ADM_GAINMode * mode,int32_t * gain,int32_t * maxlevel)372 bool ADM_Composer::getAudioFilterNormalise(int dex, ADM_GAINMode *mode, int32_t *gain, int32_t *maxlevel)
373 {
374     EditableAudioTrack *ed=getEditableAudioTrackAt(dex);
375     if(!ed) return false;
376     return ed->audioEncodingConfig.audioFilterGetNormalize(mode,gain,maxlevel);
377 }
378 /**
379     \fn getAudioFilterFrameRate
380 */
getAudioFilterFrameRate(int dex)381 FILMCONV ADM_Composer::getAudioFilterFrameRate(int dex)
382 {
383 	EditableAudioTrack *ed=getEditableAudioTrackAt(dex);
384     if(!ed) return FILMCONV_NONE;
385     return ed->audioEncodingConfig.audioFilterGetFrameRate();
386 }
387 /**
388     \fn setAudioFilterFrameRate
389 */
390 
setAudioFilterFrameRate(int dex,FILMCONV conf)391 bool ADM_Composer::setAudioFilterFrameRate(int dex,FILMCONV conf)
392 {
393     EditableAudioTrack *ed=getEditableAudioTrackAt(dex);
394     if(!ed) return false;
395     return ed->audioEncodingConfig.audioFilterSetFrameRate(conf);
396 }
397 /**
398     \fn clearAudioTracks
399 */
400 
clearAudioTracks(void)401 bool        ADM_Composer::clearAudioTracks(void)
402 {
403     // Remove all audio tracks
404     activeAudioTracks.clear();
405     return true;
406 }
407 /**
408     \fn setAudioFilterFrameRate
409 */
410 
addAudioTrack(int poolIndex)411 bool        ADM_Composer::addAudioTrack(int poolIndex)
412 {
413     ADM_info("** Adding active track from pool **\n");
414     activeAudioTracks.addTrack(poolIndex,audioTrackPool.at(poolIndex));
415     ADM_info("Adding track %d\n",poolIndex);
416     activeAudioTracks.dump();
417     return true;
418 }
419 /**
420     \fn addExternalAudioTrack
421 */
addExternalAudioTrack(const char * fileName)422 bool    ADM_Composer::addExternalAudioTrack(const char *fileName)
423 {
424     ADM_edAudioTrackExternal *ext=create_edAudioExternal(fileName);
425     if(!ext)
426     {
427         ADM_warning("Error","Cannot use that file as audio track (%s)\n",fileName);
428         return false;
429     }else
430     {
431         ADM_info("Adding %s as external audio track %d\n",fileName,audioTrackPool.size());
432         audioTrackPool.addInternalTrack(ext);
433         audioTrackPool.dump();
434         return true;
435     }
436 }
437 
getVideoCount(void)438 int ADM_Composer::getVideoCount(void)
439 {
440 	return _segments.getNbRefVideos();
441 }
442 
closeFile(void)443 void ADM_Composer::closeFile(void)
444 {
445 	GUI_close();
446 }
447 
getSegment(int i)448 _SEGMENT* ADM_Composer::getSegment(int i)
449 {
450 	return _segments.getSegment(i);
451 }
452 
isFileOpen(void)453 bool ADM_Composer::isFileOpen(void)
454 {
455     return avifileinfo != NULL;
456 }
457 
setCurrentFramePts(uint64_t pts)458 bool ADM_Composer::setCurrentFramePts(uint64_t pts)
459 {
460     if (video_body->getPKFramePTS(&pts))
461     {
462         return GUI_GoToTime(pts);
463     }
464     else
465     {
466         return false;
467     }
468 }
469 
getCurrentFrameFlags(uint32_t * flags,uint32_t * quantiser)470 void ADM_Composer::getCurrentFrameFlags(uint32_t *flags, uint32_t *quantiser)
471 {
472     admPreview::getFrameFlags(flags, quantiser);
473 }
474 
getRefVideo(int videoIndex)475 _VIDEOS* ADM_Composer::getRefVideo(int videoIndex)
476 {
477 	return _segments.getRefVideo(videoIndex);
478 }
479 
seekFrame(int count)480 void ADM_Composer::seekFrame(int count)
481 {
482 	if (count >= 0)
483 	{
484 		for (int i = 0; i < count; i++)
485 		{
486 			GUI_NextFrame(1);
487 		}
488 	}
489 	else
490 	{
491 		for (int i = 0; i < -count; i++)
492 		{
493 			GUI_PrevFrame(1);
494 		}
495 	}
496 }
497 
seekKeyFrame(int count)498 void ADM_Composer::seekKeyFrame(int count)
499 {
500     uint64_t pts = video_body->getCurrentFramePts();
501     if(pts == ADM_NO_PTS)
502         return;
503 
504     if(count >= 0)
505     {
506         for(int i = 0; i < count; i++)
507         {
508             uint64_t tmp = pts;
509             if(false == video_body->getNKFramePTS(&tmp))
510                 break;
511             pts = tmp;
512         }
513     }else
514     {
515         for(int i = 0; i < -count; i++)
516         {
517             uint64_t tmp = pts;
518             if(false == video_body->getPKFramePTS(&tmp))
519                 break;
520             pts = tmp;
521         }
522     }
523 
524     GUI_GoToKFrameTime(pts);
525 }
526 
seekBlackFrame(int count)527 void ADM_Composer::seekBlackFrame(int count)
528 {
529 	int direction = (count > 0) ? 1 : -1;
530 	count = count * direction;
531 
532 	for (int i = 0; i < count; i++)
533 	{
534 		if (direction == 1)
535 			GUI_NextBlackFrame();
536 		else
537 			GUI_PrevBlackFrame();
538 	}
539 }
540 
updateDefaultAudioTrack(void)541 void ADM_Composer::updateDefaultAudioTrack(void)
542 {
543 	EditableAudioTrack *ed = this->getDefaultEditableAudioTrack();
544 
545 	if (ed)
546 	{
547 		UI_setAudioCodec(ed->encoderIndex);
548 	}
549 }
550