stream2file_error_msg_t start_recording(const char * const filename, const char * const info, const unsigned short vpid, const unsigned short * const pids, const unsigned int numpids) { int fd; char buf[FILENAMEBUFFERSIZE]; struct statfs s; // rip rec_filename if(autoshift) sprintf(rec_filename, "%s_temp", filename); else sprintf(rec_filename, "%s", filename); // write stream information (should wakeup the disk from standby, too) sprintf(buf, "%s.xml", rec_filename); char * dir = strdup(buf); int ret = statfs(dirname(dir), &s); free(dir); if((ret != 0) || (s.f_type == 0x72b6) || (s.f_type == 0x24051905)) { return STREAM2FILE_INVALID_DIRECTORY; } if ((fd = open(buf, O_SYNC | O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) >= 0) { write(fd, info, strlen(info)); fdatasync(fd); close(fd); } else { return STREAM2FILE_INVALID_DIRECTORY; } exit_flag = STREAM2FILE_STATUS_RUNNING; sprintf(buf, "%s.ts", rec_filename); dprintf(DEBUG_NORMAL, "[Stream2File] Record start: file %s vpid 0x%x apid 0x%x\n", buf, vpid, pids[0]); fd = open(buf, O_CREAT | O_RDWR | O_LARGEFILE | O_TRUNC , S_IRWXO | S_IRWXG | S_IRWXU); if(fd < 0) { perror(buf); return STREAM2FILE_INVALID_DIRECTORY; } genpsi(fd); // init record if(!record) { if(channel) record = new cRecord( channel->getFeIndex() ); } // open record->Open(numpids); // start_recording if(!record->Start(fd, (unsigned short ) vpid, (unsigned short *) pids, numpids)) { record->Stop(); delete record; record = NULL; return STREAM2FILE_INVALID_DIRECTORY; } if(channel) { cam0->setCaPmt(channel->getCaPmt(), 0, 1, true); // demux 0+2 , update } return STREAM2FILE_OK; }
void * FileThread(void * v_arg) { ringbuffer_data_t vec[2]; size_t readsize; unsigned int filecount = 0; char radio_extension[5]; const unsigned long long splitsize = (limit / TS_SIZE) * TS_SIZE; unsigned long long remfile=0; int fd2 = -1; ringbuffer_t * ringbuf = ((struct filenames_t *)v_arg)->ringbuffer; while (1) { ringbuffer_get_read_vector(ringbuf, &(vec[0])); readsize = vec[0].len + vec[1].len; if (readsize) { // Do Splitting if necessary if (remfile == 0) { char filename[FILENAMEBUFFERSIZE]; int flags = O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_LARGEFILE; if (use_o_sync) flags |= O_SYNC; retry: if (mymode == 2) // without extension .mp2 the Neutrino Audioplayer can not access the recording sprintf(radio_extension, "%s", ".mp2"); else sprintf(radio_extension, "%s", ""); sprintf(filename, "%s.%3.3d.%s%s", myfilename, ++filecount, ((struct filenames_t *)v_arg)->extension, radio_extension); printf("[stream2file] filename: '%s'\n" " myfilename: '%s'\n", filename, myfilename); if (fd2 != -1) close(fd2); if ((fd2 = open(filename, flags, REC_FILE_PERMISSIONS)) < 0) { if (errno == EEXIST) { printf("[stream2file] %s exists, retrying...\n", filename); goto retry; } perror("[stream2file]: error opening outfile"); exit_flag = STREAM2FILE_STATUS_WRITE_OPEN_FAILURE; pthread_exit(NULL); } if( strstr(filename, ".ts") != NULL && gen_psi ) { genpsi(fd2); } remfile = splitsize; } /* make sure file contains complete TS-packets and is <= splitsize */ if ((unsigned long long)readsize > remfile) { readsize = remfile; if (vec[0].len > readsize) vec[0].len = readsize; vec[1].len = readsize - vec[0].len; } ssize_t written; while (1) { if ((written = write(fd2, vec[0].buf, vec[0].len)) < 0) { if (errno != EAGAIN) { exit_flag = STREAM2FILE_STATUS_WRITE_FAILURE; perror("[stream2file]: error in write"); goto terminate_thread; } } else { ringbuffer_read_advance(ringbuf, written); if (vec[0].len == (size_t)written) { if (vec[1].len == 0) { goto all_bytes_written; } vec[0] = vec[1]; vec[1].len = 0; } else { vec[0].len -= written; vec[0].buf += written; } } } all_bytes_written: if (use_fdatasync) fdatasync(fd2); remfile -= (unsigned long long)readsize; } else { if (exit_flag != STREAM2FILE_STATUS_RUNNING) goto terminate_thread; usleep(1000); } } terminate_thread: if (fd2 != -1) close (fd2); pthread_exit(NULL); }