aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/thumbnailffmpeg_extractor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/thumbnailffmpeg_extractor.c')
-rw-r--r--src/plugins/thumbnailffmpeg_extractor.c705
1 files changed, 353 insertions, 352 deletions
diff --git a/src/plugins/thumbnailffmpeg_extractor.c b/src/plugins/thumbnailffmpeg_extractor.c
index 72af79f..72f0137 100644
--- a/src/plugins/thumbnailffmpeg_extractor.c
+++ b/src/plugins/thumbnailffmpeg_extractor.c
@@ -97,7 +97,7 @@
97/** 97/**
98 * Maximum size in bytes for the thumbnail. 98 * Maximum size in bytes for the thumbnail.
99 */ 99 */
100#define MAX_THUMB_BYTES (100*1024) 100#define MAX_THUMB_BYTES (100 * 1024)
101 101
102/** 102/**
103 * Number of bytes to feed to libav in one go. 103 * Number of bytes to feed to libav in one go.
@@ -135,8 +135,8 @@ static magic_t magic;
135 */ 135 */
136static int 136static int
137read_cb (void *opaque, 137read_cb (void *opaque,
138 uint8_t *buf, 138 uint8_t *buf,
139 int buf_size) 139 int buf_size)
140{ 140{
141 struct EXTRACTOR_ExtractContext *ec = opaque; 141 struct EXTRACTOR_ExtractContext *ec = opaque;
142 void *data; 142 void *data;
@@ -160,8 +160,8 @@ read_cb (void *opaque,
160 */ 160 */
161static int64_t 161static int64_t
162seek_cb (void *opaque, 162seek_cb (void *opaque,
163 int64_t offset, 163 int64_t offset,
164 int whence) 164 int whence)
165{ 165{
166 struct EXTRACTOR_ExtractContext *ec = opaque; 166 struct EXTRACTOR_ExtractContext *ec = opaque;
167 167
@@ -187,12 +187,12 @@ seek_cb (void *opaque,
187 */ 187 */
188static size_t 188static size_t
189create_thumbnail (AVCodecContext *pCodecCtx, int src_width, int src_height, 189create_thumbnail (AVCodecContext *pCodecCtx, int src_width, int src_height,
190 int src_stride[], 190 int src_stride[],
191 enum AVPixelFormat src_pixfmt, 191 enum AVPixelFormat src_pixfmt,
192 const uint8_t * const src_data[], 192 const uint8_t *const src_data[],
193 int dst_width, int dst_height, 193 int dst_width, int dst_height,
194 uint8_t **output_data, 194 uint8_t **output_data,
195 size_t output_max_size) 195 size_t output_max_size)
196{ 196{
197 AVCodecContext *encoder_codec_ctx; 197 AVCodecContext *encoder_codec_ctx;
198 AVDictionary *opts; 198 AVDictionary *opts;
@@ -205,73 +205,73 @@ create_thumbnail (AVCodecContext *pCodecCtx, int src_width, int src_height,
205 int err; 205 int err;
206 206
207 AVPacket pkt; 207 AVPacket pkt;
208 av_init_packet(&pkt); 208 av_init_packet (&pkt);
209 pkt.data = NULL; 209 pkt.data = NULL;
210 pkt.size = 0; 210 pkt.size = 0;
211 int gotPacket; 211 int gotPacket;
212#if USE_JPEG 212#if USE_JPEG
213 #if LIBAVCODEC_BUILD >= AV_VERSION_INT(54,25,0) 213 #if LIBAVCODEC_BUILD >= AV_VERSION_INT (54,25,0)
214 if (NULL == (encoder_codec = avcodec_find_encoder ( AV_CODEC_ID_MJPEG ))) 214 if (NULL == (encoder_codec = avcodec_find_encoder (AV_CODEC_ID_MJPEG)))
215 #else 215 #else
216 if (NULL == (encoder_codec = avcodec_find_encoder ( CODEC_ID_MJPEG ))) 216 if (NULL == (encoder_codec = avcodec_find_encoder (CODEC_ID_MJPEG)))
217 #endif 217 #endif
218 #else 218 #else
219 if (NULL == (encoder_codec = avcodec_find_encoder_by_name ("png"))) 219 if (NULL == (encoder_codec = avcodec_find_encoder_by_name ("png")))
220 #endif 220 #endif
221 { 221 {
222#if DEBUG 222#if DEBUG
223 fprintf (stderr, 223 fprintf (stderr,
224 "Couldn't find a encoder\n"); 224 "Couldn't find a encoder\n");
225#endif 225#endif
226 return 0; 226 return 0;
227 } 227 }
228 228
229 /* NOTE: the scaler will be used even if the src and dst image dimensions 229 /* NOTE: the scaler will be used even if the src and dst image dimensions
230 * match, because the scaler will also perform colour space conversion */ 230 * match, because the scaler will also perform colour space conversion */
231 if (NULL == 231 if (NULL ==
232 (scaler_ctx = 232 (scaler_ctx =
233 sws_getContext (src_width, src_height, src_pixfmt, 233 sws_getContext (src_width, src_height, src_pixfmt,
234 dst_width, dst_height, 234 dst_width, dst_height,
235 PIX_OUTPUT_FORMAT, 235 PIX_OUTPUT_FORMAT,
236 SWS_BILINEAR, NULL, NULL, NULL))) 236 SWS_BILINEAR, NULL, NULL, NULL)))
237 { 237 {
238#if DEBUG 238#if DEBUG
239 fprintf (stderr, 239 fprintf (stderr,
240 "Failed to get a scaler context\n"); 240 "Failed to get a scaler context\n");
241#endif 241#endif
242 return 0; 242 return 0;
243 } 243 }
244 244
245#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) 245#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (55,28,1)
246 dst_frame = av_frame_alloc (); 246 dst_frame = av_frame_alloc ();
247#else 247#else
248 dst_frame = avcodec_alloc_frame(); 248 dst_frame = avcodec_alloc_frame ();
249#endif 249#endif
250 if (NULL == dst_frame) 250 if (NULL == dst_frame)
251 { 251 {
252#if DEBUG 252#if DEBUG
253 fprintf (stderr, 253 fprintf (stderr,
254 "Failed to allocate the destination image frame\n"); 254 "Failed to allocate the destination image frame\n");
255#endif 255#endif
256 sws_freeContext (scaler_ctx); 256 sws_freeContext (scaler_ctx);
257 return 0; 257 return 0;
258 } 258 }
259 if (NULL == (dst_buffer = 259 if (NULL == (dst_buffer =
260 av_malloc (avpicture_get_size (PIX_OUTPUT_FORMAT, 260 av_malloc (avpicture_get_size (PIX_OUTPUT_FORMAT,
261 dst_width, dst_height)))) 261 dst_width, dst_height))))
262 { 262 {
263#if DEBUG 263#if DEBUG
264 fprintf (stderr, 264 fprintf (stderr,
265 "Failed to allocate the destination image buffer\n"); 265 "Failed to allocate the destination image buffer\n");
266#endif 266#endif
267#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) 267#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (55,28,1)
268 av_frame_free (&dst_frame); 268 av_frame_free (&dst_frame);
269#else 269#else
270 avcodec_free_frame (&dst_frame); 270 avcodec_free_frame (&dst_frame);
271#endif 271#endif
272 sws_freeContext (scaler_ctx); 272 sws_freeContext (scaler_ctx);
273 return 0; 273 return 0;
274 } 274 }
275 avpicture_fill ((AVPicture *) dst_frame, dst_buffer, 275 avpicture_fill ((AVPicture *) dst_frame, dst_buffer,
276 PIX_OUTPUT_FORMAT, 276 PIX_OUTPUT_FORMAT,
277 dst_width, dst_height); 277 dst_width, dst_height);
@@ -284,47 +284,47 @@ create_thumbnail (AVCodecContext *pCodecCtx, int src_width, int src_height,
284 284
285 encoder_output_buffer_size = output_max_size; 285 encoder_output_buffer_size = output_max_size;
286 if (NULL == (encoder_output_buffer = av_malloc (encoder_output_buffer_size))) 286 if (NULL == (encoder_output_buffer = av_malloc (encoder_output_buffer_size)))
287 { 287 {
288#if DEBUG 288#if DEBUG
289 fprintf (stderr, 289 fprintf (stderr,
290 "Failed to allocate the encoder output buffer\n"); 290 "Failed to allocate the encoder output buffer\n");
291#endif 291#endif
292 av_free (dst_buffer); 292 av_free (dst_buffer);
293#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) 293#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (55,28,1)
294 av_frame_free (&dst_frame); 294 av_frame_free (&dst_frame);
295#else 295#else
296 avcodec_free_frame (&dst_frame); 296 avcodec_free_frame (&dst_frame);
297#endif 297#endif
298 sws_freeContext (scaler_ctx); 298 sws_freeContext (scaler_ctx);
299 return 0; 299 return 0;
300 } 300 }
301 301
302 if (NULL == (encoder_codec_ctx = avcodec_alloc_context3 (encoder_codec))) 302 if (NULL == (encoder_codec_ctx = avcodec_alloc_context3 (encoder_codec)))
303 { 303 {
304#if DEBUG 304#if DEBUG
305 fprintf (stderr, 305 fprintf (stderr,
306 "Failed to allocate the encoder codec context\n"); 306 "Failed to allocate the encoder codec context\n");
307#endif 307#endif
308 av_free (encoder_output_buffer); 308 av_free (encoder_output_buffer);
309 av_free (dst_buffer); 309 av_free (dst_buffer);
310#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) 310#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (55,28,1)
311 av_frame_free (&dst_frame); 311 av_frame_free (&dst_frame);
312#else 312#else
313 avcodec_free_frame (&dst_frame); 313 avcodec_free_frame (&dst_frame);
314#endif 314#endif
315 sws_freeContext (scaler_ctx); 315 sws_freeContext (scaler_ctx);
316 return 0; 316 return 0;
317 } 317 }
318 encoder_codec_ctx->width = dst_width; 318 encoder_codec_ctx->width = dst_width;
319 encoder_codec_ctx->height = dst_height; 319 encoder_codec_ctx->height = dst_height;
320#if USE_JPEG 320#if USE_JPEG
321 encoder_codec_ctx->bit_rate = pCodecCtx->bit_rate; 321 encoder_codec_ctx->bit_rate = pCodecCtx->bit_rate;
322#if LIBAVCODEC_BUILD >= AV_VERSION_INT(54,25,0) 322#if LIBAVCODEC_BUILD >= AV_VERSION_INT (54,25,0)
323 encoder_codec_ctx->codec_id = AV_CODEC_ID_MJPEG; 323 encoder_codec_ctx->codec_id = AV_CODEC_ID_MJPEG;
324#else 324#else
325 encoder_codec_ctx->codec_id = CODEC_ID_MJPEG; 325 encoder_codec_ctx->codec_id = CODEC_ID_MJPEG;
326#endif 326#endif
327#if LIBAVCODEC_BUILD >= AV_VERSION_INT(53,35,0) 327#if LIBAVCODEC_BUILD >= AV_VERSION_INT (53,35,0)
328 encoder_codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO; 328 encoder_codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
329#else 329#else
330 encoder_codec_ctx->codec_type = CODEC_TYPE_VIDEO; 330 encoder_codec_ctx->codec_type = CODEC_TYPE_VIDEO;
@@ -338,51 +338,52 @@ create_thumbnail (AVCodecContext *pCodecCtx, int src_width, int src_height,
338 338
339 opts = NULL; 339 opts = NULL;
340 if (avcodec_open2 (encoder_codec_ctx, encoder_codec, &opts) < 0) 340 if (avcodec_open2 (encoder_codec_ctx, encoder_codec, &opts) < 0)
341 { 341 {
342#if DEBUG 342#if DEBUG
343 fprintf (stderr, 343 fprintf (stderr,
344 "Failed to open the encoder\n"); 344 "Failed to open the encoder\n");
345#endif 345#endif
346 avcodec_free_context (&encoder_codec_ctx); 346 avcodec_free_context (&encoder_codec_ctx);
347 av_free (encoder_output_buffer); 347 av_free (encoder_output_buffer);
348 av_free (dst_buffer); 348 av_free (dst_buffer);
349#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) 349#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (55,28,1)
350 av_frame_free (&dst_frame); 350 av_frame_free (&dst_frame);
351#else 351#else
352 avcodec_free_frame (&dst_frame); 352 avcodec_free_frame (&dst_frame);
353#endif 353#endif
354 sws_freeContext (scaler_ctx); 354 sws_freeContext (scaler_ctx);
355 return 0; 355 return 0;
356 } 356 }
357
358 357
359 358
360#ifdef USE_JPEG 359#ifdef USE_JPEG
361#if FF_API_MPV_OPT 360#if FF_API_MPV_OPT
362 encoder_codec_ctx->mb_lmin = encoder_codec_ctx->lmin = encoder_codec_ctx->qmin * FF_QP2LAMBDA; 361 encoder_codec_ctx->mb_lmin = encoder_codec_ctx->lmin =
363 encoder_codec_ctx->mb_lmax = encoder_codec_ctx->lmax = encoder_codec_ctx->qmax * FF_QP2LAMBDA; 362 encoder_codec_ctx->qmin * FF_QP2LAMBDA;
363 encoder_codec_ctx->mb_lmax = encoder_codec_ctx->lmax =
364 encoder_codec_ctx->qmax * FF_QP2LAMBDA;
364#else 365#else
365 encoder_codec_ctx->mb_lmin = encoder_codec_ctx->qmin * FF_QP2LAMBDA; 366 encoder_codec_ctx->mb_lmin = encoder_codec_ctx->qmin * FF_QP2LAMBDA;
366 encoder_codec_ctx->mb_lmax = encoder_codec_ctx->qmax * FF_QP2LAMBDA; 367 encoder_codec_ctx->mb_lmax = encoder_codec_ctx->qmax * FF_QP2LAMBDA;
367#endif 368#endif
368 encoder_codec_ctx->flags = AV_CODEC_FLAG_QSCALE; 369 encoder_codec_ctx->flags = AV_CODEC_FLAG_QSCALE;
369 encoder_codec_ctx->global_quality = encoder_codec_ctx->qmin * FF_QP2LAMBDA; 370 encoder_codec_ctx->global_quality = encoder_codec_ctx->qmin * FF_QP2LAMBDA;
370 371
371 dst_frame->pts = 1; 372 dst_frame->pts = 1;
372 dst_frame->quality = encoder_codec_ctx->global_quality; 373 dst_frame->quality = encoder_codec_ctx->global_quality;
373#endif 374#endif
374 375
375#if LIBAVCODEC_BUILD >= AV_VERSION_INT(54,25,0) 376#if LIBAVCODEC_BUILD >= AV_VERSION_INT (54,25,0)
376 err = avcodec_encode_video2 (encoder_codec_ctx, 377 err = avcodec_encode_video2 (encoder_codec_ctx,
377 &pkt, 378 &pkt,
378 dst_frame, &gotPacket); 379 dst_frame, &gotPacket);
379 380
380 if(err < 0) 381 if (err < 0)
381 goto cleanup; 382 goto cleanup;
382 err = pkt.size; 383 err = pkt.size;
383 memcpy(encoder_output_buffer,pkt.data, pkt.size); 384 memcpy (encoder_output_buffer,pkt.data, pkt.size);
384 385
385 av_free_packet(&pkt); 386 av_free_packet (&pkt);
386 387
387 388
388#else 389#else
@@ -396,7 +397,7 @@ cleanup:
396 avcodec_close (encoder_codec_ctx); 397 avcodec_close (encoder_codec_ctx);
397 avcodec_free_context (&encoder_codec_ctx); 398 avcodec_free_context (&encoder_codec_ctx);
398 av_free (dst_buffer); 399 av_free (dst_buffer);
399#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) 400#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (55,28,1)
400 av_frame_free (&dst_frame); 401 av_frame_free (&dst_frame);
401#else 402#else
402 avcodec_free_frame (&dst_frame); 403 avcodec_free_frame (&dst_frame);
@@ -408,7 +409,6 @@ cleanup:
408} 409}
409 410
410 411
411
412/** 412/**
413 * calculate the thumbnail dimensions, taking pixel aspect into account 413 * calculate the thumbnail dimensions, taking pixel aspect into account
414 * 414 *
@@ -421,30 +421,30 @@ cleanup:
421 */ 421 */
422static void 422static void
423calculate_thumbnail_dimensions (int src_width, 423calculate_thumbnail_dimensions (int src_width,
424 int src_height, 424 int src_height,
425 int src_sar_num, 425 int src_sar_num,
426 int src_sar_den, 426 int src_sar_den,
427 int *dst_width, 427 int *dst_width,
428 int *dst_height) 428 int *dst_height)
429{ 429{
430 if ( (src_sar_num <= 0) || (src_sar_den <= 0) ) 430 if ( (src_sar_num <= 0) || (src_sar_den <= 0) )
431 { 431 {
432 src_sar_num = 1; 432 src_sar_num = 1;
433 src_sar_den = 1; 433 src_sar_den = 1;
434 } 434 }
435 if ((src_width * src_sar_num) / src_sar_den > src_height) 435 if ((src_width * src_sar_num) / src_sar_den > src_height)
436 { 436 {
437 *dst_width = MAX_THUMB_DIMENSION; 437 *dst_width = MAX_THUMB_DIMENSION;
438 *dst_height = (*dst_width * src_height) / 438 *dst_height = (*dst_width * src_height)
439 ((src_width * src_sar_num) / src_sar_den); 439 / ((src_width * src_sar_num) / src_sar_den);
440 } 440 }
441 else 441 else
442 { 442 {
443 *dst_height = MAX_THUMB_DIMENSION; 443 *dst_height = MAX_THUMB_DIMENSION;
444 *dst_width = (*dst_height * 444 *dst_width = (*dst_height
445 ((src_width * src_sar_num) / src_sar_den)) / 445 * ((src_width * src_sar_num) / src_sar_den))
446 src_height; 446 / src_height;
447 } 447 }
448 if (*dst_width < 8) 448 if (*dst_width < 8)
449 *dst_width = 8; 449 *dst_width = 8;
450 if (*dst_height < 1) 450 if (*dst_height < 1)
@@ -456,10 +456,11 @@ calculate_thumbnail_dimensions (int src_width,
456#endif 456#endif
457} 457}
458 458
459#if LIBAVCODEC_BUILD >= AV_VERSION_INT(54,25,0) 459
460 #define ENUM_CODEC_ID enum AVCodecID 460#if LIBAVCODEC_BUILD >= AV_VERSION_INT (54,25,0)
461 #define ENUM_CODEC_ID enum AVCodecID
461#else 462#else
462 #define ENUM_CODEC_ID enum CodecID 463 #define ENUM_CODEC_ID enum CodecID
463#endif 464#endif
464 465
465/** 466/**
@@ -487,77 +488,77 @@ extract_image (ENUM_CODEC_ID image_codec_id,
487 unsigned char padded_data[PADDED_BUFFER_SIZE]; 488 unsigned char padded_data[PADDED_BUFFER_SIZE];
488 489
489 if (NULL == (codec = avcodec_find_decoder (image_codec_id))) 490 if (NULL == (codec = avcodec_find_decoder (image_codec_id)))
490 { 491 {
491#if DEBUG 492#if DEBUG
492 fprintf (stderr, 493 fprintf (stderr,
493 "No suitable codec found\n"); 494 "No suitable codec found\n");
494#endif 495#endif
495 return; 496 return;
496 } 497 }
497 if (NULL == (codec_ctx = avcodec_alloc_context3 (codec))) 498 if (NULL == (codec_ctx = avcodec_alloc_context3 (codec)))
498 { 499 {
499#if DEBUG 500#if DEBUG
500 fprintf (stderr, 501 fprintf (stderr,
501 "Failed to allocate codec context\n"); 502 "Failed to allocate codec context\n");
502#endif 503#endif
503 return; 504 return;
504 } 505 }
505 opts = NULL; 506 opts = NULL;
506 if (0 != avcodec_open2 (codec_ctx, codec, &opts)) 507 if (0 != avcodec_open2 (codec_ctx, codec, &opts))
507 { 508 {
508#if DEBUG 509#if DEBUG
509 fprintf (stderr, 510 fprintf (stderr,
510 "Failed to open image codec\n"); 511 "Failed to open image codec\n");
511#endif 512#endif
512 avcodec_free_context (&codec_ctx); 513 avcodec_free_context (&codec_ctx);
513 return; 514 return;
514 } 515 }
515 av_dict_free (&opts); 516 av_dict_free (&opts);
516#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) 517#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (55,28,1)
517 frame = av_frame_alloc (); 518 frame = av_frame_alloc ();
518#else 519#else
519 frame = avcodec_alloc_frame(); 520 frame = avcodec_alloc_frame ();
520#endif 521#endif
521 if (NULL == frame) 522 if (NULL == frame)
522 { 523 {
523#if DEBUG 524#if DEBUG
524 fprintf (stderr, 525 fprintf (stderr,
525 "Failed to allocate frame\n"); 526 "Failed to allocate frame\n");
526#endif 527#endif
527 avcodec_close (codec_ctx); 528 avcodec_close (codec_ctx);
528 avcodec_free_context (&codec_ctx); 529 avcodec_free_context (&codec_ctx);
529 return; 530 return;
530 } 531 }
531 532
532 frame_finished = 0; 533 frame_finished = 0;
533 while (! frame_finished) 534 while (! frame_finished)
534 { 535 {
535 if (0 >= (iret = ec->read (ec->cls, 536 if (0 >= (iret = ec->read (ec->cls,
536 &data, 537 &data,
537 BUFFER_SIZE))) 538 BUFFER_SIZE)))
538 break; 539 break;
539 memcpy (padded_data, data, iret); 540 memcpy (padded_data, data, iret);
540 memset (&padded_data[iret], 0, PADDED_BUFFER_SIZE - iret); 541 memset (&padded_data[iret], 0, PADDED_BUFFER_SIZE - iret);
541 av_init_packet (&avpkt); 542 av_init_packet (&avpkt);
542 avpkt.data = padded_data; 543 avpkt.data = padded_data;
543 avpkt.size = iret; 544 avpkt.size = iret;
544 avcodec_decode_video2 (codec_ctx, frame, &frame_finished, &avpkt); 545 avcodec_decode_video2 (codec_ctx, frame, &frame_finished, &avpkt);
545 } 546 }
546 if (! frame_finished) 547 if (! frame_finished)
547 { 548 {
548#if DEBUG 549#if DEBUG
549 fprintf (stderr, 550 fprintf (stderr,
550 "Failed to decode a complete frame\n"); 551 "Failed to decode a complete frame\n");
551#endif 552#endif
552#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) 553#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (55,28,1)
553 av_frame_free (&frame); 554 av_frame_free (&frame);
554#else 555#else
555 avcodec_free_frame (&frame); 556 avcodec_free_frame (&frame);
556#endif 557#endif
557 avcodec_close (codec_ctx); 558 avcodec_close (codec_ctx);
558 avcodec_free_context (&codec_ctx); 559 avcodec_free_context (&codec_ctx);
559 return; 560 return;
560 } 561 }
561 calculate_thumbnail_dimensions (codec_ctx->width, codec_ctx->height, 562 calculate_thumbnail_dimensions (codec_ctx->width, codec_ctx->height,
562 codec_ctx->sample_aspect_ratio.num, 563 codec_ctx->sample_aspect_ratio.num,
563 codec_ctx->sample_aspect_ratio.den, 564 codec_ctx->sample_aspect_ratio.den,
@@ -565,40 +566,41 @@ extract_image (ENUM_CODEC_ID image_codec_id,
565 566
566 err = create_thumbnail (codec_ctx, codec_ctx->width, codec_ctx->height, 567 err = create_thumbnail (codec_ctx, codec_ctx->width, codec_ctx->height,
567 frame->linesize, codec_ctx->pix_fmt, 568 frame->linesize, codec_ctx->pix_fmt,
568 (const uint8_t * const*) frame->data, 569 (const uint8_t *const*) frame->data,
569 thumb_width, thumb_height, 570 thumb_width, thumb_height,
570 &encoded_thumbnail, MAX_THUMB_BYTES); 571 &encoded_thumbnail, MAX_THUMB_BYTES);
571 if (err > 0) 572 if (err > 0)
573 {
574 ec->proc (ec->cls,
575 "thumbnailffmpeg",
576 EXTRACTOR_METATYPE_THUMBNAIL,
577 EXTRACTOR_METAFORMAT_BINARY,
578 "image/png",
579 (const char*) encoded_thumbnail,
580 err);
581
582 #if OUTPUT_FILE
583 FILE *f;
584 #ifdef USE_JPEG
585 f = fopen ("thumb.jpg", "wb");
586 #else
587 f = fopen ("thumb.png", "wb");
588 #endif
589 if (! f)
572 { 590 {
573 ec->proc (ec->cls, 591 fprintf (stderr, "Could not open %s\n", "file");
574 "thumbnailffmpeg", 592 exit (1);
575 EXTRACTOR_METATYPE_THUMBNAIL, 593 }
576 EXTRACTOR_METAFORMAT_BINARY, 594
577 "image/png", 595 fwrite (encoded_thumbnail, 1, err, f);
578 (const char*) encoded_thumbnail, 596 fclose (f);
579 err);
580
581 #if OUTPUT_FILE
582 FILE *f;
583 #ifdef USE_JPEG
584 f = fopen("thumb.jpg", "wb");
585 #else
586 f = fopen("thumb.png", "wb");
587 #endif
588 if (!f) {
589 fprintf(stderr, "Could not open %s\n", "file");
590 exit(1);
591 }
592
593 fwrite(encoded_thumbnail, 1, err, f);
594 fclose(f);
595 597
596 #endif 598 #endif
597 599
598 600
599 av_free (encoded_thumbnail); 601 av_free (encoded_thumbnail);
600 } 602 }
601#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) 603#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (55,28,1)
602 av_frame_free (&frame); 604 av_frame_free (&frame);
603#else 605#else
604 avcodec_free_frame (&frame); 606 avcodec_free_frame (&frame);
@@ -637,107 +639,107 @@ extract_video (struct EXTRACTOR_ExtractContext *ec)
637 return; 639 return;
638 if (NULL == (io_ctx = avio_alloc_context (iob, 640 if (NULL == (io_ctx = avio_alloc_context (iob,
639 16 * 1024, 641 16 * 1024,
640 0, ec, 642 0, ec,
641 &read_cb, 643 &read_cb,
642 NULL /* no writing */, 644 NULL /* no writing */,
643 &seek_cb))) 645 &seek_cb)))
644 { 646 {
645 av_free (iob); 647 av_free (iob);
646 return; 648 return;
647 } 649 }
648 if (NULL == (format_ctx = avformat_alloc_context ())) 650 if (NULL == (format_ctx = avformat_alloc_context ()))
649 { 651 {
650 av_free (io_ctx); 652 av_free (io_ctx);
651 return; 653 return;
652 } 654 }
653 format_ctx->pb = io_ctx; 655 format_ctx->pb = io_ctx;
654 options = NULL; 656 options = NULL;
655 if (0 != avformat_open_input (&format_ctx, "<no file>", NULL, &options)) 657 if (0 != avformat_open_input (&format_ctx, "<no file>", NULL, &options))
656 { 658 {
657 av_free (io_ctx); 659 av_free (io_ctx);
658 return; 660 return;
659 } 661 }
660 av_dict_free (&options); 662 av_dict_free (&options);
661 if (0 > avformat_find_stream_info (format_ctx, NULL)) 663 if (0 > avformat_find_stream_info (format_ctx, NULL))
662 { 664 {
663#if DEBUG 665#if DEBUG
664 fprintf (stderr, 666 fprintf (stderr,
665 "Failed to read stream info\n"); 667 "Failed to read stream info\n");
666#endif 668#endif
667 avformat_close_input (&format_ctx); 669 avformat_close_input (&format_ctx);
668 av_free (io_ctx); 670 av_free (io_ctx);
669 return; 671 return;
670 } 672 }
671 codec = NULL; 673 codec = NULL;
672 codec_ctx = NULL; 674 codec_ctx = NULL;
673 video_stream_index = -1; 675 video_stream_index = -1;
674 for (i=0; i<format_ctx->nb_streams; i++) 676 for (i = 0; i<format_ctx->nb_streams; i++)
677 {
678 codec_ctx = format_ctx->streams[i]->codec;
679 if (AVMEDIA_TYPE_VIDEO != codec_ctx->codec_type)
680 continue;
681 if (NULL == (codec = avcodec_find_decoder (codec_ctx->codec_id)))
682 continue;
683 options = NULL;
684 if (0 != (err = avcodec_open2 (codec_ctx, codec, &options)))
675 { 685 {
676 codec_ctx = format_ctx->streams[i]->codec; 686 codec = NULL;
677 if (AVMEDIA_TYPE_VIDEO != codec_ctx->codec_type) 687 continue;
678 continue;
679 if (NULL == (codec = avcodec_find_decoder (codec_ctx->codec_id)))
680 continue;
681 options = NULL;
682 if (0 != (err = avcodec_open2 (codec_ctx, codec, &options)))
683 {
684 codec = NULL;
685 continue;
686 }
687 av_dict_free (&options);
688 video_stream_index = i;
689 break;
690 } 688 }
689 av_dict_free (&options);
690 video_stream_index = i;
691 break;
692 }
691 if ( (-1 == video_stream_index) || 693 if ( (-1 == video_stream_index) ||
692 (0 == codec_ctx->width) || 694 (0 == codec_ctx->width) ||
693 (0 == codec_ctx->height) ) 695 (0 == codec_ctx->height) )
694 { 696 {
695#if DEBUG 697#if DEBUG
696 fprintf (stderr, 698 fprintf (stderr,
697 "No video streams or no suitable codec found\n"); 699 "No video streams or no suitable codec found\n");
698#endif 700#endif
699 if (NULL != codec) 701 if (NULL != codec)
700 avcodec_close (codec_ctx); 702 avcodec_close (codec_ctx);
701 avformat_close_input (&format_ctx); 703 avformat_close_input (&format_ctx);
702 av_free (io_ctx); 704 av_free (io_ctx);
703 return; 705 return;
704 } 706 }
705 707
706#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) 708#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (55,28,1)
707 frame = av_frame_alloc (); 709 frame = av_frame_alloc ();
708#else 710#else
709 frame = avcodec_alloc_frame(); 711 frame = avcodec_alloc_frame ();
710#endif 712#endif
711 if (NULL == frame) 713 if (NULL == frame)
712 { 714 {
713#if DEBUG 715#if DEBUG
714 fprintf (stderr, 716 fprintf (stderr,
715 "Failed to allocate frame\n"); 717 "Failed to allocate frame\n");
716#endif 718#endif
717 avcodec_close (codec_ctx); 719 avcodec_close (codec_ctx);
718 avformat_close_input (&format_ctx); 720 avformat_close_input (&format_ctx);
719 av_free (io_ctx); 721 av_free (io_ctx);
720 return; 722 return;
721 } 723 }
722 724
723 if (format_ctx->duration == AV_NOPTS_VALUE) 725 if (format_ctx->duration == AV_NOPTS_VALUE)
724 { 726 {
725 duration = -1; 727 duration = -1;
726#if DEBUG 728#if DEBUG
727 fprintf (stderr, 729 fprintf (stderr,
728 "Duration unknown\n"); 730 "Duration unknown\n");
729#endif 731#endif
730 } 732 }
731 else 733 else
732 { 734 {
733 duration = format_ctx->duration; 735 duration = format_ctx->duration;
734 } 736 }
735 737
736 /* if duration is known, seek to first tried, 738 /* if duration is known, seek to first tried,
737 * else use 10 sec into stream */ 739 * else use 10 sec into stream */
738 740
739 if(-1 != duration) 741 if (-1 != duration)
740 err = av_seek_frame (format_ctx, -1, (duration/3), 0); 742 err = av_seek_frame (format_ctx, -1, (duration / 3), 0);
741 else 743 else
742 err = av_seek_frame (format_ctx, -1, 10 * AV_TIME_BASE, 0); 744 err = av_seek_frame (format_ctx, -1, 10 * AV_TIME_BASE, 0);
743 745
@@ -746,41 +748,41 @@ extract_video (struct EXTRACTOR_ExtractContext *ec)
746 frame_finished = 0; 748 frame_finished = 0;
747 749
748 while (1) 750 while (1)
751 {
752 err = av_read_frame (format_ctx, &packet);
753 if (err < 0)
754 break;
755 if (packet.stream_index == video_stream_index)
749 { 756 {
750 err = av_read_frame (format_ctx, &packet); 757 avcodec_decode_video2 (codec_ctx,
751 if (err < 0) 758 frame,
759 &frame_finished,
760 &packet);
761 if (frame_finished && frame->key_frame)
762 {
763 av_free_packet (&packet);
752 break; 764 break;
753 if (packet.stream_index == video_stream_index) 765 }
754 {
755 avcodec_decode_video2 (codec_ctx,
756 frame,
757 &frame_finished,
758 &packet);
759 if (frame_finished && frame->key_frame)
760 {
761 av_free_packet (&packet);
762 break;
763 }
764 }
765 av_free_packet (&packet);
766 } 766 }
767 av_free_packet (&packet);
768 }
767 769
768 if (! frame_finished) 770 if (! frame_finished)
769 { 771 {
770#if DEBUG 772#if DEBUG
771 fprintf (stderr, 773 fprintf (stderr,
772 "Failed to decode a complete frame\n"); 774 "Failed to decode a complete frame\n");
773#endif 775#endif
774#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) 776#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (55,28,1)
775 av_frame_free (&frame); 777 av_frame_free (&frame);
776#else 778#else
777 avcodec_free_frame (&frame); 779 avcodec_free_frame (&frame);
778#endif 780#endif
779 avcodec_close (codec_ctx); 781 avcodec_close (codec_ctx);
780 avformat_close_input (&format_ctx); 782 avformat_close_input (&format_ctx);
781 av_free (io_ctx); 783 av_free (io_ctx);
782 return; 784 return;
783 } 785 }
784 calculate_thumbnail_dimensions (codec_ctx->width, codec_ctx->height, 786 calculate_thumbnail_dimensions (codec_ctx->width, codec_ctx->height,
785 codec_ctx->sample_aspect_ratio.num, 787 codec_ctx->sample_aspect_ratio.num,
786 codec_ctx->sample_aspect_ratio.den, 788 codec_ctx->sample_aspect_ratio.den,
@@ -788,37 +790,37 @@ extract_video (struct EXTRACTOR_ExtractContext *ec)
788 790
789 err = create_thumbnail (codec_ctx, codec_ctx->width, codec_ctx->height, 791 err = create_thumbnail (codec_ctx, codec_ctx->width, codec_ctx->height,
790 frame->linesize, codec_ctx->pix_fmt, 792 frame->linesize, codec_ctx->pix_fmt,
791 (const uint8_t* const *) frame->data, 793 (const uint8_t*const *) frame->data,
792 thumb_width, thumb_height, 794 thumb_width, thumb_height,
793 &encoded_thumbnail, MAX_THUMB_BYTES); 795 &encoded_thumbnail, MAX_THUMB_BYTES);
794 if (err > 0) 796 if (err > 0)
795 { 797 {
796 ec->proc (ec->cls, 798 ec->proc (ec->cls,
797 "thumbnailffmpeg", 799 "thumbnailffmpeg",
798 EXTRACTOR_METATYPE_THUMBNAIL, 800 EXTRACTOR_METATYPE_THUMBNAIL,
799 EXTRACTOR_METAFORMAT_BINARY, 801 EXTRACTOR_METAFORMAT_BINARY,
800 "image/png", 802 "image/png",
801 (const char*) encoded_thumbnail, 803 (const char*) encoded_thumbnail,
802 err); 804 err);
803#if OUTPUT_FILE 805#if OUTPUT_FILE
804 FILE *f; 806 FILE *f;
805#ifdef USE_JPEG 807#ifdef USE_JPEG
806 f = fopen("thumb.jpg", "wb"); 808 f = fopen ("thumb.jpg", "wb");
807#else 809#else
808 f = fopen("thumb.png", "wb"); 810 f = fopen ("thumb.png", "wb");
809#endif 811#endif
810 if (!f) 812 if (! f)
811 { 813 {
812 fprintf(stderr, "Could not open %s\n", "file"); 814 fprintf (stderr, "Could not open %s\n", "file");
813 exit(1); 815 exit (1);
814 } 816 }
815 817
816 fwrite(encoded_thumbnail, 1, err, f); 818 fwrite (encoded_thumbnail, 1, err, f);
817 fclose(f); 819 fclose (f);
818#endif 820#endif
819 av_free (encoded_thumbnail); 821 av_free (encoded_thumbnail);
820 } 822 }
821#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,28,1) 823#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (55,28,1)
822 av_frame_free (&frame); 824 av_frame_free (&frame);
823#else 825#else
824 avcodec_free_frame (&frame); 826 avcodec_free_frame (&frame);
@@ -849,28 +851,27 @@ struct MIMEToDecoderMapping
849/** 851/**
850 * map MIME image types to an ffmpeg decoder 852 * map MIME image types to an ffmpeg decoder
851 */ 853 */
852static const struct MIMEToDecoderMapping m2d_map[] = 854static const struct MIMEToDecoderMapping m2d_map[] = {
853 { 855
854 856#if LIBAVCODEC_BUILD >= AV_VERSION_INT (54,25,0)
855#if LIBAVCODEC_BUILD >= AV_VERSION_INT(54,25,0) 857 { "image/x-bmp", AV_CODEC_ID_BMP },
856 { "image/x-bmp", AV_CODEC_ID_BMP }, 858 { "image/gif", AV_CODEC_ID_GIF },
857 { "image/gif", AV_CODEC_ID_GIF }, 859 { "image/jpeg", AV_CODEC_ID_MJPEG },
858 { "image/jpeg", AV_CODEC_ID_MJPEG }, 860 { "image/png", AV_CODEC_ID_PNG },
859 { "image/png", AV_CODEC_ID_PNG }, 861 { "image/x-png", AV_CODEC_ID_PNG },
860 { "image/x-png", AV_CODEC_ID_PNG }, 862 { "image/x-portable-pixmap", AV_CODEC_ID_PPM },
861 { "image/x-portable-pixmap", AV_CODEC_ID_PPM }, 863 { NULL, AV_CODEC_ID_NONE }
862 { NULL, AV_CODEC_ID_NONE }
863#else 864#else
864 { "image/x-bmp", CODEC_ID_BMP }, 865 { "image/x-bmp", CODEC_ID_BMP },
865 { "image/gif", CODEC_ID_GIF }, 866 { "image/gif", CODEC_ID_GIF },
866 { "image/jpeg", CODEC_ID_MJPEG }, 867 { "image/jpeg", CODEC_ID_MJPEG },
867 { "image/png", CODEC_ID_PNG }, 868 { "image/png", CODEC_ID_PNG },
868 { "image/x-png", CODEC_ID_PNG }, 869 { "image/x-png", CODEC_ID_PNG },
869 { "image/x-portable-pixmap", CODEC_ID_PPM }, 870 { "image/x-portable-pixmap", CODEC_ID_PPM },
870 { NULL, CODEC_ID_NONE } 871 { NULL, CODEC_ID_NONE }
871#endif 872#endif
872 873
873 }; 874};
874 875
875 876
876/** 877/**
@@ -887,8 +888,8 @@ EXTRACTOR_thumbnailffmpeg_extract_method (struct EXTRACTOR_ExtractContext *ec)
887 const char *mime; 888 const char *mime;
888 889
889 if (-1 == (iret = ec->read (ec->cls, 890 if (-1 == (iret = ec->read (ec->cls,
890 &data, 891 &data,
891 16 * 1024))) 892 16 * 1024)))
892 return; 893 return;
893 if (NULL == (mime = magic_buffer (magic, data, iret))) 894 if (NULL == (mime = magic_buffer (magic, data, iret)))
894 return; 895 return;
@@ -896,10 +897,10 @@ EXTRACTOR_thumbnailffmpeg_extract_method (struct EXTRACTOR_ExtractContext *ec)
896 return; 897 return;
897 for (i = 0; NULL != m2d_map[i].mime_type; i++) 898 for (i = 0; NULL != m2d_map[i].mime_type; i++)
898 if (0 == strcmp (m2d_map[i].mime_type, mime)) 899 if (0 == strcmp (m2d_map[i].mime_type, mime))
899 { 900 {
900 extract_image (m2d_map[i].codec_id, ec); 901 extract_image (m2d_map[i].codec_id, ec);
901 return; 902 return;
902 } 903 }
903 extract_video (ec); 904 extract_video (ec);
904} 905}
905 906
@@ -926,13 +927,13 @@ EXTRACTOR_thumbnail_extract_method (struct EXTRACTOR_ExtractContext *ec)
926 * @param ap arguments for format 927 * @param ap arguments for format
927 */ 928 */
928static void 929static void
929thumbnailffmpeg_av_log_callback (void* ptr, 930thumbnailffmpeg_av_log_callback (void*ptr,
930 int level, 931 int level,
931 const char *format, 932 const char *format,
932 va_list ap) 933 va_list ap)
933{ 934{
934#if DEBUG 935#if DEBUG
935 vfprintf(stderr, format, ap); 936 vfprintf (stderr, format, ap);
936#endif 937#endif
937} 938}
938 939
@@ -947,9 +948,9 @@ thumbnailffmpeg_lib_init (void)
947 av_register_all (); 948 av_register_all ();
948 magic = magic_open (MAGIC_MIME_TYPE); 949 magic = magic_open (MAGIC_MIME_TYPE);
949 if (0 != magic_load (magic, NULL)) 950 if (0 != magic_load (magic, NULL))
950 { 951 {
951 /* FIXME: how to deal with errors? */ 952 /* FIXME: how to deal with errors? */
952 } 953 }
953} 954}
954 955
955 956
@@ -960,10 +961,10 @@ void __attribute__ ((destructor))
960thumbnailffmpeg_ltdl_fini () 961thumbnailffmpeg_ltdl_fini ()
961{ 962{
962 if (NULL != magic) 963 if (NULL != magic)
963 { 964 {
964 magic_close (magic); 965 magic_close (magic);
965 magic = NULL; 966 magic = NULL;
966 } 967 }
967} 968}
968 969
969 970