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