static void encode_2pass_prepare(struct encode_lavc_context *ctx, AVDictionary **dictp, AVStream *stream, AVCodecContext *codec, struct stream **bytebuf, const char *prefix) { if (!*bytebuf) { char buf[sizeof(ctx->avc->filename) + 12]; AVDictionaryEntry *de = av_dict_get(ctx->voptions, "flags", NULL, 0); snprintf(buf, sizeof(buf), "%s-%s-pass1.log", ctx->avc->filename, prefix); buf[sizeof(buf) - 1] = 0; if (value_has_flag(de ? de->value : "", "pass2")) { if (!(*bytebuf = stream_open(buf, ctx->global))) { MP_WARN(ctx, "%s: could not open '%s', " "disabling 2-pass encoding at pass 2\n", prefix, buf); codec->flags &= ~AV_CODEC_FLAG_PASS2; set_to_avdictionary(ctx, dictp, "flags", "-pass2"); } else { struct bstr content = stream_read_complete(*bytebuf, NULL, 1000000000); if (content.start == NULL) { MP_WARN(ctx, "%s: could not read '%s', " "disabling 2-pass encoding at pass 1\n", prefix, ctx->avc->filename); } else { content.start[content.len] = 0; codec->stats_in = content.start; } free_stream(*bytebuf); *bytebuf = NULL; } } if (value_has_flag(de ? de->value : "", "pass1")) { if (!(*bytebuf = open_output_stream(buf, ctx->global))) { MP_WARN(ctx, "%s: could not open '%s', disabling " "2-pass encoding at pass 1\n", prefix, ctx->avc->filename); set_to_avdictionary(ctx, dictp, "flags", "-pass1"); } } } }
static bool open_this_file(int i,char *outfilename,progress_info *proginfo) { unsigned char header[CANONICAL_HEADER_SIZE]; create_output_filename(files[i]->filename,files[i]->input_format->extension,outfilename); proginfo->filename1 = files[i]->filename; proginfo->filedesc1 = files[i]->m_ss; proginfo->filename2 = outfilename; if (NULL == (files[i]->output = open_output_stream(outfilename,&files[i]->output_proc))) { prog_error(proginfo); st_error("could not open output file: [%s]",outfilename); } make_canonical_header(header,files[i]); if ((numfiles - 1 == i) && pad) put_data_size(header,CANONICAL_HEADER_SIZE,files[i]->new_data_size+pad_bytes); else { put_data_size(header,CANONICAL_HEADER_SIZE,files[i]->new_data_size); if (files[i]->new_data_size & 1) put_chunk_size(header,(files[i]->new_data_size + 1) + CANONICAL_HEADER_SIZE - 8); } if (write_n_bytes(files[i]->output,header,CANONICAL_HEADER_SIZE,proginfo) != CANONICAL_HEADER_SIZE) { prog_error(proginfo); st_warning("error while writing %d-byte WAVE header",CANONICAL_HEADER_SIZE); return FALSE; } proginfo->filename2 = outfilename; proginfo->bytes_total = files[i]->new_data_size + CANONICAL_HEADER_SIZE; return TRUE; }
static bool do_join() { int i,bytes_to_skip,bytes_to_xfer; proc_info output_proc; char outfilename[FILENAME_SIZE]; wlong total=0; unsigned char header[CANONICAL_HEADER_SIZE]; FILE *output; wave_info *joined_info; bool success; progress_info proginfo; success = FALSE; create_output_filename("","",outfilename); for (i=0;i<numfiles;i++) total += files[i]->data_size; if (all_files_cd_quality && (total % CD_BLOCK_SIZE) != 0) { pad_bytes = CD_BLOCK_SIZE - (total % CD_BLOCK_SIZE); if (JOIN_NOPAD != pad_type) total += pad_bytes; } if (NULL == (joined_info = new_wave_info(NULL))) { st_error("could not allocate memory for joined file information"); } joined_info->chunk_size = total + CANONICAL_HEADER_SIZE - 8; joined_info->channels = files[0]->channels; joined_info->samples_per_sec = files[0]->samples_per_sec; joined_info->avg_bytes_per_sec = files[0]->avg_bytes_per_sec; joined_info->rate = files[0]->rate; joined_info->block_align = files[0]->block_align; joined_info->bits_per_sample = files[0]->bits_per_sample; joined_info->data_size = total; joined_info->wave_format = files[0]->wave_format; joined_info->problems = (files[0]->problems & PROBLEM_NOT_CD_QUALITY); if (PROB_ODD_SIZED_DATA(joined_info)) joined_info->chunk_size++; joined_info->total_size = joined_info->chunk_size + 8; joined_info->length = joined_info->data_size / joined_info->rate; joined_info->exact_length = (double)joined_info->data_size / (double)joined_info->rate; length_to_str(joined_info); proginfo.initialized = FALSE; proginfo.prefix = "Joining"; proginfo.clause = "-->"; proginfo.filename1 = files[0]->filename; proginfo.filedesc1 = files[0]->m_ss; proginfo.filename2 = outfilename; proginfo.filedesc2 = joined_info->m_ss; proginfo.bytes_total = files[0]->total_size; prog_update(&proginfo); if (NULL == (output = open_output_stream(outfilename,&output_proc))) { st_error("could not open output file"); } make_canonical_header(header,joined_info); if (write_n_bytes(output,header,CANONICAL_HEADER_SIZE,&proginfo) != CANONICAL_HEADER_SIZE) { prog_error(&proginfo); st_warning("error while writing %d-byte WAVE header",CANONICAL_HEADER_SIZE); goto cleanup; } if (all_files_cd_quality && (JOIN_PREPAD == pad_type) && pad_bytes) { if (pad_bytes != write_padding(output,pad_bytes,&proginfo)) { prog_error(&proginfo); st_warning("error while pre-padding with %d zero-bytes",pad_bytes); goto cleanup; } } for (i=0;i<numfiles;i++) { proginfo.bytes_total = files[i]->total_size; proginfo.filename1 = files[i]->filename; proginfo.filedesc1 = files[i]->m_ss; prog_update(&proginfo); if (!open_input_stream(files[i])) { prog_error(&proginfo); st_warning("could not reopen input file"); goto cleanup; } bytes_to_skip = files[i]->header_size; while (bytes_to_skip > 0) { bytes_to_xfer = min(bytes_to_skip,CANONICAL_HEADER_SIZE); if (read_n_bytes(files[i]->input,header,bytes_to_xfer,NULL) != bytes_to_xfer) { prog_error(&proginfo); st_warning("error while reading %d bytes of data",bytes_to_xfer); goto cleanup; } bytes_to_skip -= bytes_to_xfer; } if (transfer_n_bytes(files[i]->input,output,files[i]->data_size,&proginfo) != files[i]->data_size) { prog_error(&proginfo); st_warning("error while transferring %lu bytes of data",files[i]->data_size); goto cleanup; } prog_success(&proginfo); close_input_stream(files[i]); } if (all_files_cd_quality && JOIN_POSTPAD == pad_type && pad_bytes) { if (pad_bytes != write_padding(output,pad_bytes,NULL)) { prog_error(&proginfo); st_warning("error while post-padding with %d zero-bytes",pad_bytes); goto cleanup; } } if ((JOIN_NOPAD == pad_type) && PROB_ODD_SIZED_DATA(joined_info) && (1 != write_padding(output,1,NULL))) { prog_error(&proginfo); st_warning("error while NULL-padding odd-sized data chunk"); goto cleanup; } if (all_files_cd_quality) { if (JOIN_NOPAD != pad_type) { if (pad_bytes) st_info("%s-padded output file with %d zero-bytes.\n",((JOIN_PREPAD == pad_type)?"Pre":"Post"),pad_bytes); else st_info("No padding needed.\n"); } else { st_info("Output file was not padded, "); if (pad_bytes) st_info("though it needs %d bytes of padding.\n",pad_bytes); else st_info("nor was it needed.\n"); } } success = TRUE; cleanup: if ((CLOSE_CHILD_ERROR_OUTPUT == close_output(output,output_proc)) || !success) { success = FALSE; remove_file(outfilename); st_error("failed to join files"); } return success; }
static bool split_file(wave_info *info) { unsigned char header[CANONICAL_HEADER_SIZE]; char outfilename[FILENAME_SIZE],filenum[FILENAME_SIZE]; int current; wint discard,bytes; bool success; wlong leadin_bytes, leadout_bytes, bytes_to_xfer; progress_info proginfo; // uwe double start_time, end_time, last_end_time; success = FALSE; proginfo.initialized = FALSE; proginfo.prefix = "Splitting"; proginfo.clause = "-->"; proginfo.filename1 = info->filename; proginfo.filedesc1 = info->m_ss; proginfo.filename2 = NULL; proginfo.filedesc2 = NULL; proginfo.bytes_total = 0; if (!open_input_stream(info)) { prog_error(&proginfo); st_error("could not reopen input file: [%s]",info->filename); } discard = info->header_size; while (discard > 0) { bytes = min(discard,CANONICAL_HEADER_SIZE); if (read_n_bytes(info->input,header,bytes,NULL) != bytes) { prog_error(&proginfo); st_error("error while discarding %d-byte WAVE header",info->header_size); } discard -= bytes; } leadin_bytes = (leadin) ? smrt_parse((unsigned char *)leadin,info) : 0; leadout_bytes = (leadout) ? smrt_parse((unsigned char *)leadout,info) : 0; adjust_for_leadinout(leadin_bytes,leadout_bytes); // uwe transcription st_output("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"); st_output("<Trans version=\"2\">\n\n"); start_time = end_time = last_end_time = 0; for (current=0;current<numfiles;current++) { if (SPLIT_INPUT_CUE == input_type && cueinfo.format) { create_output_filename(cueinfo.filenames[current],"",outfilename); } else { st_snprintf(filenum,8,num_format,current+offset); create_output_filename(filenum,"",outfilename); } files[current]->chunk_size = files[current]->data_size + CANONICAL_HEADER_SIZE - 8; files[current]->channels = info->channels; files[current]->samples_per_sec = info->samples_per_sec; files[current]->avg_bytes_per_sec = info->avg_bytes_per_sec; files[current]->block_align = info->block_align; files[current]->bits_per_sample = info->bits_per_sample; files[current]->wave_format = info->wave_format; files[current]->rate = info->rate; files[current]->length = files[current]->data_size / (wlong)info->rate; files[current]->exact_length = (double)files[current]->data_size / (double)info->rate; files[current]->total_size = files[current]->chunk_size + 8; length_to_str(files[current]); proginfo.filedesc2 = files[current]->m_ss; proginfo.bytes_total = files[current]->total_size; if (extract_track[current]) { proginfo.prefix = "Splitting"; proginfo.filename2 = outfilename; // uwe transcription start_time += last_end_time; end_time += files[current]->data_size / (wlong)info->rate; last_end_time = end_time; printf("<Turn startTime=\"%.2f\"", start_time); // %.2f st_output(" endTime=\"%.2f\"", end_time); st_output(" splitFilename=\"%s\"", outfilename); st_output(" speaker=\"spk1\">\n"); st_output("<Sync time=\"%.2f\"/>\n", start_time); st_output("***Include transcript words here***\n"); st_output("</Turn>\n"); if (NULL == (files[current]->output = open_output_stream(outfilename,&files[current]->output_proc))) { prog_error(&proginfo); st_error("could not open output file"); } } else { proginfo.prefix = "Skipping "; proginfo.filename2 = NULLDEVICE; if (NULL == (files[current]->output = open_output(NULLDEVICE))) { prog_error(&proginfo); st_error("while skipping track %d: could not open output file: [%s]",current+1,NULLDEVICE); } files[current]->output_proc.pid = NO_CHILD_PID; } if (PROB_ODD_SIZED_DATA(files[current])) files[current]->chunk_size++; make_canonical_header(header,files[current]); // uwe disable //prog_update(&proginfo); if (write_n_bytes(files[current]->output,header,CANONICAL_HEADER_SIZE,&proginfo) != CANONICAL_HEADER_SIZE) { prog_error(&proginfo); st_warning("error while writing %d-byte WAVE header",CANONICAL_HEADER_SIZE); goto cleanup; } /* if this is not the first file, finish up writing previous file, and simultaneously start writing to current file */ if (0 != current) { /* write overlapping lead-in/lead-out data to both previous and current files */ if (transfer_n_bytes2(info->input,files[current]->output,files[current-1]->output,leadin_bytes+leadout_bytes,&proginfo) != leadin_bytes+leadout_bytes) { prog_error(&proginfo); st_warning("error while transferring %ld bytes of lead-in/lead-out",leadin_bytes+leadout_bytes); goto cleanup; } /* pad and close previous file */ if (PROB_ODD_SIZED_DATA(files[current-1]) && (1 != write_padding(files[current-1]->output,1,&proginfo))) { prog_error(&proginfo); st_warning("error while NULL-padding odd-sized data chunk"); goto cleanup; } close_output(files[current-1]->output,files[current-1]->output_proc); } /* transfer unique non-overlapping data from input file to current file */ bytes_to_xfer = files[current]->new_data_size; if (0 != current) bytes_to_xfer -= leadout_bytes; if (numfiles - 1 != current) bytes_to_xfer -= leadin_bytes; if (transfer_n_bytes(info->input,files[current]->output,bytes_to_xfer,&proginfo) != bytes_to_xfer) { prog_error(&proginfo); st_warning("error while transferring %ld bytes of data",bytes_to_xfer); goto cleanup; } /* if this is the last file, close it */ if (numfiles - 1 == current) { /* pad and close current file */ if (PROB_ODD_SIZED_DATA(files[current]) && (1 != write_padding(files[current]->output,1,&proginfo))) { prog_error(&proginfo); st_warning("error while NULL-padding odd-sized data chunk"); goto cleanup; } close_output(files[current]->output,files[current]->output_proc); // uwe transcription st_output("</Trans>\n"); } // uwe disable // prog_success(&proginfo); } close_input_stream(info); success = TRUE; cleanup: if (!success) { close_output(files[current]->output,files[current]->output_proc); remove_file(outfilename); st_error("failed to split file"); } return success; }
SCM make_ffmpeg_output(SCM scm_file_name, SCM scm_format_name, SCM scm_video_parameters, SCM scm_have_video, SCM scm_audio_parameters, SCM scm_have_audio, SCM scm_debug) { SCM retval; struct ffmpeg_t *self; scm_dynwind_begin(0); const char *file_name = scm_to_locale_string(scm_file_name); scm_dynwind_free(file_name); self = (struct ffmpeg_t *)scm_gc_calloc(sizeof(struct ffmpeg_t), "ffmpeg"); self->video_stream_idx = -1; self->audio_stream_idx = -1; SCM_NEWSMOB(retval, ffmpeg_tag, self); int err; const char *format_name = NULL; if (!scm_is_false(scm_format_name)) { format_name = scm_to_locale_string(scm_symbol_to_string(scm_format_name)); scm_dynwind_free(format_name); }; #ifdef HAVE_AVFORMAT_ALLOC_OUTPUT_CONTEXT2 err = avformat_alloc_output_context2(&self->fmt_ctx, NULL, format_name, file_name); if (!self->fmt_ctx) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-output", "Error initializing output format for file '~a': ~a", scm_list_2(scm_file_name, get_error_text(err))); }; #else AVOutputFormat *format; if (format_name) format = av_guess_format(format_name, NULL, NULL); else format = av_guess_format(NULL, file_name, NULL); if (!format) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-output", "Unable to determine file format for file '~a'", scm_list_1(scm_file_name)); }; self->fmt_ctx = avformat_alloc_context(); if (!self->fmt_ctx) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-output", "Error initializing output format for file '~a'", scm_list_1(scm_file_name)); }; self->fmt_ctx->oformat = format; strncpy(self->fmt_ctx->filename, file_name, sizeof(self->fmt_ctx->filename)); #endif char have_video = scm_is_true(scm_have_video); if (have_video) { // Open codec and video stream enum AVCodecID video_codec_id = self->fmt_ctx->oformat->video_codec; AVCodec *video_encoder = find_encoder(retval, video_codec_id, "video"); AVStream *video_stream = open_output_stream(retval, video_encoder, &self->video_stream_idx, "video", scm_file_name); // Get video parameters SCM scm_shape = scm_car(scm_video_parameters); SCM scm_frame_rate = scm_cadr(scm_video_parameters); SCM scm_video_bit_rate = scm_caddr(scm_video_parameters); SCM scm_aspect_ratio = scm_cadddr(scm_video_parameters); // Configure the output video codec self->video_codec_ctx = configure_output_video_codec(video_stream, video_codec_id, scm_video_bit_rate, scm_shape, scm_frame_rate, scm_aspect_ratio); // Some formats want stream headers to be separate. if (self->fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) self->video_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; // Open output video codec open_codec(retval, self->video_codec_ctx, video_encoder, "video", scm_file_name); // Allocate frame self->video_target_frame = allocate_output_video_frame(retval, self->video_codec_ctx); }; char have_audio = scm_is_true(scm_have_audio); if (have_audio) { // Open audio codec and stream enum AVCodecID audio_codec_id = self->fmt_ctx->oformat->audio_codec; AVCodec *audio_encoder = find_encoder(retval, audio_codec_id, "audio"); AVStream *audio_stream = open_output_stream(retval, audio_encoder, &self->audio_stream_idx, "audio", scm_file_name); // Get audio parameters SCM scm_select_rate = scm_car(scm_audio_parameters); SCM scm_channels = scm_cadr(scm_audio_parameters); SCM scm_audio_bit_rate = scm_caddr(scm_audio_parameters); SCM scm_select_format = scm_cadddr(scm_audio_parameters); // Configure the output audio codec self->audio_codec_ctx = configure_output_audio_codec(retval, audio_stream, audio_codec_id, scm_select_rate, scm_channels, scm_audio_bit_rate, scm_select_format); // Some formats want stream headers to be separate. if (self->fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) self->audio_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; // Open output audio codec open_codec(retval, self->audio_codec_ctx, audio_encoder, "audio", scm_file_name); // Allocate audio frame self->audio_target_frame = allocate_output_audio_frame(retval, self->audio_codec_ctx, self->audio_codec_ctx->sample_fmt); self->audio_packed_frame = allocate_output_audio_frame(retval, self->audio_codec_ctx, av_get_packed_sample_fmt(self->audio_codec_ctx->sample_fmt)); // Initialise audio buffer ringbuffer_init(&self->audio_buffer, 1024); }; if (scm_is_true(scm_debug)) av_dump_format(self->fmt_ctx, 0, file_name, 1); // Open the output file if needed if (!(self->fmt_ctx->oformat->flags & AVFMT_NOFILE)) { int err = avio_open(&self->fmt_ctx->pb, file_name, AVIO_FLAG_WRITE); if (err < 0) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-output", "Could not open '~a': ~a", scm_list_2(scm_file_name, get_error_text(err))); } self->output_file = 1; } // Write video file header err = avformat_write_header(self->fmt_ctx, NULL); if (err < 0) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-output", "Error writing header of video '~a': ~a", scm_list_2(scm_file_name, get_error_text(err))); }; self->header_written = 1; scm_dynwind_end(); return retval; }