int rename2 (const char *oldname, const char *newname) { int retval; char dir1[FILENAME_MAX], dir2[FILENAME_MAX]; struct stat fstate; dirname2 (oldname, dir1); dirname2 (newname, dir2); // We should use dirname{2}() in case oldname or newname doesn't exist yet if (one_filesystem (dir1, dir2)) { if (access (newname, F_OK) == 0 && !one_file (oldname, newname)) { stat (newname, &fstate); chmod (newname, fstate.st_mode | S_IWUSR); remove (newname); // *try* to remove or rename() will fail } retval = rename (oldname, newname); } else { retval = fcopy_raw (oldname, newname); // don't remove unless the file can be copied if (retval == 0) { stat (oldname, &fstate); chmod (oldname, fstate.st_mode | S_IWUSR); remove (oldname); } } return retval; }
char * mkbak (const char *filename, backup_t type) { static char buf[FILENAME_MAX]; if (access (filename, R_OK) != 0) return (char *) filename; strcpy (buf, filename); set_suffix (buf, ".bak"); if (strcmp (filename, buf) != 0) { remove (buf); // *try* to remove or rename() will fail if (rename (filename, buf)) // keep file attributes like date, etc. { fprintf (stderr, "ERROR: Can't rename \"%s\" to \"%s\"\n", filename, buf); exit (1); } } else // handle the case where filename has the suffix ".bak". { char buf2[FILENAME_MAX]; if (!dirname2 (filename, buf)) { fprintf (stderr, "INTERNAL ERROR: dirname2() returned NULL\n"); exit (1); } if (buf[0] != 0) if (buf[strlen (buf) - 1] != FILE_SEPARATOR) strcat (buf, FILE_SEPARATOR_S); strcat (buf, basename2 (tmpnam2 (buf2))); if (rename (filename, buf)) { fprintf (stderr, "ERROR: Can't rename \"%s\" to \"%s\"\n", filename, buf); exit (1); } } switch (type) { case BAK_MOVE: return buf; case BAK_DUPE: default: if (fcopy (buf, 0, fsizeof (buf), filename, "wb")) { fprintf (stderr, "ERROR: Can't open \"%s\" for writing\n", filename); exit (1); } sync (); return buf; } }
st_strpath_t * strpath (st_strpath_t *path, const char *path_s) { // TODO: compare this with splitpath() if (path_s == NULL) return NULL; realpath2 (path_s, path->realpath); #if defined DJGPP || defined __CYGWIN__ || defined _WIN32 if (isalpha (path->realpath[0]) && path->realpath[1] == ':' && path->realpath[2] == FILE_SEPARATOR) sprintf (path->drive, "%c:\\", toupper (path->realpath[0])); #else strcpy (path->drive, FILE_SEPARATOR_S); #endif dirname2 (path_s, path->dirname); strcpy (path->basename, basename2 (path_s)); strcpy (path->suffix, get_suffix (path_s)); return path; }
static VALUE segmenter_segment(VALUE klass, VALUE input_, VALUE output_prefix_, VALUE duration_ ) { const char *input; const char *output_prefix; int segment_duration; long max_tsfiles = 0; double prev_segment_time = 0; unsigned int output_index = 1; AVInputFormat *ifmt; AVOutputFormat *ofmt; AVFormatContext *ic = NULL; AVFormatContext *oc; AVStream *video_st; AVStream *audio_st; AVCodec *codec; char *output_filename; char *remove_filename; int video_index; int audio_index; unsigned int first_segment = 1; unsigned int last_segment = 0; int decode_done; int ret; unsigned int i; int remove_file; bool soundOnly = false; VALUE sArray = rb_ary_new(); av_register_all(); av_log_set_level(AV_LOG_PANIC); input = RSTRING_PTR(input_); output_prefix = RSTRING_PTR(output_prefix_); segment_duration = (FIX2INT(duration_)); char *folder = dirname2(strdup(input)); remove_filename = malloc(sizeof(char) * (strlen(output_prefix) + 15)); if (!remove_filename) { rb_raise(rb_eNoMemError, "Could not allocate space for remove filenames"); } output_filename = malloc(sizeof(char) * (strlen(output_prefix) + strlen(folder) + 15)); if (!output_filename) { rb_raise(rb_eNoMemError, "Could not allocate space for output filenames"); } ifmt = av_find_input_format("mpegts"); if (!ifmt) { rb_raise(rb_eException, "Could not find MPEG-TS demuxer"); } ret = av_open_input_file(&ic, input, ifmt, 0, NULL); if (ret != 0) { rb_raise(rb_eException, "Could not open input file, make sure it is an mpegts file: %d %s", ret, input); } if (av_find_stream_info(ic) < 0) { rb_raise(rb_eException, "Could not read stream information"); } ofmt = av_guess_format("mpegts", NULL, NULL); if (!ofmt) { rb_raise(rb_eException, "Could not find MPEG-TS muxer"); } oc = avformat_alloc_context(); if (!oc) { rb_raise(rb_eException, "Could not allocated output context"); } oc->oformat = ofmt; ic->flags |= AVFMT_FLAG_IGNDTS; video_index = -1; audio_index = -1; for (i = 0; i < ic->nb_streams && (video_index < 0 || audio_index < 0); i++) { switch (ic->streams[i]->codec->codec_type) { case CODEC_TYPE_VIDEO: video_index = i; ic->streams[i]->discard = AVDISCARD_NONE; video_st = add_output_stream(oc, ic->streams[i]); break; case CODEC_TYPE_AUDIO: audio_index = i; ic->streams[i]->discard = AVDISCARD_NONE; audio_st = add_output_stream(oc, ic->streams[i]); break; default: ic->streams[i]->discard = AVDISCARD_ALL; break; } } if(!soundOnly) { soundOnly = (video_st != NULL); } if (av_set_parameters(oc, NULL) < 0) { rb_raise(rb_eException, "Invalid output format parameters"); } dump_format(oc, 0, output_prefix, 1); if (!soundOnly) { if(video_st == NULL) { fprintf(stderr, "video_st is fail\n"); rb_raise(rb_eException, "video_st fail"); exit(1); } if(video_st->codec == NULL) { fprintf(stderr,"codec is fail\n"); rb_raise(rb_eException, "codec fail"); exit(1); } if(video_st->codec->codec_id == NULL) { fprintf(stderr, "codec_id is fail\n"); rb_raise(rb_eException, "codec fail"); exit(1); } codec = avcodec_find_decoder(video_st->codec->codec_id); if (!codec) { rb_raise(rb_eException, "Could not find video decoder, key frames will not be honored"); } if (avcodec_open(video_st->codec, codec) < 0) { rb_raise(rb_eException, "Could not open video decoder, key frames will not be honored"); } if (video_st->codec->ticks_per_frame > 1) { // h264 sets the ticks_per_frame and time_base.den but not time_base.num // since we don't use ticks_per_frame, adjust time_base.num accordingly. video_st->codec->time_base.num *= video_st->codec->ticks_per_frame; } } snprintf(output_filename, strlen(output_prefix) + strlen(folder) + 15, "%s/%s-%u.ts", folder, output_prefix, output_index++); if (url_fopen(&oc->pb, output_filename, URL_WRONLY) < 0) { rb_raise(rb_eException, "Could not open '%s'", output_filename); } if (av_write_header(oc)) { rb_raise(rb_eException, "Could not write mpegts header to first output file"); } //write_index = !write_index_file(index, tmp_index, segment_duration, output_prefix, http_prefix, first_segment, last_segment, 0, max_tsfiles); int64_t initial_audio_pts = -1; int64_t initial_video_pts = -1; double segment_time; do { AVPacket packet; //av_init_packet(&packet); decode_done = av_read_frame(ic, &packet); if (decode_done < 0) { break; } if (av_dup_packet(&packet) < 0) { rb_raise(rb_eException, "Could not duplicate packet"); av_free_packet(&packet); break; } if (!soundOnly) { if (packet.stream_index == video_index) { if (initial_video_pts < 0) initial_video_pts = packet.pts; packet.pts -= initial_video_pts; packet.dts = packet.pts; if (packet.flags & AV_PKT_FLAG_KEY) { segment_time = (double)packet.pts * video_st->time_base.num / video_st->time_base.den; } else { segment_time = prev_segment_time; } } else if (packet.stream_index == audio_index) { if (initial_audio_pts < 0) initial_audio_pts = packet.pts; packet.pts -= initial_audio_pts; packet.dts = packet.pts; segment_time = prev_segment_time; } else { segment_time = prev_segment_time; segment_time = prev_segment_time; } } else { if (packet.stream_index == audio_index) { if (initial_audio_pts < 0) initial_audio_pts = packet.pts; if (packet.flags & AV_PKT_FLAG_KEY) { segment_time = (double)packet.pts * audio_st->time_base.num / audio_st->time_base.den; } else { segment_time = prev_segment_time; } packet.pts -= initial_audio_pts; packet.dts = packet.pts; } else { segment_time = prev_segment_time; segment_time = prev_segment_time; } } if (segment_time - prev_segment_time >= segment_duration) { put_flush_packet(oc->pb); url_fclose(oc->pb); if (max_tsfiles && (int)(last_segment - first_segment) >= max_tsfiles - 1) { remove_file = 1; first_segment++; } else { remove_file = 0; } // Create Segment object VALUE seg = rb_obj_alloc(rb_cAvSegment); rb_obj_call_init(seg, 0, 0); rb_iv_set(seg, "@index", INT2FIX(++last_segment)); rb_iv_set(seg, "@duration",INT2FIX((int)floor((segment_time - prev_segment_time)))); rb_iv_set(seg, "@filename", rb_str_new2(output_filename)); rb_ary_push(sArray, seg); if (remove_file) { snprintf(remove_filename, strlen(output_prefix) + strlen(folder) + 15, "%s/%s-%u.ts", folder, output_prefix, first_segment - 1); //snprintf(remove_filename, strlen(output_prefix) + 15, "%s-%u.ts", output_prefix, first_segment - 1); remove(remove_filename); } // snprintf(output_filename, strlen(output_prefix) + 15, "%s-%u.ts", output_prefix, output_index++); snprintf(output_filename, strlen(output_prefix) + strlen(folder) + 15, "%s/%s-%u.ts", folder, output_prefix, output_index++); if (url_fopen(&oc->pb, output_filename, URL_WRONLY) < 0) { fprintf(stderr, "Could not open '%s'\n", output_filename); break; } prev_segment_time = segment_time; } ret = av_interleaved_write_frame(oc, &packet); if (ret < 0) { fprintf(stderr, "Warning: Could not write frame of stream\n"); } else if (ret > 0) { fprintf(stderr, "End of stream requested\n"); av_free_packet(&packet); break; } av_free_packet(&packet); } while (!decode_done); av_write_trailer(oc); if (!soundOnly) avcodec_close(video_st->codec); for(i = 0; i < oc->nb_streams; i++) { if(&oc->streams[i]->codec != NULL) av_freep(&oc->streams[i]->codec); if (&oc->streams[i] != NULL) av_freep(&oc->streams[i]); } url_fclose(oc->pb); av_free(oc); if (max_tsfiles && (int)(last_segment - first_segment) >= max_tsfiles - 1) { remove_file = 1; first_segment++; } else { remove_file = 0; } if (remove_file) { snprintf(remove_filename, strlen(output_prefix) + strlen(folder) + 15, "%s/%s-%u.ts", folder, output_prefix, first_segment - 1); remove(remove_filename); } return sArray; }