static void init (GeglProperties *o) { static gint inited = 0; /*< this is actually meant to be static, only to be done once */ Priv *p = (Priv*)o->user_data; if (p == NULL) { p = g_new0 (Priv, 1); o->user_data = (void*) p; } if (!inited) { av_register_all (); avcodec_register_all (); inited = 1; } clear_audio_track (o); p->audio_pos = 0; p->audio_read_pos = 0; p->audio_sample_rate = -1; /* only do this if it hasn't been manually set? */ }
static void init (GeglProperties *o) { Priv *p = (Priv*)o->user_data; static gint av_inited = 0; if (av_inited == 0) { av_register_all (); av_inited = 1; } if (p == NULL) { p = g_new0 (Priv, 1); o->user_data = (void*) p; } p->width = 320; p->height = 200; clear_audio_track (o); p->loadedfilename = g_strdup (""); ff_cleanup (o); av_log_set_level (AV_LOG_WARNING); }
static void ff_cleanup (GeglProperties *o) { Priv *p = (Priv*)o->user_data; if (p) { clear_audio_track (o); if (p->loadedfilename) g_free (p->loadedfilename); if (p->video_stream && p->video_stream->codec) avcodec_close (p->video_stream->codec); if (p->audio_stream && p->audio_stream->codec) avcodec_close (p->audio_stream->codec); if (p->video_fcontext) avformat_close_input(&p->video_fcontext); if (p->audio_fcontext) avformat_close_input(&p->audio_fcontext); if (p->rgb_frame) av_free (p->rgb_frame); if (p->lavc_frame) av_free (p->lavc_frame); p->video_fcontext = NULL; p->audio_fcontext = NULL; p->lavc_frame = NULL; p->rgb_frame = NULL; p->loadedfilename = NULL; } }
static void prepare (GeglOperation *operation) { GeglProperties *o = GEGL_PROPERTIES (operation); Priv *p = (Priv*)o->user_data; if (p == NULL) init (o); p = (Priv*)o->user_data; g_assert (o->user_data != NULL); gegl_operation_set_format (operation, "output", babl_format ("R'G'B' u8")); if (!p->loadedfilename || strcmp (p->loadedfilename, o->path) || p->prevframe > o->frame /* a bit heavy handed, but improves consistency */ ) { gint i; gint err; ff_cleanup (o); err = avformat_open_input(&p->video_fcontext, o->path, NULL, 0); if (err < 0) { print_error (o->path, err); } err = avformat_find_stream_info (p->video_fcontext, NULL); if (err < 0) { g_warning ("ff-load: error finding stream info for %s", o->path); return; } err = avformat_open_input(&p->audio_fcontext, o->path, NULL, 0); if (err < 0) { print_error (o->path, err); } err = avformat_find_stream_info (p->audio_fcontext, NULL); if (err < 0) { g_warning ("ff-load: error finding stream info for %s", o->path); return; } for (i = 0; i< p->video_fcontext->nb_streams; i++) { AVCodecContext *c = p->video_fcontext->streams[i]->codec; if (c->codec_type == AVMEDIA_TYPE_VIDEO) { p->video_stream = p->video_fcontext->streams[i]; p->video_index = i; } if (c->codec_type == AVMEDIA_TYPE_AUDIO) { p->audio_stream = p->audio_fcontext->streams[i]; p->audio_index = i; } } p->video_codec = avcodec_find_decoder (p->video_stream->codec->codec_id); if (p->audio_stream) { p->audio_codec = avcodec_find_decoder (p->audio_stream->codec->codec_id); if (p->audio_codec == NULL) g_warning ("audio codec not found"); else if (avcodec_open2 (p->audio_stream->codec, p->audio_codec, NULL) < 0) { g_warning ("error opening codec %s", p->audio_stream->codec->codec->name); } else { o->audio_sample_rate = p->audio_stream->codec->sample_rate; o->audio_channels = MIN(p->audio_stream->codec->channels, GEGL_MAX_AUDIO_CHANNELS); } } p->video_stream->codec->err_recognition = AV_EF_IGNORE_ERR | AV_EF_BITSTREAM | AV_EF_BUFFER; p->video_stream->codec->workaround_bugs = FF_BUG_AUTODETECT; if (p->video_codec == NULL) g_warning ("video codec not found"); if (avcodec_open2 (p->video_stream->codec, p->video_codec, NULL) < 0) { g_warning ("error opening codec %s", p->video_stream->codec->codec->name); return; } p->width = p->video_stream->codec->width; p->height = p->video_stream->codec->height; p->lavc_frame = av_frame_alloc (); if (o->video_codec) g_free (o->video_codec); if (p->video_codec->name) o->video_codec = g_strdup (p->video_codec->name); else o->video_codec = g_strdup (""); if (o->audio_codec) g_free (o->audio_codec); if (p->audio_codec && p->audio_codec->name) o->audio_codec = g_strdup (p->audio_codec->name); else o->audio_codec = g_strdup (""); if (p->loadedfilename) g_free (p->loadedfilename); p->loadedfilename = g_strdup (o->path); p->prevframe = -1; p->a_prevframe = -1; o->frames = p->video_stream->nb_frames; o->frame_rate = av_q2d (av_guess_frame_rate (p->video_fcontext, p->video_stream, NULL)); if (!o->frames) { /* this is a guesstimate of frame-count */ o->frames = p->video_fcontext->duration * o->frame_rate / AV_TIME_BASE; /* make second guess for things like luxo */ if (o->frames < 1) o->frames = 23; } #if 0 { int m ,h; int s = o->frames / o->frame_rate; m = s / 60; s -= m * 60; h = m / 60; m -= h * 60; fprintf (stdout, "duration: %02i:%02i:%02i\n", h, m, s); } #endif p->codec_delay = p->video_stream->codec->delay; if (!strcmp (o->video_codec, "mpeg1video")) p->codec_delay = 1; else if (!strcmp (o->video_codec, "h264")) { if (strstr (p->video_fcontext->filename, ".mp4") || strstr (p->video_fcontext->filename, ".MP4")) /* XXX: too hacky, isn't there an avformat thing to use?, or perhaps we can measure this when decoding the first frame. */ p->codec_delay = 3; else p->codec_delay = 0; } clear_audio_track (o); } }
/* maintain list of audio samples */ static int decode_audio (GeglOperation *operation, gdouble pts1, gdouble pts2) { GeglProperties *o = GEGL_PROPERTIES (operation); Priv *p = (Priv*)o->user_data; pts1 -= 2.0; if (pts1 < 0.0)pts1 = 0.0; if(pts1 - 15.0 > p->prevapts){ int64_t seek_target = av_rescale_q (pts1 * AV_TIME_BASE, AV_TIME_BASE_Q, p->audio_stream->time_base); clear_audio_track (o); p->prevapts = 0.0; if (av_seek_frame (p->audio_fcontext, p->audio_stream->index, seek_target, (AVSEEK_FLAG_BACKWARD)) < 0) fprintf (stderr, "audio seek error!\n"); else avcodec_flush_buffers (p->audio_stream->codec); } while (p->prevapts <= pts2) { AVPacket pkt = {0,}; int decoded_bytes; if (av_read_frame (p->audio_fcontext, &pkt) < 0) { av_free_packet (&pkt); return -1; } if (pkt.stream_index==p->audio_index && p->audio_stream) { static AVFrame frame; int got_frame; decoded_bytes = avcodec_decode_audio4(p->audio_stream->codec, &frame, &got_frame, &pkt); if (decoded_bytes < 0) { fprintf (stderr, "avcodec_decode_audio4 failed for %s\n", o->path); } if (got_frame) { int samples_left = frame.nb_samples; int si = 0; while (samples_left) { int sample_count = samples_left; int channels = MIN(p->audio_stream->codec->channels, GEGL_MAX_AUDIO_CHANNELS); GeglAudioFragment *af = gegl_audio_fragment_new (o->audio_sample_rate, channels, AV_CH_LAYOUT_STEREO, samples_left); //); switch (p->audio_stream->codec->sample_fmt) { case AV_SAMPLE_FMT_FLT: for (gint i = 0; i < sample_count; i++) for (gint c = 0; c < channels; c++) af->data[c][i] = ((int16_t *)frame.data[0])[(i + si) * channels + c]; break; case AV_SAMPLE_FMT_FLTP: for (gint i = 0; i < sample_count; i++) for (gint c = 0; c < channels; c++) { af->data[c][i] = ((float *)frame.data[c])[i + si]; } break; case AV_SAMPLE_FMT_S16: for (gint i = 0; i < sample_count; i++) for (gint c = 0; c < channels; c++) af->data[c][i] = ((int16_t *)frame.data[0])[(i + si) * channels + c] / 32768.0; break; case AV_SAMPLE_FMT_S16P: for (gint i = 0; i < sample_count; i++) for (gint c = 0; c < channels; c++) af->data[c][i] = ((int16_t *)frame.data[c])[i + si] / 32768.0; break; case AV_SAMPLE_FMT_S32: for (gint i = 0; i < sample_count; i++) for (gint c = 0; c < channels; c++) af->data[c][i] = ((int32_t *)frame.data[0])[(i + si) * channels + c] / 2147483648.0; break; case AV_SAMPLE_FMT_S32P: for (gint i = 0; i < sample_count; i++) for (gint c = 0; c < channels; c++) af->data[c][i] = ((int32_t *)frame.data[c])[i + si] / 2147483648.0; break; default: g_warning ("undealt with sample format\n"); } gegl_audio_fragment_set_sample_count (af, sample_count); gegl_audio_fragment_set_pos (af, (long int)av_rescale_q ((pkt.pts), p->audio_stream->time_base, AV_TIME_BASE_Q) * o->audio_sample_rate /AV_TIME_BASE); p->audio_pos += sample_count; p->audio_track = g_list_append (p->audio_track, af); samples_left -= sample_count; si += sample_count; } p->prevapts = pkt.pts * av_q2d (p->audio_stream->time_base); } } av_free_packet (&pkt); } return 0; }