SCM make_ffmpeg_input(SCM scm_file_name, 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; err = avformat_open_input(&self->fmt_ctx, file_name, NULL, NULL); if (err < 0) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-input", "Error opening file '~a': ~a", scm_list_2(scm_file_name, get_error_text(err))); }; err = avformat_find_stream_info(self->fmt_ctx, NULL); if (err < 0) { ffmpeg_destroy(retval); scm_misc_error("make-ffmpeg-input", "No stream information in file '~a': ~a", scm_list_2(scm_file_name, get_error_text(err))); }; // TODO: only open desired streams // Open video stream self->video_stream_idx = av_find_best_stream(self->fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); if (self->video_stream_idx >= 0) self->video_codec_ctx = open_decoder(retval, scm_file_name, video_stream(self), "video"); // Open audio stream self->audio_stream_idx = av_find_best_stream(self->fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); if (self->audio_stream_idx >= 0) self->audio_codec_ctx = open_decoder(retval, scm_file_name, audio_stream(self), "audio"); // Print debug information if (scm_is_true(scm_debug)) av_dump_format(self->fmt_ctx, 0, file_name, 0); // Allocate input frames self->video_target_frame = allocate_frame(retval); self->audio_target_frame = allocate_frame(retval); // Initialise data packet av_init_packet(&self->pkt); self->pkt.data = NULL; self->pkt.size = 0; scm_dynwind_end(); return retval; }
int lwlibav_get_desired_video_track ( const char *file_path, lwlibav_video_decode_handler_t *vdhp, int threads ) { int error = vdhp->stream_index < 0 || vdhp->frame_count == 0 || lavf_open_file( &vdhp->format, file_path, &vdhp->lh ); AVCodecContext *ctx = !error ? vdhp->format->streams[ vdhp->stream_index ]->codec : NULL; if( error || open_decoder( ctx, vdhp->codec_id, threads ) ) { if( vdhp->index_entries ) av_freep( &vdhp->index_entries ); if( vdhp->frame_list ) lw_freep( &vdhp->frame_list ); if( vdhp->order_converter ) lw_freep( &vdhp->order_converter ); if( vdhp->keyframe_list ) lw_freep( &vdhp->keyframe_list ); if( vdhp->format ) { lavf_close_file( &vdhp->format ); vdhp->format = NULL; } return -1; } vdhp->ctx = ctx; ctx->refcounted_frames = 1; return 0; }
int find_and_open_decoder ( AVCodecContext *ctx, enum AVCodecID codec_id, const char **preferred_decoder_names, int threads ) { AVCodec *codec = find_decoder( codec_id, preferred_decoder_names ); if( !codec ) return -1; ctx->thread_count = threads; return (open_decoder( ctx, codec ) < 0) ? -1 : 0; }
size_t lha_reader_read(LHAReader *reader, void *buf, size_t buf_len) { // The first time that we try to read the current file, we // must create the decoder to decompress it. if (reader->decoder == NULL) { if (!open_decoder(reader, NULL, NULL)) { return 0; } } // Read from decoder and return the result. return lha_decoder_read(reader->decoder, buf, buf_len); }
static int extract_file(LHAReader *reader, char *filename, LHADecoderProgressCallback callback, void *callback_data) { FILE *fstream; char *tmp_filename = NULL; int result; // Construct filename? if (filename == NULL) { tmp_filename = full_path_for_header(reader->curr_file); if (tmp_filename == NULL) { return 0; } filename = tmp_filename; } // Create decoder. If the file cannot be created, there is no // need to even create an output file. If successful, open the // output file and decode. result = 0; if (open_decoder(reader, callback, callback_data)) { fstream = open_output_file(reader, filename); if (fstream != NULL) { result = do_decode(reader, fstream); fclose(fstream); } } // Set timestamp on file: if (result) { set_timestamps_from_header(filename, reader->curr_file); } free(tmp_filename); return result; }
int lha_reader_check(LHAReader *reader, LHADecoderProgressCallback callback, void *callback_data) { if (reader->curr_file_type != CURR_FILE_NORMAL) { return 0; } // CRC checking of directories is not necessary. if (!strcmp(reader->curr_file->compress_method, LHA_COMPRESS_TYPE_DIR)) { return 1; } // Decode file. return open_decoder(reader, callback, callback_data) && do_decode(reader, NULL); }
void lwlibav_flush_buffers ( lwlibav_decode_handler_t *dhp ) { /* Close and reopen the decoder even if the decoder implements avcodec_flush_buffers(). * It seems this brings about more stable composition when seeking. */ AVCodecContext *ctx = dhp->format->streams[ dhp->stream_index ]->codec; const AVCodec *codec = ctx->codec; avcodec_close( ctx ); ctx->codec_id = AV_CODEC_ID_NONE; /* AVCodecContext.codec_id is supposed to be set properly in avcodec_open2(). * This avoids avcodec_open2() failure by the difference of enum AVCodecID. * For instance, when stream is encoded as AC-3, * AVCodecContext.codec_id might have been set to AV_CODEC_ID_EAC3 * while AVCodec.id is set to AV_CODEC_ID_AC3. */ if( open_decoder( ctx, codec ) < 0 ) { dhp->error = 1; lw_log_show( &dhp->lh, LW_LOG_FATAL, "Failed to flush buffers.\n" "It is recommended you reopen the file." ); } dhp->exh.delay_count = 0; }
void lwlibav_update_configuration ( lwlibav_decode_handler_t *dhp, uint32_t frame_number, int extradata_index, int64_t rap_pos ) { lwlibav_extradata_handler_t *exhp = &dhp->exh; if( exhp->entry_count == 0 || extradata_index < 0 ) { /* No need to update the extradata. */ exhp->current_index = extradata_index; lwlibav_flush_buffers( dhp ); return; } AVCodecContext *ctx = dhp->format->streams[ dhp->stream_index ]->codec; void *app_specific = ctx->opaque; avcodec_close( ctx ); if( ctx->extradata ) { av_freep( &ctx->extradata ); ctx->extradata_size = 0; } /* Find an appropriate decoder. */ char error_string[96] = { 0 }; lwlibav_extradata_t *entry = &exhp->entries[extradata_index]; const AVCodec *codec = find_decoder( entry->codec_id, dhp->preferred_decoder_names ); if( !codec ) { strcpy( error_string, "Failed to find the decoder.\n" ); goto fail; } /* Get decoder default settings. */ int thread_count = ctx->thread_count; if( avcodec_get_context_defaults3( ctx, codec ) < 0 ) { strcpy( error_string, "Failed to get CODEC default.\n" ); goto fail; } /* Set up decoder basic settings. */ if( ctx->codec_type == AVMEDIA_TYPE_VIDEO ) set_video_basic_settings( dhp, frame_number ); else set_audio_basic_settings( dhp, frame_number ); /* Update extradata. */ if( entry->extradata_size > 0 ) { ctx->extradata = (uint8_t *)av_malloc( entry->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE ); if( !ctx->extradata ) { strcpy( error_string, "Failed to allocate extradata.\n" ); goto fail; } ctx->extradata_size = entry->extradata_size; memcpy( ctx->extradata, entry->extradata, ctx->extradata_size ); memset( ctx->extradata + ctx->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE ); } /* AVCodecContext.codec_id is supposed to be set properly in avcodec_open2(). * See lwlibav_flush_buffers(), why this is needed. */ ctx->codec_id = AV_CODEC_ID_NONE; /* This is needed by some CODECs such as UtVideo and raw video. */ ctx->codec_tag = entry->codec_tag; /* Open an appropriate decoder. * Here, we force single threaded decoding since some decoder doesn't do its proper initialization with multi-threaded decoding. */ ctx->thread_count = 1; if( open_decoder( ctx, codec ) < 0 ) { strcpy( error_string, "Failed to open decoder.\n" ); goto fail; } exhp->current_index = extradata_index; exhp->delay_count = 0; /* Set up decoder basic settings by actual decoding. */ if( ctx->codec_type == AVMEDIA_TYPE_VIDEO ? try_decode_video_frame( dhp, frame_number, rap_pos, error_string ) < 0 : try_decode_audio_frame( dhp, frame_number, error_string ) < 0 ) goto fail; /* Reopen/flush with the requested number of threads. */ ctx->thread_count = thread_count; int width = ctx->width; int height = ctx->height; lwlibav_flush_buffers( dhp ); ctx->get_buffer2 = exhp->get_buffer ? exhp->get_buffer : avcodec_default_get_buffer2; ctx->opaque = app_specific; /* avcodec_open2() may have changed resolution unexpectedly. */ ctx->width = width; ctx->height = height; return; fail: exhp->delay_count = 0; dhp->error = 1; lw_log_show( &dhp->lh, LW_LOG_FATAL, "%sIt is recommended you reopen the file.", error_string ); }