3 * Copyright (C) 2009 Adam Williams <broadcast at earthling dot net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "bcsignals.h"
28 #include "fileserver.h"
29 #include "filesystem.h"
30 #include "filethread.h"
46 FileFork::FileFork(FileServer *server) : ForkWrapper()
50 this->server = server;
51 //printf("FileFork::FileFork %d\n", __LINE__);
58 MWindow::file_server->delete_filefork(real_fork);
62 void FileFork::init_child()
64 //printf("FileFork::init_child %d\n", __LINE__);
67 int FileFork::handle_command()
72 if(debug) printf("FileFork::handle_command %d (pid=%d) this=%p command=%d\n",
73 __LINE__, getpid(), this, command_token);
74 // to grab this task in the debugger
75 //static int zbug = 1; volatile int bug = zbug;
76 //while( bug ) usleep(10000);
88 int rd = *(int*)(command_data + offset);
89 offset += sizeof(int);
90 int wr = *(int*)(command_data + offset);
91 offset += sizeof(int);
92 file->cpus = *(int*)(command_data + offset);
93 offset += sizeof(int);
94 file->white_balance_raw = *(int*)(command_data + offset);
95 offset += sizeof(int);
96 file->interpolate_raw = *(int*)(command_data + offset);
97 offset += sizeof(int);
98 file->playback_subtitle = *(int*)(command_data + offset);
99 offset += sizeof(int);
100 file->current_program = *(int*)(command_data + offset);
101 offset += sizeof(int);
103 // Read asset from socket
105 table.load_string((char*)command_data + offset);
106 Asset *new_asset = new Asset;
107 new_asset->load_defaults(&table, "", 1, 1, 1, 1, 1);
110 printf("FileFork::handle_command %d\n%s\n",
112 command_data + offset);
117 // printf("FileFork::handle_command %d\n", __LINE__);
119 //printf("FileFork::handle_command %d server=%p\n", __LINE__, server);
120 //printf("FileFork::handle_command %d server->preferences=%p\n", __LINE__, server->preferences);
121 result = file->open_file(
126 new_asset->Garbage::remove_user();
127 if(debug) printf("FileFork::handle_command %d result=" _LD "\n",
132 // Send updated asset
133 file->asset->save_defaults(&table, "", 1, 1, 1, 1, 1);
135 table.save_string(string);
136 int buffer_size = strlen(string) + 1;
137 send_result(result, (unsigned char*)string, buffer_size);
143 file->set_processors(*(int*)command_data);
144 send_result(0, 0, 0);
149 file->set_preload(*(int64_t*)command_data);
150 send_result(0, 0, 0);
154 file->set_subtitle(*(int*)command_data);
155 send_result(0, 0, 0);
158 case SET_INTERPOLATE_RAW:
159 file->set_interpolate_raw(*(int*)command_data);
160 send_result(0, 0, 0);
163 case SET_WHITE_BALANCE_RAW:
164 file->set_white_balance_raw(*(int*)command_data);
165 send_result(0, 0, 0);
170 unsigned char result_buffer[sizeof(int64_t) * 2];
171 int64_t *rbfr = (int64_t *)result_buffer;
173 rbfr[0] = file->asset->audio_length;
174 rbfr[1] = file->asset->video_length;
175 // printf("FileFork::handle_command %d " _LD " " _LD "\n",
177 // file->asset->audio_length,
178 // file->asset->video_length);
179 send_result(0, result_buffer, sizeof(int64_t) * 2);
185 result = file->get_index((char*)command_data);
186 send_result(result, 0, 0);
190 case START_AUDIO_THREAD:
192 int buffer_size = *(int*)command_data;
193 int ring_buffers = *(int*)(command_data + sizeof(int));
194 result = file->start_audio_thread(buffer_size, ring_buffers);
195 // Send buffer information back to server here
196 int result_bytes = ring_buffers *
197 Samples::filefork_size() *
198 file->asset->channels;
199 unsigned char result_buffer[result_bytes];
200 for(int i = 0; i < ring_buffers; i++)
202 Samples **samples = file->audio_thread->audio_buffer[i];
203 for(int j = 0; j < file->asset->channels; j++)
205 samples[j]->to_filefork(result_buffer +
206 i * Samples::filefork_size() * file->asset->channels +
207 j * Samples::filefork_size());
211 send_result(result, result_buffer, result_bytes);
215 case START_VIDEO_THREAD:
217 int buffer_size = *(int*)command_data;
218 int color_model = *(int*)(command_data + sizeof(int));
219 int ring_buffers = *(int*)(command_data + sizeof(int) * 2);
220 int compressed = *(int*)(command_data + sizeof(int) * 3);
221 // allocate buffers here
222 result = file->start_video_thread(buffer_size,
227 // Send buffer information back to server here
228 int result_bytes = ring_buffers *
229 file->asset->layers *
231 VFrame::filefork_size();
232 unsigned char result_buffer[result_bytes];
234 for(int i = 0; i < ring_buffers; i++)
236 VFrame ***frames = file->video_thread->video_buffer[i];
237 for(int j = 0; j < file->asset->layers; j++)
239 for(int k = 0; k < buffer_size; k++)
241 //printf("FileFork::handle_command %d j=%d k=%d %p %p\n", __LINE__, j, k, frames[j][k], frames[j][k]->get_shmid()));
242 frames[j][k]->to_filefork(result_buffer +
243 i * file->asset->layers *
245 VFrame::filefork_size() +
247 VFrame::filefork_size() +
248 k * VFrame::filefork_size());
253 send_result(result, result_buffer, result_bytes);
258 case START_VIDEO_DECODE_THREAD:
259 result = file->start_video_decode_thread();
260 send_result(result, 0, 0);
264 case STOP_AUDIO_THREAD:
265 result = file->stop_audio_thread();
266 send_result(result, 0, 0);
269 case STOP_VIDEO_THREAD:
270 result = file->stop_video_thread();
271 send_result(result, 0, 0);
275 result = file->set_channel(*(int*)command_data);
276 send_result(result, 0, 0);
280 result = file->set_layer(*(int*)command_data, 0);
281 send_result(result, 0, 0);
284 case GET_AUDIO_LENGTH:
285 result = file->get_audio_length();
286 send_result(result, 0, 0);
289 case GET_VIDEO_LENGTH:
290 result = file->get_video_length();
291 send_result(result, 0, 0);
294 case GET_VIDEO_POSITION:
295 result = file->get_video_position();
296 send_result(result, 0, 0);
299 case GET_AUDIO_POSITION:
300 result = file->get_audio_position();
301 send_result(result, 0, 0);
304 case SET_AUDIO_POSITION:
305 result = file->set_audio_position(*(int64_t*)command_data);
306 send_result(result, 0, 0);
309 case SET_VIDEO_POSITION:
310 result = file->set_video_position(*(int64_t*)command_data, 0);
311 send_result(result, 0, 0);
316 int entry_size = Samples::filefork_size();
317 Samples **samples = new Samples*[file->asset->channels];
318 for(int i = 0; i < file->asset->channels; i++)
320 samples[i] = new Samples;
321 samples[i]->from_filefork(
322 command_data + entry_size * i);
324 int64_t len = *(int64_t*)(command_data +
325 entry_size * file->asset->channels);
327 result = file->write_samples(samples, len);
328 send_result(result, 0, 0);
330 for(int i = 0; i < file->asset->channels; i++)
341 int entry_size = VFrame::filefork_size();
343 VFrame ***frames = new VFrame**[file->asset->layers];
344 //printf("FileFork::handle_command %d %d\n", __LINE__, file->asset->layers);
345 int len = *(int*)command_data;
346 //printf("FileFork::handle_command %d %d %d\n", __LINE__, file->asset->layers, len);
348 for(int i = 0; i < file->asset->layers; i++)
350 frames[i] = new VFrame*[len];
351 for(int j = 0; j < len; j++)
353 frames[i][j] = new VFrame;
355 frames[i][j]->from_filefork(command_data +
357 entry_size * len * i +
359 // printf("FileFork::handle_command %d color_model=%d\n",
361 // frames[i][j]->get_color_model(),
362 // frames[i][j]->get_compressed_size());
369 result = file->write_frames(frames, len);
372 send_result(result, 0, 0);
373 for(int i = 0; i < file->asset->layers; i++)
375 for(int j = 0; j < len; j++)
386 case WRITE_AUDIO_BUFFER:
387 result = file->write_audio_buffer(*(int64_t*)command_data);
388 send_result(result, 0, 0);
391 case WRITE_VIDEO_BUFFER:
393 //printf("FileFork::handle_command %d\n", __LINE__);
394 int len = *(int64_t*)command_data;
395 VFrame ***video_buffer = file->video_thread->get_last_video_buffer();
396 for(int i = 0; i < file->asset->layers; i++)
398 for(int j = 0; j < len; j++)
401 //printf("FileFork::handle_command %d i=%d j=%d %p %p\n", __LINE__, i, j, video_buffer[i][j], video_buffer[i][j]->get_shmid());
402 video_buffer[i][j]->from_filefork(command_data +
404 VFrame::filefork_size() * (len * i + j));
405 //printf("FileFork::handle_command %d %p " _LD "\n", __LINE__, video_buffer[i][j]->get_shmid(), video_buffer[i][j]->get_number());
410 result = file->write_video_buffer(len);
411 send_result(result, 0, 0);
412 //printf("FileFork::handle_command %d\n", __LINE__);
416 case GET_AUDIO_BUFFER:
418 // int entry_size = Samples::filefork_size();
419 // int result_bytes = entry_size * file->asset->channels;
420 // unsigned char result_buffer[sizeof(int)];
422 // Make it swap buffers
423 // Samples **samples = file->get_audio_buffer();
424 // for(int i = 0; i < file->asset->channels; i++)
426 // samples[i]->to_filefork(result_buffer +
427 // i * Samples::filefork_size());
430 file->get_audio_buffer();
431 send_result(file->audio_thread->current_buffer, 0, 0);
435 case GET_VIDEO_BUFFER:
437 // int entry_size = VFrame::filefork_size();
438 // int layers = file->asset->layers;
439 // int buffer_size = file->video_thread->buffer_size;
440 // int result_size = entry_size *
444 // unsigned char result_buffer[result_size];
445 // *(int*)(result_buffer + entry_size *
447 // buffer_size) = buffer_size;
448 //printf("FileFork::handle_command %d layers=%d\n", __LINE__, layers);
450 // VFrame ***frames = file->get_video_buffer();
451 // for(int i = 0; i < layers; i++)
453 // for(int j = 0; j < buffer_size; j++)
455 // frames[i][j]->to_filefork(result_buffer +
456 // entry_size * i * buffer_size +
461 file->get_video_buffer();
462 send_result(file->video_thread->current_buffer, 0, 0);
463 //printf("FileFork::handle_command %d\n", __LINE__);
469 if(debug) PRINT_TRACE
470 int len = *(int64_t*)(command_data + Samples::filefork_size());
471 if(debug) PRINT_TRACE
472 Samples *samples = new Samples;
473 samples->from_filefork(command_data);
474 if(debug) PRINT_TRACE
476 result = file->read_samples(samples, len);
477 if(debug) PRINT_TRACE
478 send_result(result, 0, 0);
479 if(debug) PRINT_TRACE
482 if(debug) PRINT_TRACE
488 VFrame *frame = new VFrame;
489 frame->from_filefork(command_data);
490 int allocated_data = frame->get_compressed_allocated();
493 // printf("FileFork::handle_command %d file=%p\n",
497 result = file->read_frame(frame, 0);
500 // printf("FileFork::handle_command %d size=%d\n",
502 // frame->get_compressed_size());
505 // Send compressed data through socket only if data allocation changed.
506 if(frame->get_color_model() == BC_COMPRESSED &&
507 allocated_data != frame->get_compressed_allocated())
509 int result_size = sizeof(int) * 2 + frame->get_compressed_size();
510 unsigned char *result_data = new unsigned char[result_size];
511 *(int*)result_data = frame->get_compressed_size();
512 *(int*)(result_data + sizeof(int)) = frame->get_keyframe();
513 memcpy(result_data + sizeof(int) * 2,
515 frame->get_compressed_size());
519 delete [] result_data;
523 int result_size = sizeof(int) * 2;
524 unsigned char *result_data = new unsigned char[result_size];
525 *(int*)result_data = frame->get_compressed_size();
526 *(int*)(result_data + sizeof(int)) = frame->get_keyframe();
527 send_result(result, result_data, result_size);
528 delete [] result_data;
532 // printf("FileFork::handle_command %d size=%d\n",
534 // frame->get_compressed_size());
537 // printf("FileFork::handle_command %d size=%d\n",
539 // frame->get_compressed_size());
546 int64_t position = *(int64_t*)(command_data);
547 int output_w = *(int*)(command_data + sizeof(int64_t));
548 int output_h = *(int*)(command_data + sizeof(int64_t) + sizeof(int));
549 xml.read_from_string((char*)command_data +
553 // Asset doesn't read the XML path.
554 Asset *new_asset = new Asset(xml.tag.get_property("SRC"));
555 new_asset->read(&xml, 1);
556 result = file->can_copy_from(new_asset,
560 send_result(result, 0, 0);
561 new_asset->Garbage::remove_user();
565 case COLORMODEL_SUPPORTED:
567 int colormodel = *(int*)command_data;
568 result = file->colormodel_supported(colormodel);
569 send_result(result, 0, 0);
573 case FILE_MEMORY_USAGE:
574 result = file->file_memory_usage();
575 send_result(result, 0, 0);
580 int no = *(int*)command_data;
581 result = file->set_program(no);
582 send_result(result, 0, 0);
589 int no = *(int*)command_data;
590 result = file->get_cell_time(no, time);
591 send_result(result, (unsigned char *)&time, sizeof(time));
598 result = file->get_system_time(tm);
599 send_result(result, (unsigned char *)&tm, sizeof(tm));
603 case GET_AUDIO4VIDEO:
605 int64_t channel_mask = 0;
606 int vstream = *(int*)command_data;
607 int astream = *(int*)(command_data + sizeof(int));
608 result = file->get_audio_for_video(vstream, astream, channel_mask);
609 send_result(result, (unsigned char *)&channel_mask, sizeof(channel_mask));
615 int track = *(int*)command_data;
616 result = file->get_video_pid(track);
617 send_result(result, 0, 0);
623 int width=0, height=0; double framerate=0;
624 char title[BCTEXTLEN]; title[0]=0;
625 int track = *(int*)command_data;
626 result = file->get_video_info(track, pid,
627 framerate, width, height, title);
628 unsigned char data[sizeof(framerate)+sizeof(pid)+
629 sizeof(width)+sizeof(height)+sizeof(title)];
630 unsigned char *bp = data;
631 *(double *)bp = framerate; bp += sizeof(framerate);
632 *(int *)bp = pid; bp += sizeof(pid);
633 *(int *)bp = width; bp += sizeof(width);
634 *(int *)bp = height; bp += sizeof(height);
635 for( char *cp=title; (*bp++=*cp)!=0; ++cp );
636 send_result(result, data, bp-data);
639 case SELECT_VIDEO_STREAM:
641 Asset *asset = new Asset;
642 int vstream = *(int*)command_data;
643 result = file->select_video_stream(asset, vstream);
644 unsigned char data[sizeof(asset->frame_rate)+sizeof(asset->video_length)+
645 sizeof(asset->width)+sizeof(asset->height)];
646 unsigned char *bp = data;
647 *(double *)bp = asset->frame_rate; bp += sizeof(asset->frame_rate);
648 *(int *)bp = asset->video_length; bp += sizeof(asset->video_length);
649 *(int *)bp = asset->width; bp += sizeof(asset->width);
650 *(int *)bp = asset->height; bp += sizeof(asset->height);
652 send_result(result, data, bp-data);
655 case SELECT_AUDIO_STREAM:
657 Asset *asset = new Asset;
658 int astream = *(int*)command_data;
659 result = file->select_audio_stream(asset, astream);
660 unsigned char data[sizeof(asset->channels)+sizeof(asset->sample_rate)+
661 sizeof(asset->audio_length)];
662 unsigned char *bp = data;
663 *(int *)bp = asset->channels; bp += sizeof(asset->channels);
664 *(int *)bp = asset->sample_rate; bp += sizeof(asset->sample_rate);
665 *(int *)bp = asset->audio_length; bp += sizeof(asset->audio_length);
667 send_result(result, data, bp-data);
676 #endif // USE_FILEFORK