[FFmpeg-devel] [WIP] movie video source

Stefano Sabatini stefano.sabatini-lala
Tue Dec 28 14:42:33 CET 2010


On date Sunday 2010-11-21 17:49:57 +0100, Michael Niedermayer encoded:
> On Sun, Oct 31, 2010 at 08:56:34PM +0100, Stefano Sabatini wrote:
> [...]
> > +    // Try to find the movie format (container)
> > +    if (*movie->format_name)
> > +        iformat = av_find_input_format(movie->format_name);
> > +    else
> 
> {} nitpick
> 
> 
> > +        iformat = NULL;
> > +
> > +    movie->format_ctx = NULL;
> > +    if ((ret = av_open_input_file(&movie->format_ctx, movie->file_name, iformat, 0, NULL)) < 0) {
> > +        av_log(ctx, AV_LOG_ERROR,
> > +               "Failed to av_open_input_file '%s'\n", movie->file_name);
> > +        return ret;
> > +    }
> > +    if ((ret = av_find_stream_info(movie->format_ctx)) < 0) {
> > +        av_log(ctx, AV_LOG_ERROR, "Failed to find stream info\n");
> > +        return ret;
> > +    }
> > +
> > +    // if seeking requested, we execute it
> > +    if (movie->seek_point > 0) {
> > +        timestamp = movie->seek_point;
> > +        // add the stream start time, should it exist
> > +        if (movie->format_ctx->start_time != AV_NOPTS_VALUE)
> > +            timestamp += movie->format_ctx->start_time;
> > +        if (av_seek_frame(movie->format_ctx, -1, timestamp, AVSEEK_FLAG_BACKWARD) < 0) {
> > +            av_log(ctx, AV_LOG_ERROR, "%s: could not seek to position %"PRId64"\n",
> > +                   movie->file_name, timestamp);
> > +        }
> > +    }
> > +
> 
> > +    /* find the first available video stream */
> > +    if (movie->video_stream < 0) {
> > +        for (i = 0; i < movie->format_ctx->nb_streams; i++)
> > +            if (movie->format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
> > +                movie->video_stream = i;
> > +                break;
> > +            }
> > +        if (movie->video_stream < 0) {
> > +            av_log(ctx, AV_LOG_ERROR, "No video stream found\n");
> > +            return AVERROR(EINVAL);
> > +        }
> 
> should use the same st_best_packet_count system as ffplay to select the default
> stream. Or this effectively introduces a bug that said system fixed

Updated, now it uses av_find_best_stream().
 
> 
> [....]
> > +static av_cold void uninit(AVFilterContext *ctx)
> > +{
> > +    MovieContext *movie = ctx->priv;
> > +
> > +    if (movie->codec_ctx)
> > +        avcodec_close(movie->codec_ctx);
> > +    if (movie->format_ctx)
> > +        av_close_input_file(movie->format_ctx);
> > +    av_freep(&movie->frame);
> > +    if (movie->picref)
> > +        avfilter_unref_buffer(movie->picref);
> 
> some of these functions should get null pointer checks so that the callers
> dont have to
> 
> [...]
> > +    if (!movie->picref)
> > +        movie->picref = avfilter_get_video_buffer(outlink,
> > +                                                  AV_PERM_WRITE | AV_PERM_PRESERVE | AV_PERM_REUSE2,
> > +                                                  outlink->w, outlink->h);
> > +
> > +    while (av_read_frame(movie->format_ctx, &packet) >= 0) {
> > +        // Is this a packet from the video stream?
> > +        if (packet.stream_index == movie->video_stream) {
> > +            // Decode video frame
> > +            avcodec_decode_video2(movie->codec_ctx, movie->frame, &frame_finished, &packet);
> > +
> > +            // Did we get a video frame?
> > +            if (frame_finished) {
> > +                av_image_copy(movie->picref->data, movie->picref->linesize,
> > +                              movie->frame ->data, movie->frame ->linesize,
> > +                              movie->picref->format, outlink->w, outlink->h);
> > +
> > +                movie->picref->pts = packet.pts;
> > +                movie->picref->pos = packet.pos;
> > +                movie->picref->video->pixel_aspect = movie->codec_ctx->sample_aspect_ratio;
> > +                movie->picref->video->interlaced = movie->frame->interlaced_frame;
> > +                movie->picref->video->top_field_first = movie->frame->top_field_first;
> > +
> > +#ifdef DEBUG
> > +                av_log(outlink->src, AV_LOG_DEBUG,
> > +                       "movie_get_frame(): file:'%s' pkt.pts:%"PRId64" t:%lf pts:%"PRId64"\n",
> > +                       movie->file_name, packet.pts,
> > +                       (double)packet.pts * av_q2d(movie->format_ctx->streams[movie->video_stream]->time_base),
> > +                       movie->picref->pts);
> > +#endif
> > +
> > +                // We got it. Free the packet since we are returning
> > +                av_free_packet(&packet);
> > +
> > +                return 0;
> > +            }
> > +        }
> > +        // Free the packet that was allocated by av_read_frame
> > +        av_free_packet(&packet);
> > +    }
> 
> There are 2 ways to implement this
> 1. as you do get a frame from the next filter and draw into this (this is a bit
> hard)
> 2. make a AVFilterBufferRef out of the returned picture from the decoder
>    you just recently wrote a function doing this, so it should be trivial
> 
> but taking a frame from the next filter and then forcing a copy as done is
> really the wrong way and also more complex than 2. above

Fixed by using avfilter_get_video_buffer_ref_from_arrays().
-- 
FFmpeg = Foolish & Fundamental Magnificient Pure Efficient Gangster



More information about the ffmpeg-devel mailing list