centos build workarounds
[goodguy/history.git] / cinelerra-5.0 / cinelerra / packagerenderer.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "arender.h"
23 #include "asset.h"
24 #include "auto.h"
25 #include "bctimer.h"
26 #include "brender.h"
27 #include "cache.h"
28 #include "clip.h"
29 #include "cwindow.h"
30 #include "cwindowgui.h"
31 #include "edit.h"
32 #include "edits.h"
33 #include "edl.h"
34 #include "edlsession.h"
35 #include "errorbox.h"
36 #include "file.h"
37 #include "filesystem.h"
38 #include "format.inc"
39 #include "indexfile.h"
40 #include "language.h"
41 #include "mwindow.h"
42 #include "mwindowgui.h"
43 #include "packagerenderer.h"
44 #include "playabletracks.h"
45 #include "playbackconfig.h"
46 #include "pluginserver.h"
47 #include "preferences.h"
48 #include "render.h"
49 #include "renderengine.h"
50 #include "renderfarmfsserver.h"
51 #include "samples.h"
52 #include "sighandler.h"
53 #include "tracks.h"
54 #include "transportque.h"
55 #include "vedit.h"
56 #include "vframe.h"
57 #include "videodevice.h"
58 #include "vrender.h"
59
60
61
62
63
64
65
66 RenderPackage::RenderPackage()
67 {
68         audio_start = 0;
69         audio_end = 0;
70         video_start = 0;
71         video_end = 0;
72         audio_do = 0;
73         video_do = 0;
74         path[0] = 0;
75         done = 0;
76         use_brender = 0;
77 }
78
79 RenderPackage::~RenderPackage()
80 {
81 }
82
83
84
85
86
87
88
89
90 // Used by RenderFarm and in the future, Render, to do packages.
91 PackageRenderer::PackageRenderer()
92 {
93         command = 0;
94         audio_cache = 0;
95         video_cache = 0;
96         aconfig = 0;
97         vconfig = 0;
98         timer = new Timer;
99         frames_per_second = 0;
100 }
101
102 PackageRenderer::~PackageRenderer()
103 {
104         delete command;
105         delete audio_cache;
106         delete video_cache;
107         delete vconfig;
108         delete aconfig;
109         delete timer;
110 }
111
112
113 int PackageRenderer::initialize(MWindow *mwindow,
114                 EDL *edl,
115                 Preferences *preferences,
116                 Asset *default_asset)
117 {
118         int result = 0;
119
120         this->mwindow = mwindow;
121         this->edl = edl;
122         this->preferences = preferences;
123         this->default_asset = default_asset;
124
125
126 //printf("PackageRenderer::initialize %d\n", preferences->processors);
127         command = new TransportCommand;
128         command->command = NORMAL_FWD;
129         command->get_edl()->copy_all(edl);
130         command->change_type = CHANGE_ALL;
131         command->set_playback_range(edl);
132
133         default_asset->frame_rate = command->get_edl()->session->frame_rate;
134         default_asset->sample_rate = command->get_edl()->session->sample_rate;
135         default_asset->aspect_ratio = (double)command->get_edl()->session->aspect_w /
136                 command->get_edl()->session->aspect_h;
137         result = Render::check_asset(edl, *default_asset);
138
139         audio_cache = new CICache(preferences);
140         video_cache = new CICache(preferences);
141
142         //PlaybackConfig *config = command->get_edl()->session->playback_config;
143         aconfig = new AudioOutConfig();
144         vconfig = new VideoOutConfig;
145
146         return result;
147 }
148
149 void PackageRenderer::create_output()
150 {
151         FileSystem fs;
152         asset = new Asset(*default_asset);
153
154         if(!get_master() && preferences->renderfarm_vfs && preferences->use_renderfarm)
155                 sprintf(asset->path, RENDERFARM_FS_PREFIX "%s", package->path);
156         else
157                 strcpy(asset->path, package->path);
158
159
160
161
162         file = new File;
163
164         file->set_processors(preferences->processors);
165
166 //printf("PackageRenderer::create_output %d\n", __LINE__);
167         result = file->open_file(preferences,
168                                         asset,
169                                         0,
170                                         1);
171 //printf("PackageRenderer::create_output %d %d\n", __LINE__, result);
172
173         if(result && mwindow)
174         {
175 // open failed
176                 char string[BCTEXTLEN];
177                 sprintf(string, _("Couldn't open %s"), asset->path);
178                 ErrorBox error(_(PROGRAM_NAME ": Error"),
179                         mwindow->gui->get_abs_cursor_x(1),
180                         mwindow->gui->get_abs_cursor_y(1));
181                 error.create_objects(string);
182                 error.run_window();
183         }
184         else
185         if(mwindow)
186         {
187                 mwindow->sighandler->push_file(file);
188                 IndexFile::delete_index(preferences, asset);
189         }
190 //printf("PackageRenderer::create_output %d %d\n", __LINE__, result);
191 }
192
193 void PackageRenderer::create_engine()
194 {
195 // Fix audio buffers to 1 second
196         audio_read_length = command->get_edl()->session->sample_rate;
197         command->get_edl()->session->playback_config->aconfig->fragment_size = audio_read_length;
198
199         aconfig->fragment_size = audio_read_length;
200
201
202         render_engine = new RenderEngine(0,
203                 preferences,
204                 0,
205                 0,
206                 0);
207         render_engine->set_acache(audio_cache);
208         render_engine->set_vcache(video_cache);
209         render_engine->arm_command(command);
210
211         if(package->use_brender)
212         {
213                 audio_preroll = Units::to_int64((double)preferences->brender_preroll /
214                         default_asset->frame_rate *
215                         default_asset->sample_rate);
216                 video_preroll = preferences->brender_preroll;
217         }
218         else
219         {
220                 audio_preroll = Units::to_int64(preferences->render_preroll *
221                         default_asset->sample_rate);
222                 video_preroll = Units::to_int64(preferences->render_preroll *
223                         default_asset->frame_rate);
224         }
225         audio_position = package->audio_start - audio_preroll;
226         if( audio_position < 0 )
227         {
228                 audio_preroll += audio_position;
229                 audio_position = 0;
230         }
231         video_position = package->video_start - video_preroll;
232         if( video_position < 0 )
233         {
234                 video_preroll += video_position;
235                 video_position = 0;
236         }
237
238
239 //      PRINT_TRACE
240
241 // Create output buffers
242         if(asset->audio_data)
243         {
244                 file->start_audio_thread(audio_read_length,
245                         preferences->processors > 1 ? 2 : 1);
246         }
247
248 //      PRINT_TRACE
249
250         if(asset->video_data)
251         {
252                 compressed_output = new VFrame;
253 // The write length needs to correlate with the processor count because
254 // it is passed to the file handler which usually processes frames simultaneously.
255                 video_write_length = preferences->processors;
256                 video_write_position = 0;
257                 direct_frame_copying = 0;
258
259
260 //printf("PackageRenderer::create_engine %d\n", __LINE__);
261                 file->start_video_thread(video_write_length,
262                         command->get_edl()->session->color_model,
263                         preferences->processors > 1 ? 2 : 1,
264                         0);
265 //printf("PackageRenderer::create_engine %d\n", __LINE__);
266
267
268                 if(mwindow)
269                 {
270                         video_device = new VideoDevice;
271                         video_device->open_output(vconfig,
272                                 command->get_edl()->session->frame_rate,
273                                 command->get_edl()->session->output_w,
274                                 command->get_edl()->session->output_h,
275                                 mwindow->cwindow->gui->canvas,
276                                 0);
277 //                      video_device->start_playback();
278                 }
279         }
280
281
282         playable_tracks = new PlayableTracks(render_engine->get_edl(),
283                 video_position,
284                 PLAY_FORWARD,
285                 TRACK_VIDEO,
286                 1);
287
288 }
289
290
291
292
293 void PackageRenderer::do_audio()
294 {
295 //printf("PackageRenderer::do_audio %d\n", __LINE__);
296 // Do audio data
297         if(asset->audio_data)
298         {
299                 audio_output = file->get_audio_buffer();
300 // Zero unused channels in output vector
301                 for(int i = 0; i < MAX_CHANNELS; i++)
302                 {
303                         audio_output_ptr[i] = (i < asset->channels) ?
304                                 audio_output[i] :
305                                 0;
306                 }
307
308
309
310 // Call render engine
311
312                 result = render_engine->arender->process_buffer(audio_output_ptr,
313                         audio_read_length,
314                         audio_position);
315
316
317
318 // Fix buffers for preroll
319                 int64_t output_length = audio_read_length;
320                 if(audio_preroll > 0)
321                 {
322                         if(audio_preroll >= output_length)
323                                 output_length = 0;
324                         else
325                         {
326                                 output_length -= audio_preroll;
327                                 for(int i = 0; i < MAX_CHANNELS; i++)
328                                 {
329                                         if(audio_output_ptr[i])
330                                         {
331                                                 double *data = audio_output_ptr[i]->get_data();
332                                                 for(int j = 0; j < output_length; j++)
333                                                 {
334                                                         data[j] = data[j + audio_read_length - output_length];
335                                                 }
336                                         }
337                                 }
338                         }
339 //printf("PackageRenderer::do_audio 4\n");
340
341                         audio_preroll -= audio_read_length;
342                 }
343
344 // Must perform writes even if 0 length so get_audio_buffer doesn't block
345                 result |= file->write_audio_buffer(output_length);
346         }
347
348         audio_position += audio_read_length;
349 //printf("PackageRenderer::do_audio %d\n", __LINE__);
350 }
351
352
353 void PackageRenderer::do_video()
354 {
355         const int debug = 0;
356 // Do video data
357         if(asset->video_data)
358         {
359 // get the absolute video position from the audio position
360                 int64_t video_end = video_position + video_read_length;
361
362                 if(video_end > package->video_end)
363                         video_end = package->video_end;
364
365                 while(video_position < video_end && !result)
366                 {
367 // Try to copy the compressed frame directly from the input to output files
368 //printf("PackageRenderer::do_video 2 video_position=%ld\n", video_position);
369                         if(direct_frame_copy(command->get_edl(),
370                                 video_position,
371                                 file,
372                                 result))
373                         {
374 // Direct frame copy failed.
375 // Switch back to background compression
376                                 if(direct_frame_copying)
377                                 {
378
379                                         file->start_video_thread(video_write_length,
380                                                 command->get_edl()->session->color_model,
381                                                 preferences->processors > 1 ? 2 : 1,
382                                                 0);
383 //printf("PackageRenderer::do_video %d %d\n", __LINE__, preferences->processors);
384                                         direct_frame_copying = 0;
385                                 }
386
387 // Try to use the rendering engine to write the frame.
388 // Get a buffer for background writing.
389
390                                 if(video_write_position == 0)
391                                         video_output = file->get_video_buffer();
392
393                                 if(debug) printf("PackageRenderer::do_video %d %p\n", __LINE__, video_output);
394                                 if(debug) printf("PackageRenderer::do_video %d %p\n", __LINE__, video_output[0]);
395
396
397
398
399 // Construct layered output buffer
400                                 video_output_ptr = video_output[0][video_write_position];
401                                 if(debug)
402                                 {
403                                         printf("PackageRenderer::do_video %d %p\n", __LINE__, video_output_ptr);
404                                         printf("PackageRenderer::do_video %d %d\n", __LINE__, result);
405                                         video_output_ptr->dump();
406                                 }
407
408                                 if(!result)
409                                         result = render_engine->vrender->process_buffer(
410                                                 video_output_ptr,
411                                                 video_position,
412                                                 0);
413
414
415                                 if(debug) printf("PackageRenderer::do_video %d %d\n", __LINE__, result);
416
417                                 if(!result &&
418                                         mwindow &&
419                                         video_device->output_visible())
420                                 {
421 // Vector for video device
422                                         VFrame *preview_output;
423
424                                         video_device->new_output_buffer(&preview_output,
425                                                 command->get_edl()->session->color_model);
426
427                                         preview_output->copy_from(video_output_ptr);
428                                         video_device->write_buffer(preview_output,
429                                                 command->get_edl());
430                                 }
431
432                                 if(debug) printf("PackageRenderer::do_video %d %d\n", __LINE__, result);
433
434
435 // Don't write to file
436                                 if(video_preroll && !result)
437                                 {
438                                         video_preroll--;
439 // Keep the write position at 0 until ready to write real frames
440                                         result = file->write_video_buffer(0);
441                                         video_write_position = 0;
442                                 }
443                                 else
444                                 if(!result)
445                                 {
446 // Set background rendering parameters
447 // Allow us to skip sections of the output file by setting the frame number.
448 // Used by background render and render farm.
449 //printf("PackageRenderer::do_video %d " _LD "\n", __LINE__, video_position);
450                                         video_output_ptr->set_number(video_position);
451                                         video_write_position++;
452
453                                         if(video_write_position >= video_write_length)
454                                         {
455                                                 result = file->write_video_buffer(video_write_position);
456 //printf("PackageRenderer::do_video %d " _LD "\n", __LINE__, video_position);
457 // Update the brender map after writing the files.
458                                                 if(package->use_brender)
459                                                 {
460 //printf("PackageRenderer::do_video 10\n");
461                                                         for(int i = 0; i < video_write_position && !result; i++)
462                                                         {
463                                                                 result = set_video_map(video_position + 1 - video_write_position + i,
464                                                                         BRender::RENDERED);
465                                                         }
466 //printf("PackageRenderer::do_video 11 %d\n", result);
467                                                 }
468                                                 video_write_position = 0;
469                                         }
470                                 }
471 //printf("PackageRenderer::do_video %d " _LD "\n", __LINE__, video_position);
472
473
474                         }
475
476                         video_position++;
477                         if(!result && get_result()) result = 1;
478                         if(!result && progress_cancelled()) result = 1;
479                 }
480         }
481         else
482         {
483                 video_position += video_read_length;
484         }
485 }
486
487
488 void PackageRenderer::stop_engine()
489 {
490         delete render_engine;
491         delete playable_tracks;
492 }
493
494
495 void PackageRenderer::stop_output()
496 {
497         int error = 0;
498         if(asset->audio_data)
499         {
500 // stop file I/O
501                 file->stop_audio_thread();
502         }
503
504         if(asset->video_data)
505         {
506                 delete compressed_output;
507                 if(video_write_position)
508                         file->write_video_buffer(video_write_position);
509                 if(package->use_brender)
510                 {
511                         for(int i = 0; i < video_write_position && !error; i++)
512                         {
513                                 error = set_video_map(video_position - video_write_position + i,
514                                         BRender::RENDERED);
515                         }
516                 }
517                 video_write_position = 0;
518                 if(!error) file->stop_video_thread();
519                 if(mwindow)
520                 {
521 //                      video_device->stop_playback();
522                         video_device->close_all();
523                         delete video_device;
524                 }
525         }
526 }
527
528
529 void PackageRenderer::close_output()
530 {
531         if(mwindow)
532                 mwindow->sighandler->pull_file(file);
533         file->close_file();
534         delete file;
535         asset->Garbage::remove_user();
536 }
537
538 // Aborts and returns 1 if an error is encountered.
539 int PackageRenderer::render_package(RenderPackage *package)
540 {
541         int audio_done = 0;
542         int video_done = 0;
543         int samples_rendered = 0;
544         const int debug = 0;
545
546
547         result = 0;
548         this->package = package;
549
550 // printf(
551 // "PackageRenderer::render_package: audio s=" _LD " l=" _LD " video s=" _LD " l=" _LD "\n",
552 //      package->audio_start,
553 //      package->audio_end - package->audio_start,
554 //      package->video_start,
555 //      package->video_end - package->video_start);
556
557         if(debug) PRINT_TRACE
558
559         if( package->video_do ) default_asset->video_data = 1;
560         if( package->audio_do ) default_asset->audio_data = 1;
561         Render::check_asset(edl, *default_asset);
562
563         create_output();
564         if(debug) PRINT_TRACE
565
566         if(!asset->video_data) video_done = 1;
567         if(!asset->audio_data) audio_done = 1;
568
569 // Create render engine
570         if(!result)
571         {
572 if(debug) PRINT_TRACE
573                 create_engine();
574 if(debug) PRINT_TRACE
575
576
577 // Main loop
578                 timer->update();
579                 total_samples_rendered = 0;
580                 while((!audio_done || !video_done) && !result)
581                 {
582                         int need_audio = 0, need_video = 0;
583
584
585
586
587 // Calculate lengths to process.  Audio fragment is constant.
588                         if(!audio_done)
589                         {
590                                 if(audio_position + audio_read_length >= package->audio_end)
591                                 {
592                                         audio_done = 1;
593                                         audio_read_length = package->audio_end - audio_position;
594                                 }
595
596                                 samples_rendered = audio_read_length;
597                                 need_audio = 1;
598                         }
599
600 //printf("PackageRenderer::render_package 6 %d\n", samples_rendered);
601
602                         if(!video_done)
603                         {
604                                 if(audio_done)
605                                 {
606 //                                      video_read_length = package->video_end - video_position;
607 // // Packetize video length so progress gets updated
608 //                                      video_read_length = (int)MIN(asset->frame_rate, video_read_length);
609 //                                      video_read_length = MAX(video_read_length, 30);
610                                         video_read_length = 1;
611                                 }
612                                 else
613 // Guide video with audio
614                                 {
615                                         video_read_length = Units::to_int64(
616                                                 (double)(audio_position + audio_read_length) /
617                                                 asset->sample_rate *
618                                                 asset->frame_rate) -
619                                                 video_position;
620                                 }
621
622 // Clamp length
623                                 if(video_position + video_read_length >= package->video_end)
624                                 {
625                                         video_done = 1;
626                                         video_read_length = package->video_end - video_position;
627                                 }
628
629 // Calculate samples rendered for progress bar.
630                                 if(audio_done)
631                                         samples_rendered = Units::round((double)video_read_length /
632                                                 asset->frame_rate *
633                                                 asset->sample_rate);
634
635                                 need_video = 1;
636                         }
637                         if(debug) PRINT_TRACE
638
639                         if(debug) printf("PackageRenderer::render_package 1 %d " _LD " " _LD "\n",
640                                         result, audio_read_length, video_read_length);
641                         if(need_video && !result) do_video();
642                         if(debug) printf("PackageRenderer::render_package %d %d %d\n",
643                                         __LINE__, result, samples_rendered);
644                         if(need_audio && !result) do_audio();
645
646
647                         if(debug) PRINT_TRACE
648                         if(!result)
649                         {
650 // Calculate frames per second for the renderfarm table.
651                                 total_samples_rendered += samples_rendered;
652                                 if(!video_done && timer->get_difference() > 30000)
653                                 {
654                                         frames_per_second = (double)total_samples_rendered *
655                                                 asset->frame_rate /
656                                                 asset->sample_rate /
657                                                 ((double)timer->get_difference() / 1000);
658                                 }
659                                 set_progress(samples_rendered);
660                         }
661                         if(debug) PRINT_TRACE
662
663
664
665
666
667                         if(!result && progress_cancelled()) result = 1;
668                         if(debug) PRINT_TRACE
669
670 // printf("PackageRenderer::render_package 10 %d %d %d %d\n",
671 // audio_read_length, video_read_length, samples_rendered, result);
672                         if(result)
673                                 set_result(result);
674                         else
675                                 result = get_result();
676                 }
677
678 // Final FPS readout
679                 frames_per_second = (double)(package->video_end - package->video_start) /
680                         ((double)timer->get_difference() / 1000);
681
682
683 //PRINT_TRACE
684                 stop_engine();
685 //PRINT_TRACE
686
687                 stop_output();
688 //PRINT_TRACE
689
690
691         }
692
693
694 //PRINT_TRACE
695
696         close_output();
697
698 //PRINT_TRACE
699
700         set_result(result);
701 //PRINT_TRACE
702
703
704
705         return result;
706 }
707
708
709
710
711
712
713
714
715 // Try to copy the compressed frame directly from the input to output files
716 // Return 1 on failure and 0 on success
717 int PackageRenderer::direct_frame_copy(EDL *edl,
718         int64_t &video_position,
719         File *file,
720         int &error)
721 {
722         Track *playable_track = 0;
723         Edit *playable_edit = 0;
724
725 //printf("Render::direct_frame_copy 1\n");
726         if(direct_copy_possible(edl,
727                 video_position,
728                 playable_track,
729                 playable_edit,
730                 file))
731         {
732 // Switch to direct copying
733                 if(!direct_frame_copying)
734                 {
735                         if(video_write_position)
736                         {
737                                 error |= file->write_video_buffer(video_write_position);
738                                 video_write_position = 0;
739                         }
740                         file->stop_video_thread();
741                         direct_frame_copying = 1;
742                 }
743 //printf("Render::direct_frame_copy 2\n");
744
745                 if(!package->use_brender)
746                         error |= ((VEdit*)playable_edit)->read_frame(compressed_output,
747                                 video_position,
748                                 PLAY_FORWARD,
749                                 video_cache,
750                                 1,
751                                 0,
752                                 0);
753
754
755                 if(!error && video_preroll > 0)
756                 {
757                         video_preroll--;
758                 }
759                 else
760                 if(!error)
761                 {
762                         if(package->use_brender)
763                         {
764 //printf("PackageRenderer::direct_frame_copy 1\n");
765                                 error = set_video_map(video_position, BRender::SCANNED);
766 //printf("PackageRenderer::direct_frame_copy 10 %d\n", error);
767                         }
768                         else
769                         {
770                                 VFrame ***temp_output = new VFrame**[1];
771                                 temp_output[0] = new VFrame*[1];
772                                 temp_output[0][0] = compressed_output;
773                                 error = file->write_frames(temp_output, 1);
774                                 delete [] temp_output[0];
775                                 delete [] temp_output;
776                         }
777                 }
778                 return 0;
779         }
780         else
781                 return 1;
782 }
783
784 int PackageRenderer::direct_copy_possible(EDL *edl,
785                                 int64_t current_position,
786                                 Track* &playable_track,  // The one track which is playable
787                                 Edit* &playable_edit, // The edit which is playing
788                                 File *file)   // Output file
789 {
790         int result = 1;
791         int total_playable_tracks = 0;
792         Track* current_track;
793
794 // Number of playable tracks must equal 1
795         for(current_track = edl->tracks->first;
796                 current_track && result;
797                 current_track = current_track->next)
798         {
799                 if(current_track->data_type == TRACK_VIDEO)
800                 {
801                         if(playable_tracks->is_playable(current_track,
802                                 current_position,
803                                 PLAY_FORWARD,
804                                 1))
805                         {
806                                 playable_track = current_track;
807                                 total_playable_tracks++;
808                         }
809                 }
810         }
811
812 //printf("Render::direct_copy_possible 1 %d\n", result);
813         if(total_playable_tracks != 1) result = 0;
814 //printf("Render::direct_copy_possible 2 %d\n", result);
815
816 // Edit must have a source file
817 // TODO: descend into nested EDL's
818         if(result)
819         {
820 //printf("Render::direct_copy_possible 3 %d\n", result);
821                 playable_edit = playable_track->edits->get_playable_edit(current_position, 1);
822 //printf("Render::direct_copy_possible 4 %d %p\n", result, playable_edit);
823                 if(!playable_edit)
824                         result = 0;
825         }
826
827 // Source file must be able to copy to destination file.
828 // Source file must be same size as project output.
829         if(result)
830         {
831                 if(!file->can_copy_from(playable_edit->asset,
832                         current_position + playable_track->nudge,
833                         edl->session->output_w,
834                         edl->session->output_h))
835                         result = 0;
836         }
837 //printf("Render::direct_copy_possible 6 %d\n", result);
838
839 // Test conditions mutual between vrender.C and this.
840         if(result &&
841                 !playable_track->direct_copy_possible(current_position, PLAY_FORWARD, 1))
842                 result = 0;
843 //printf("Render::direct_copy_possible 7 %d\n", result);
844
845         return result;
846 }
847
848
849
850
851
852
853
854
855
856 int PackageRenderer::get_master()
857 {
858         return 0;
859 }
860
861 // Get result status from server
862 int PackageRenderer::get_result()
863 {
864         return 0;
865 }
866
867 void PackageRenderer::set_result(int value)
868 {
869 }
870
871 void PackageRenderer::set_progress(int64_t value)
872 {
873 }
874
875 int PackageRenderer::set_video_map(int64_t position, int value)
876 {
877         return 0;
878 }
879
880 int PackageRenderer::progress_cancelled()
881 {
882         return 0;
883 }
884
885
886
887
888
889
890
891
892
893