Use newer format to specify filter graphs; don't filter unless necessary; fix tiny...
authorCarl Hetherington <cth@carlh.net>
Thu, 2 May 2013 21:15:32 +0000 (22:15 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 2 May 2013 21:15:32 +0000 (22:15 +0100)
src/lib/ffmpeg_decoder.cc
src/lib/filter_graph.cc
src/lib/image.cc
src/lib/image.h
test/pixel_formats_test.cc

index 8e09810cb2cc75c3a6109139e0a0db8427f4eb8e..cd68e52941c22d6ead11e959928bc3e80442b9fa 100644 (file)
@@ -500,32 +500,41 @@ FFmpegDecoder::set_subtitle_stream (shared_ptr<SubtitleStream> s)
 void
 FFmpegDecoder::filter_and_emit_video ()
 {
-       boost::mutex::scoped_lock lm (_filter_graphs_mutex);
+       int64_t const bet = av_frame_get_best_effort_timestamp (_frame);
+       if (bet == AV_NOPTS_VALUE) {
+               _film->log()->log ("Dropping frame without PTS");
+               return;
+       }
        
-       shared_ptr<FilterGraph> graph;
-
-       list<shared_ptr<FilterGraph> >::iterator i = _filter_graphs.begin();
-       while (i != _filter_graphs.end() && !(*i)->can_process (libdcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format)) {
-               ++i;
+       if (_film->crop() == Crop() && _film->filters().empty()) {
+               /* No filter graph needed; just emit */
+               emit_video (shared_ptr<Image> (new FrameImage (_frame, false)), false, bet * av_q2d (_format_context->streams[_video_stream]->time_base));
+               return;
        }
+       
+       shared_ptr<FilterGraph> graph;
 
-       if (i == _filter_graphs.end ()) {
-               graph.reset (new FilterGraph (_film, this, libdcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format));
-               _filter_graphs.push_back (graph);
-               _film->log()->log (String::compose (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format));
-       } else {
-               graph = *i;
+       {
+               boost::mutex::scoped_lock lm (_filter_graphs_mutex);
+               
+               list<shared_ptr<FilterGraph> >::iterator i = _filter_graphs.begin();
+               while (i != _filter_graphs.end() && !(*i)->can_process (libdcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format)) {
+                       ++i;
+               }
+               
+               if (i == _filter_graphs.end ()) {
+                       graph.reset (new FilterGraph (_film, this, libdcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format));
+                       _filter_graphs.push_back (graph);
+                       _film->log()->log (String::compose (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format));
+               } else {
+                       graph = *i;
+               }
        }
 
        list<shared_ptr<Image> > images = graph->process (_frame);
 
        for (list<shared_ptr<Image> >::iterator i = images.begin(); i != images.end(); ++i) {
-               int64_t const bet = av_frame_get_best_effort_timestamp (_frame);
-               if (bet != AV_NOPTS_VALUE) {
-                       emit_video (*i, false, bet * av_q2d (_format_context->streams[_video_stream]->time_base));
-               } else {
-                       _film->log()->log ("Dropping frame without PTS");
-               }
+               emit_video (*i, false, bet * av_q2d (_format_context->streams[_video_stream]->time_base));
        }
 }
 
index f0c49b37c07e6a12c0969ff61f2e7b3da0eb6bc2..2624bc4d7c0354a9bf46a48348a6c75d38dd5872 100644 (file)
@@ -79,17 +79,14 @@ FilterGraph::FilterGraph (shared_ptr<Film> film, FFmpegDecoder* decoder, libdcp:
        }
 
        stringstream a;
-       a << _size.width << N_(":")
-         << _size.height << N_(":")
-         << _pixel_format << N_(":")
-         << decoder->time_base_numerator() << N_(":")
-         << decoder->time_base_denominator() << N_(":")
-         << decoder->sample_aspect_ratio_numerator() << N_(":")
-         << decoder->sample_aspect_ratio_denominator();
+       a << "video_size=" << _size.width << "x" << _size.height << ":"
+         << "pix_fmt=" << _pixel_format << ":"
+         << "time_base=" << decoder->time_base_numerator() << "/" << decoder->time_base_denominator() << ":"
+         << "pixel_aspect=" << decoder->sample_aspect_ratio_numerator() << "/" << decoder->sample_aspect_ratio_denominator();
 
        int r;
 
-       if ((r = avfilter_graph_create_filter (&_buffer_src_context, buffer_src, N_("in"), a.str().c_str(), 0, graph)) < 0) {
+       if ((r = avfilter_graph_create_filter (&_buffer_src_context, buffer_src, "in", a.str().c_str(), 0, graph)) < 0) {
                throw DecodeError (N_("could not create buffer source"));
        }
 
@@ -103,6 +100,8 @@ FilterGraph::FilterGraph (shared_ptr<Film> film, FFmpegDecoder* decoder, libdcp:
                throw DecodeError (N_("could not create buffer sink."));
        }
 
+       av_free (sink_params);
+
        AVFilterInOut* outputs = avfilter_inout_alloc ();
        outputs->name = av_strdup(N_("in"));
        outputs->filter_ctx = _buffer_src_context;
@@ -133,7 +132,7 @@ list<shared_ptr<Image> >
 FilterGraph::process (AVFrame* frame)
 {
        list<shared_ptr<Image> > images;
-       
+
        if (av_buffersrc_write_frame (_buffer_src_context, frame) < 0) {
                throw DecodeError (N_("could not push buffer into filter chain."));
        }
@@ -146,7 +145,7 @@ FilterGraph::process (AVFrame* frame)
                }
 
                /* This takes ownership of the AVFrame */
-               images.push_back (shared_ptr<Image> (new FrameImage (frame)));
+               images.push_back (shared_ptr<Image> (new FrameImage (frame, true)));
        }
        
        return images;
index b97291585afa9df994a89cce3640aaaba44a1362..1768be924fe806d6b6c1247cf38f9086572c29aa 100644 (file)
@@ -576,9 +576,10 @@ SimpleImage::aligned () const
        return _aligned;
 }
 
-FrameImage::FrameImage (AVFrame* frame)
+FrameImage::FrameImage (AVFrame* frame, bool own)
        : Image (static_cast<AVPixelFormat> (frame->format))
        , _frame (frame)
+       , _own (own)
 {
        _line_size = (int *) av_malloc (4 * sizeof (int));
        _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
@@ -590,7 +591,10 @@ FrameImage::FrameImage (AVFrame* frame)
 
 FrameImage::~FrameImage ()
 {
-       av_frame_free (&_frame);
+       if (_own) {
+               av_frame_free (&_frame);
+       }
+       
        av_free (_line_size);
 }
 
index 39d84fcd4c35cee34ff6ba947218d3827cde493b..16fbd28c24b93c4064045368cf87e171444c16c9 100644 (file)
@@ -106,7 +106,7 @@ private:
 class FrameImage : public Image
 {
 public:
-       FrameImage (AVFrame *);
+       FrameImage (AVFrame *, bool);
        ~FrameImage ();
 
        uint8_t ** data () const;
@@ -121,6 +121,7 @@ private:
        FrameImage& operator= (FrameImage const &);
        
        AVFrame* _frame;
+       bool _own;
        int* _line_size;
 };
 
index e0f6c4373a4f783f5f90f04a3319fff7eaa1246d..e8ad725ff5f85b83cbfa7152eefabecd97051b51 100644 (file)
@@ -65,7 +65,7 @@ BOOST_AUTO_TEST_CASE (pixel_formats_test)
                f->width = 640;
                f->height = 480;
                f->format = static_cast<int> (i->format);
-               FrameImage t (f);
+               FrameImage t (f, true);
                BOOST_CHECK_EQUAL(t.components(), i->components);
                BOOST_CHECK_EQUAL(t.lines(0), i->lines[0]);
                BOOST_CHECK_EQUAL(t.lines(1), i->lines[1]);