1 // Copyright (C) 2010 Dirk Vanden Boer <dirk.vdb@gmail.com>
2 //
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation; either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
17 #include "videothumbnailerc.h"
18 #include "videothumbnailer.h"
19 #include "filmstripfilter.h"
20
21 #include <vector>
22 #include <stdexcept>
23
24 using namespace ffmpegthumbnailer;
25
26 struct thumbnailer_data
27 {
28 VideoThumbnailer thumbnailer;
29 FilmStripFilter filter;
30 thumbnailer_log_callback log_cb = nullptr;
31 };
32
trace_message(video_thumbnailer * thumbnailer,ThumbnailerLogLevel lvl,const char * message)33 static void trace_message(video_thumbnailer* thumbnailer, ThumbnailerLogLevel lvl, const char* message)
34 {
35 if (thumbnailer->tdata->log_cb)
36 {
37 thumbnailer->tdata->log_cb(lvl, message);
38 }
39 }
40
video_thumbnailer_create(void)41 extern "C" video_thumbnailer* video_thumbnailer_create(void)
42 {
43 video_thumbnailer* thumbnailer = new video_thumbnailer_struct();
44
45 thumbnailer->thumbnail_size = 128;
46 thumbnailer->seek_percentage = 10;
47 thumbnailer->seek_time = nullptr;
48 thumbnailer->overlay_film_strip = 0;
49 thumbnailer->workaround_bugs = 0;
50 thumbnailer->thumbnail_image_quality = 8;
51 thumbnailer->thumbnail_image_type = Png;
52 thumbnailer->maintain_aspect_ratio = 1;
53 thumbnailer->prefer_embedded_metadata = 0;
54 thumbnailer->av_format_context = nullptr;
55 thumbnailer->tdata = new thumbnailer_data();
56
57 return thumbnailer;
58 }
59
video_thumbnailer_destroy(video_thumbnailer * thumbnailer)60 extern "C" void video_thumbnailer_destroy(video_thumbnailer* thumbnailer)
61 {
62 delete thumbnailer->tdata;
63 delete thumbnailer;
64 }
65
video_thumbnailer_create_image_data(void)66 extern "C" image_data* video_thumbnailer_create_image_data(void)
67 {
68 image_data* data = new image_data();
69
70 data->image_data_ptr = 0;
71 data->image_data_size = 0;
72 data->image_data_width = 0;
73 data->image_data_height = 0;
74 data->internal_data = new std::vector<uint8_t>();
75
76 return data;
77 }
78
video_thumbnailer_destroy_image_data(image_data * data)79 extern "C" void video_thumbnailer_destroy_image_data(image_data* data)
80 {
81 data->image_data_ptr = 0;
82 data->image_data_size = 0;
83 data->image_data_width = 0;
84 data->image_data_height = 0;
85
86 std::vector<uint8_t>* dataVector = reinterpret_cast<std::vector<uint8_t>* >(data->internal_data);
87 delete dataVector;
88 data->internal_data = 0;
89
90 delete data;
91 }
92
setProperties(video_thumbnailer * thumbnailer)93 static void setProperties(video_thumbnailer* thumbnailer)
94 {
95 auto& videoThumbnailer = thumbnailer->tdata->thumbnailer;
96
97 if (thumbnailer->thumbnail_size >= 0)
98 {
99 videoThumbnailer.setThumbnailSize(thumbnailer->thumbnail_size);
100 }
101
102 videoThumbnailer.setWorkAroundIssues(thumbnailer->workaround_bugs != 0);
103 videoThumbnailer.setImageQuality(thumbnailer->thumbnail_image_quality);
104 videoThumbnailer.setMaintainAspectRatio(thumbnailer->maintain_aspect_ratio != 0);
105 videoThumbnailer.setPreferEmbeddedMetadata(thumbnailer->prefer_embedded_metadata != 0);
106
107 if (thumbnailer->overlay_film_strip)
108 {
109 videoThumbnailer.removeFilter(&thumbnailer->tdata->filter);
110 videoThumbnailer.addFilter(&thumbnailer->tdata->filter);
111 }
112
113 if (thumbnailer->seek_time != nullptr)
114 {
115 videoThumbnailer.setSeekTime(thumbnailer->seek_time);
116 }
117 else
118 {
119 videoThumbnailer.setSeekPercentage(thumbnailer->seek_percentage);
120 }
121 }
122
video_thumbnailer_generate_thumbnail_to_buffer(video_thumbnailer * thumbnailer,const char * movie_filename,image_data * generated_image_data)123 extern "C" int video_thumbnailer_generate_thumbnail_to_buffer(video_thumbnailer* thumbnailer, const char* movie_filename, image_data* generated_image_data)
124 {
125 try
126 {
127 auto dataVector = reinterpret_cast<std::vector<uint8_t>*>(generated_image_data->internal_data);
128 auto& videoThumbnailer = thumbnailer->tdata->thumbnailer;
129 setProperties(thumbnailer);
130 auto info = videoThumbnailer.generateThumbnail(movie_filename, thumbnailer->thumbnail_image_type, *dataVector, thumbnailer->av_format_context);
131 generated_image_data->image_data_ptr = &dataVector->front();
132 generated_image_data->image_data_size = static_cast<int>(dataVector->size());
133 generated_image_data->image_data_width = info.width;
134 generated_image_data->image_data_height = info.height;
135 generated_image_data->image_data_source = info.source;
136 }
137 catch (const std::exception& e)
138 {
139 trace_message(thumbnailer, ThumbnailerLogLevelError, e.what());
140 return -1;
141 }
142
143 return 0;
144 }
145
video_thumbnailer_generate_thumbnail_to_file(video_thumbnailer * thumbnailer,const char * movie_filename,const char * output_fileName)146 extern "C" int video_thumbnailer_generate_thumbnail_to_file(video_thumbnailer* thumbnailer, const char* movie_filename, const char* output_fileName)
147 {
148 try
149 {
150 auto& videoThumbnailer = thumbnailer->tdata->thumbnailer;
151 setProperties(thumbnailer);
152 videoThumbnailer.generateThumbnail(movie_filename, thumbnailer->thumbnail_image_type, output_fileName, thumbnailer->av_format_context);
153 }
154 catch (const std::exception& e)
155 {
156 trace_message(thumbnailer, ThumbnailerLogLevelError, e.what());
157 return -1;
158 }
159
160 return 0;
161 }
162
video_thumbnailer_set_log_callback(video_thumbnailer * thumbnailer,thumbnailer_log_callback cb)163 extern "C" void video_thumbnailer_set_log_callback(video_thumbnailer* thumbnailer, thumbnailer_log_callback cb)
164 {
165 thumbnailer->tdata->log_cb = cb;
166 auto& videoThumbnailer = thumbnailer->tdata->thumbnailer;
167
168 if (!cb)
169 {
170 videoThumbnailer.setLogCallback(nullptr);
171 }
172 else
173 {
174 videoThumbnailer.setLogCallback([=] (ThumbnailerLogLevel lvl, const std::string& msg) {
175 cb(lvl, msg.c_str());
176 });
177 }
178 }
179
video_thumbnailer_set_size(video_thumbnailer * thumbnailer,int width,int height)180 extern "C" int video_thumbnailer_set_size(video_thumbnailer* thumbnailer, int width, int height)
181 {
182 auto& videoThumbnailer = thumbnailer->tdata->thumbnailer;
183
184 try
185 {
186 thumbnailer->thumbnail_size = -1;
187 videoThumbnailer.setThumbnailSize(width, height);
188 return 0;
189 }
190 catch (const std::exception& e)
191 {
192 trace_message(thumbnailer, ThumbnailerLogLevelError, e.what());
193 return -1;
194 }
195 }
196