diff options
| author | Carl Hetherington <cth@carlh.net> | 2012-12-16 16:26:37 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2012-12-16 16:26:37 +0000 |
| commit | aabc7a911b874d8e5e0929c7c031d06029fe96b5 (patch) | |
| tree | 2b32b7908e251699e52829022caa44c5b4419467 /src | |
| parent | 1fe3f08c50ba230c2eb2506d51287878679bdcb7 (diff) | |
Various hacks to subtitles etc.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/ffmpeg_decoder.cc | 16 | ||||
| -rw-r--r-- | src/lib/image.cc | 33 | ||||
| -rw-r--r-- | src/lib/image.h | 20 | ||||
| -rw-r--r-- | src/lib/video_decoder.cc | 2 | ||||
| -rw-r--r-- | src/wx/film_viewer.cc | 88 | ||||
| -rw-r--r-- | src/wx/film_viewer.h | 10 |
6 files changed, 137 insertions, 32 deletions
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 136843190..52848d3fc 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -79,6 +79,10 @@ FFmpegDecoder::FFmpegDecoder (shared_ptr<Film> f, shared_ptr<const DecodeOptions setup_subtitle (); _film_connection = f->Changed.connect (bind (&FFmpegDecoder::film_changed, this, _1)); + + if (!o->video_sync) { + _first_video = 0; + } } FFmpegDecoder::~FFmpegDecoder () @@ -254,7 +258,7 @@ FFmpegDecoder::pass () avcodec_get_frame_defaults (_frame); shared_ptr<FFmpegAudioStream> ffa = dynamic_pointer_cast<FFmpegAudioStream> (_audio_stream); - + if (_packet.stream_index == _video_stream) { int frame_finished; @@ -516,6 +520,7 @@ FFmpegDecoder::set_subtitle_stream (shared_ptr<SubtitleStream> s) { VideoDecoder::set_subtitle_stream (s); setup_subtitle (); + OutputChanged (); } void @@ -551,9 +556,14 @@ FFmpegDecoder::filter_and_emit_video (AVFrame* frame) bool FFmpegDecoder::seek (SourceFrame f) { - int64_t const t = static_cast<int64_t>(f) / (av_q2d (_format_context->streams[_video_stream]->time_base) * frames_per_second()); - int const r = av_seek_frame (_format_context, _video_stream, t, 0); + int64_t const vt = static_cast<int64_t>(f) / (av_q2d (_format_context->streams[_video_stream]->time_base) * frames_per_second()); + int const r = av_seek_frame (_format_context, _video_stream, vt, 0); + avcodec_flush_buffers (_video_codec_context); + if (_subtitle_codec_context) { + avcodec_flush_buffers (_subtitle_codec_context); + } + return r < 0; } diff --git a/src/lib/image.cc b/src/lib/image.cc index 748e9ae4b..2e4c18323 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -228,7 +228,7 @@ Image::make_black () } void -Image::alpha_blend (shared_ptr<Image> other, Position position) +Image::alpha_blend (shared_ptr<const Image> other, Position position) { /* Only implemented for RGBA onto RGB24 so far */ assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGBA); @@ -376,7 +376,7 @@ AlignedImage::AlignedImage (AVPixelFormat f, Size s) } -AlignedImage::AlignedImage (shared_ptr<Image> im) +AlignedImage::AlignedImage (shared_ptr<const Image> im) : SimpleImage (im->pixel_format(), im->size(), boost::bind (stride_round_up, _1, _2, 32)) { assert (components() == im->components()); @@ -402,7 +402,7 @@ CompactImage::CompactImage (AVPixelFormat f, Size s) } -CompactImage::CompactImage (shared_ptr<Image> im) +CompactImage::CompactImage (shared_ptr<const Image> im) : SimpleImage (im->pixel_format(), im->size(), boost::bind (stride_round_up, _1, _2, 1)) { assert (components() == im->components()); @@ -459,3 +459,30 @@ FilterBufferImage::size () const return Size (_buffer->video->w, _buffer->video->h); } +RGBPlusAlphaImage::RGBPlusAlphaImage (shared_ptr<const Image> im) + : SimpleImage (im->pixel_format(), im->size(), boost::bind (stride_round_up, _1, _2, 1)) +{ + assert (im->pixel_format() == PIX_FMT_RGBA); + + _alpha = (uint8_t *) av_malloc (im->size().width * im->size().height); + + uint8_t* in = im->data()[0]; + uint8_t* out = data()[0]; + uint8_t* out_alpha = _alpha; + for (int y = 0; y < im->size().height; ++y) { + uint8_t* in_r = in; + for (int x = 0; x < im->size().width; ++x) { + *out++ = *in_r++; + *out++ = *in_r++; + *out++ = *in_r++; + *out_alpha++ = *in_r++; + } + + in += im->stride()[0]; + } +} + +RGBPlusAlphaImage::~RGBPlusAlphaImage () +{ + av_free (_alpha); +} diff --git a/src/lib/image.h b/src/lib/image.h index 7c118f338..0cd38da11 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -72,7 +72,7 @@ public: boost::shared_ptr<Image> scale_and_convert_to_rgb (Size, int, Scaler const *) const; boost::shared_ptr<Image> scale (Size, Scaler const *) const; boost::shared_ptr<Image> post_process (std::string) const; - void alpha_blend (boost::shared_ptr<Image> image, Position pos); + void alpha_blend (boost::shared_ptr<const Image> image, Position pos); void make_black (); @@ -134,7 +134,7 @@ class AlignedImage : public SimpleImage { public: AlignedImage (AVPixelFormat, Size); - AlignedImage (boost::shared_ptr<Image>); + AlignedImage (boost::shared_ptr<const Image>); }; /** @class CompactImage @@ -144,7 +144,21 @@ class CompactImage : public SimpleImage { public: CompactImage (AVPixelFormat, Size); - CompactImage (boost::shared_ptr<Image>); + CompactImage (boost::shared_ptr<const Image>); +}; + +class RGBPlusAlphaImage : public SimpleImage +{ +public: + RGBPlusAlphaImage (boost::shared_ptr<const Image>); + ~RGBPlusAlphaImage (); + + uint8_t* alpha () const { + return _alpha; + } + +private: + uint8_t* _alpha; }; #endif diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc index d3b441fbf..cb55b4d18 100644 --- a/src/lib/video_decoder.cc +++ b/src/lib/video_decoder.cc @@ -44,7 +44,7 @@ void VideoDecoder::emit_video (shared_ptr<Image> image, SourceFrame f) { shared_ptr<Subtitle> sub; - if (_timed_subtitle && _timed_subtitle->displayed_at (double (video_frame()) / _film->frames_per_second())) { + if (_timed_subtitle && _timed_subtitle->displayed_at (f / _film->frames_per_second())) { sub = _timed_subtitle->subtitle (); } diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 8312fa5e5..dd0159ff4 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -86,12 +86,22 @@ FilmViewer::film_changed (Film::Property p) { shared_ptr<DecodeOptions> o (new DecodeOptions); o->decode_audio = false; + o->decode_subtitles = true; o->video_sync = false; _decoders = decoder_factory (_film, o, 0); _decoders.video->Video.connect (bind (&FilmViewer::process_video, this, _1, _2)); _decoders.video->OutputChanged.connect (boost::bind (&FilmViewer::decoder_changed, this)); + _decoders.video->set_subtitle_stream (_film->subtitle_stream()); break; } + case Film::WITH_SUBTITLES: + case Film::SUBTITLE_OFFSET: + case Film::SUBTITLE_SCALE: + update_from_raw (); + break; + case Film::SUBTITLE_STREAM: + _decoders.video->set_subtitle_stream (_film->subtitle_stream ()); + break; default: break; } @@ -115,6 +125,10 @@ FilmViewer::set_film (shared_ptr<Film> f) film_changed (Film::CONTENT); film_changed (Film::CROP); film_changed (Film::FORMAT); + film_changed (Film::WITH_SUBTITLES); + film_changed (Film::SUBTITLE_OFFSET); + film_changed (Film::SUBTITLE_SCALE); + film_changed (Film::SUBTITLE_STREAM); } void @@ -129,10 +143,7 @@ FilmViewer::timer (wxTimerEvent& ev) _panel->Refresh (); _panel->Update (); - shared_ptr<Image> last = _display; - while (last == _display) { - _decoders.video->pass (); - } + get_frame (); if (_film->length()) { int const new_slider_position = 4096 * _decoders.video->last_source_frame() / _film->length().get(); @@ -147,13 +158,19 @@ void FilmViewer::paint_panel (wxPaintEvent& ev) { wxPaintDC dc (_panel); - if (!_display) { + if (!_display_frame) { return; } - wxImage i (_out_width, _out_height, _display->data()[0], true); - wxBitmap b (i); - dc.DrawBitmap (b, 0, 0); + wxImage frame (_out_width, _out_height, _display_frame->data()[0], true); + wxBitmap frame_bitmap (frame); + dc.DrawBitmap (frame_bitmap, 0, 0); + + if (_film->with_subtitles() && _display_sub) { + wxImage sub (_display_sub->size().width, _display_sub->size().height, _display_sub->data()[0], _display_sub->alpha(), true); + wxBitmap sub_bitmap (sub); + dc.DrawBitmap (sub_bitmap, _display_sub_position.x, _display_sub_position.y); + } } @@ -171,11 +188,8 @@ FilmViewer::seek_and_update (SourceFrame f) if (_decoders.video->seek (f)) { return; } - - shared_ptr<Image> last = _display; - while (last == _display) { - _decoders.video->pass (); - } + + get_frame (); _panel->Refresh (); _panel->Update (); } @@ -192,19 +206,40 @@ FilmViewer::panel_sized (wxSizeEvent& ev) void FilmViewer::update_from_raw () { - if (!_raw) { + if (!_raw_frame) { return; } - if (_out_width && _out_height) { - _display = _raw->scale_and_convert_to_rgb (Size (_out_width, _out_height), 0, Scaler::from_id ("bicubic")); - } + raw_to_display (); _panel->Refresh (); _panel->Update (); } void +FilmViewer::raw_to_display () +{ + if (!_out_width || !_out_height) { + return; + } + + _display_frame = _raw_frame->scale_and_convert_to_rgb (Size (_out_width, _out_height), 0, _film->scaler()); + + if (_raw_sub) { + Rect tx = subtitle_transformed_area ( + float (_out_width) / _film->size().width, + float (_out_height) / _film->size().height, + _raw_sub->area(), _film->subtitle_offset(), _film->subtitle_scale() + ); + + _display_sub.reset (new RGBPlusAlphaImage (_raw_sub->image()->scale (tx.size(), _film->scaler ()))); + _display_sub_position = tx.position(); + } else { + _display_sub.reset (); + } +} + +void FilmViewer::calculate_sizes () { float const panel_ratio = static_cast<float> (_panel_width) / _panel_height; @@ -239,8 +274,21 @@ FilmViewer::check_play_state () void FilmViewer::process_video (shared_ptr<Image> image, shared_ptr<Subtitle> sub) { - _raw = image; - if (_out_width && _out_height) { - _display = _raw->scale_and_convert_to_rgb (Size (_out_width, _out_height), 0, Scaler::from_id ("bicubic")); + _raw_frame = image; + _raw_sub = sub; + + raw_to_display (); +} + +void +FilmViewer::get_frame () +{ + if (!_out_width || !_out_height) { + return; + } + + shared_ptr<Image> last = _display_frame; + while (last == _display_frame) { + _decoders.video->pass (); } } diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 8194d0206..2d0e17fa2 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -28,6 +28,7 @@ class wxToggleButton; class FFmpegPlayer; class Image; +class RGBPlusAlphaImage; class Subtitle; /** @class FilmViewer @@ -53,6 +54,8 @@ private: void update_from_raw (); void decoder_changed (); void seek_and_update (SourceFrame); + void raw_to_display (); + void get_frame (); boost::shared_ptr<Film> _film; @@ -62,8 +65,11 @@ private: wxTimer _timer; Decoders _decoders; - boost::shared_ptr<Image> _raw; - boost::shared_ptr<Image> _display; + boost::shared_ptr<Image> _raw_frame; + boost::shared_ptr<Subtitle> _raw_sub; + boost::shared_ptr<Image> _display_frame; + boost::shared_ptr<RGBPlusAlphaImage> _display_sub; + Position _display_sub_position; int _out_width; int _out_height; |
