af548b7944529100d2d57e3ec925e85f6255f6e4
[dcpomatic.git] / src / lib / examine_ffmpeg_subtitles_job.cc
1 /*
2     Copyright (C) 2019 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21 #include "examine_ffmpeg_subtitles_job.h"
22 #include "ffmpeg_content.h"
23 #include "ffmpeg_subtitle_stream.h"
24 #include "text_content.h"
25 #include "cross.h"
26 extern "C" {
27 #include <libavcodec/avcodec.h>
28 #include <libavformat/avformat.h>
29 }
30 #include <iostream>
31
32 #include "i18n.h"
33
34 using std::string;
35 using std::cout;
36 using boost::shared_ptr;
37
38 ExamineFFmpegSubtitlesJob::ExamineFFmpegSubtitlesJob (shared_ptr<const Film> film, shared_ptr<FFmpegContent> c)
39         : Job (film)
40         , FFmpeg (c)
41         , _content (c)
42 {
43
44 }
45
46 string
47 ExamineFFmpegSubtitlesJob::name () const
48 {
49         return _("Examining subtitles");
50 }
51
52 string
53 ExamineFFmpegSubtitlesJob::json_name () const
54 {
55         return N_("examine_subtitles");
56 }
57
58 void
59 ExamineFFmpegSubtitlesJob::run ()
60 {
61         int64_t const len = _file_group.length ();
62         while (true) {
63                 int r = av_read_frame (_format_context, &_packet);
64                 if (r < 0) {
65                         break;
66                 }
67
68                 if (len > 0) {
69                         set_progress (float(_format_context->pb->pos) / len);
70                 } else {
71                         set_progress_unknown ();
72                 }
73
74                 if (_content->subtitle_stream() && _content->subtitle_stream()->uses_index(_format_context, _packet.stream_index) && _content->only_text()->use()) {
75                         int got_subtitle;
76                         AVSubtitle sub;
77                         if (avcodec_decode_subtitle2(subtitle_codec_context(), &sub, &got_subtitle, &_packet) >= 0 && got_subtitle) {
78                                 for (unsigned int i = 0; i < sub.num_rects; ++i) {
79                                         AVSubtitleRect const * rect = sub.rects[i];
80                                         if (rect->type == SUBTITLE_BITMAP) {
81 #ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT
82                                                 /* sub_p looks up into a BGRA palette which is here
83                                                    (i.e. first byte B, second G, third R, fourth A)
84                                                 */
85                                                 uint32_t const * palette = (uint32_t *) rect->pict.data[1];
86 #else
87                                                 /* sub_p looks up into a BGRA palette which is here
88                                                    (i.e. first byte B, second G, third R, fourth A)
89                                                 */
90                                                 uint32_t const * palette = (uint32_t *) rect->data[1];
91 #endif
92                                                 for (int j = 0; j < rect->nb_colors; ++j) {
93                                                         RGBA c ((palette[j] & 0xff0000) >> 16, (palette[j] & 0xff00) >> 8, palette[j] & 0xff, (palette[j] & 0xff000000) >> 24);
94                                                         _content->subtitle_stream()->set_colour (c, c);
95                                                 }
96                                         }
97                                 }
98                         }
99                 }
100
101                 av_packet_unref (&_packet);
102         }
103
104         set_progress (1);
105         set_state (FINISHED_OK);
106 }