Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 4
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);
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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 );
}