aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Cabral <brataoufba@gmail.com>2013-12-23 19:38:16 +0000
committerBruno Cabral <brataoufba@gmail.com>2013-12-23 19:38:16 +0000
commit9b9c978b5387e89a10e8c062ec0e3546c66e05f9 (patch)
treef7a94ab45ac2847f5a0d6688a4cf9c3250f54ef5
parentb8ac0311229a3beb64cb47c70f54e3776c633c02 (diff)
downloadlibextractor-9b9c978b5387e89a10e8c062ec0e3546c66e05f9.tar.gz
libextractor-9b9c978b5387e89a10e8c062ec0e3546c66e05f9.zip
Change the thumbnailffmpeg_extractor.c default to JPG. 90% of reduction in thumbnail size. Tweak the algorithm to get the first key_frame after the first third of a file, previous was got at 10 seconds.
-rw-r--r--src/plugins/thumbnailffmpeg_extractor.c150
1 files changed, 130 insertions, 20 deletions
diff --git a/src/plugins/thumbnailffmpeg_extractor.c b/src/plugins/thumbnailffmpeg_extractor.c
index cd7ca6e..9ee7f51 100644
--- a/src/plugins/thumbnailffmpeg_extractor.c
+++ b/src/plugins/thumbnailffmpeg_extractor.c
@@ -60,7 +60,18 @@
60#endif 60#endif
61 61
62/** 62/**
63 * Set to 1 to enable debug output. 63 * Set to 1 to use JPEG, PNG otherwise
64 */
65#define USE_JPEG 1
66
67/**
68 * Set to 1 to enable a output file for testing.
69 */
70#define OUTPUT_FILE 1
71
72
73/**
74 * Set to 1 to use jpeg.
64 */ 75 */
65#define DEBUG 0 76#define DEBUG 0
66 77
@@ -114,7 +125,7 @@ read_cb (void *opaque,
114 return ret; 125 return ret;
115} 126}
116 127
117 128
118/** 129/**
119 * Seek callback. 130 * Seek callback.
120 * 131 *
@@ -151,7 +162,7 @@ seek_cb (void *opaque,
151 * @return the number of bytes used, 0 on error 162 * @return the number of bytes used, 0 on error
152 */ 163 */
153static size_t 164static size_t
154create_thumbnail (int src_width, int src_height, 165create_thumbnail (AVCodecContext *pCodecCtx, int src_width, int src_height,
155 int src_stride[], 166 int src_stride[],
156 enum PixelFormat src_pixfmt, 167 enum PixelFormat src_pixfmt,
157 const uint8_t * const src_data[], 168 const uint8_t * const src_data[],
@@ -174,12 +185,19 @@ create_thumbnail (int src_width, int src_height,
174 pkt.data = NULL; 185 pkt.data = NULL;
175 pkt.size = 0; 186 pkt.size = 0;
176 int gotPacket; 187 int gotPacket;
177 188#if USE_JPEG
178 if (NULL == (encoder_codec = avcodec_find_encoder_by_name ("png"))) 189 #if LIBAVCODEC_BUILD >= AV_VERSION_INT(54,25,0)
190 if (NULL == (encoder_codec = avcodec_find_encoder ( AV_CODEC_ID_MJPEG )))
191 #else
192 if (NULL == (encoder_codec = avcodec_find_encoder ( CODEC_ID_MJPEG )))
193 #endif
194 #else
195 if (NULL == (encoder_codec = avcodec_find_encoder_by_name ("png")))
196 #endif
179 { 197 {
180#if DEBUG 198#if DEBUG
181 fprintf (stderr, 199 fprintf (stderr,
182 "Couldn't find a PNG encoder\n"); 200 "Couldn't find a encoder\n");
183#endif 201#endif
184 return 0; 202 return 0;
185 } 203 }
@@ -189,8 +207,13 @@ create_thumbnail (int src_width, int src_height,
189 if (NULL == 207 if (NULL ==
190 (scaler_ctx = 208 (scaler_ctx =
191 sws_getContext (src_width, src_height, src_pixfmt, 209 sws_getContext (src_width, src_height, src_pixfmt,
192 dst_width, dst_height, PIX_FMT_RGB24, 210 dst_width, dst_height,
193 SWS_BILINEAR, NULL, NULL, NULL))) 211 #if USE_JPEG
212 PIX_FMT_YUVJ420P
213 #else
214 PIX_FMT_RGB24
215 #endif
216 ,SWS_BILINEAR, NULL, NULL, NULL)))
194 { 217 {
195#if DEBUG 218#if DEBUG
196 fprintf (stderr, 219 fprintf (stderr,
@@ -209,7 +232,13 @@ create_thumbnail (int src_width, int src_height,
209 return 0; 232 return 0;
210 } 233 }
211 if (NULL == (dst_buffer = 234 if (NULL == (dst_buffer =
212 av_malloc (avpicture_get_size (PIX_FMT_RGB24, dst_width, dst_height)))) 235 av_malloc (avpicture_get_size (
236 #if USE_JPEG
237 PIX_FMT_YUVJ420P
238 #else
239 PIX_FMT_RGB24
240 #endif
241 ,dst_width, dst_height))))
213 { 242 {
214#if DEBUG 243#if DEBUG
215 fprintf (stderr, 244 fprintf (stderr,
@@ -220,7 +249,12 @@ create_thumbnail (int src_width, int src_height,
220 return 0; 249 return 0;
221 } 250 }
222 avpicture_fill ((AVPicture *) dst_frame, dst_buffer, 251 avpicture_fill ((AVPicture *) dst_frame, dst_buffer,
223 PIX_FMT_RGB24, dst_width, dst_height); 252 #if USE_JPEG
253 PIX_FMT_YUVJ420P
254 #else
255 PIX_FMT_RGB24
256 #endif
257 , dst_width, dst_height);
224 sws_scale (scaler_ctx, 258 sws_scale (scaler_ctx,
225 src_data, 259 src_data,
226 src_stride, 260 src_stride,
@@ -255,7 +289,22 @@ create_thumbnail (int src_width, int src_height,
255 } 289 }
256 encoder_codec_ctx->width = dst_width; 290 encoder_codec_ctx->width = dst_width;
257 encoder_codec_ctx->height = dst_height; 291 encoder_codec_ctx->height = dst_height;
292 #if USE_JPEG
293 encoder_codec_ctx->bit_rate = pCodecCtx->bit_rate;
294 #if LIBAVCODEC_BUILD >= AV_VERSION_INT(54,25,0)
295 encoder_codec_ctx->codec_id = AV_CODEC_ID_MJPEG;
296 encoder_codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
297 #else
298 encoder_codec_ctx->codec_id = CODEC_ID_MJPEG;
299 encoder_codec_ctx->codec_type = CODEC_TYPE_VIDEO;
300 #endif
301 encoder_codec_ctx->time_base.num = pCodecCtx->time_base.num;
302 encoder_codec_ctx->time_base.den = pCodecCtx->time_base.den;
303 encoder_codec_ctx->pix_fmt = PIX_FMT_YUVJ420P;
304 #else
258 encoder_codec_ctx->pix_fmt = PIX_FMT_RGB24; 305 encoder_codec_ctx->pix_fmt = PIX_FMT_RGB24;
306 #endif
307
259 opts = NULL; 308 opts = NULL;
260 if (avcodec_open2 (encoder_codec_ctx, encoder_codec, &opts) < 0) 309 if (avcodec_open2 (encoder_codec_ctx, encoder_codec, &opts) < 0)
261 { 310 {
@@ -271,9 +320,19 @@ create_thumbnail (int src_width, int src_height,
271 return 0; 320 return 0;
272 } 321 }
273 322
323
324
325#ifdef USE_JPEG
326 encoder_codec_ctx->mb_lmin = encoder_codec_ctx->lmin = encoder_codec_ctx->qmin * FF_QP2LAMBDA;
327 encoder_codec_ctx->mb_lmax = encoder_codec_ctx->lmax = encoder_codec_ctx->qmax * FF_QP2LAMBDA;
328 encoder_codec_ctx->flags = CODEC_FLAG_QSCALE;
329 encoder_codec_ctx->global_quality = encoder_codec_ctx->qmin * FF_QP2LAMBDA;
330
331 dst_frame->pts = 1;
332 dst_frame->quality = encoder_codec_ctx->global_quality;
333#endif
274 334
275#if LIBAVCODEC_BUILD >= AV_VERSION_INT(54,25,0) 335#if LIBAVCODEC_BUILD >= AV_VERSION_INT(54,25,0)
276 //err = encode_frame (encoder_codec_ctx, dst_frame);
277 err = avcodec_encode_video2 (encoder_codec_ctx, 336 err = avcodec_encode_video2 (encoder_codec_ctx,
278 &pkt, 337 &pkt,
279 dst_frame, &gotPacket); 338 dst_frame, &gotPacket);
@@ -451,7 +510,7 @@ extract_image (ENUM_CODEC_ID image_codec_id,
451 codec_ctx->sample_aspect_ratio.den, 510 codec_ctx->sample_aspect_ratio.den,
452 &thumb_width, &thumb_height); 511 &thumb_width, &thumb_height);
453 512
454 err = create_thumbnail (codec_ctx->width, codec_ctx->height, 513 err = create_thumbnail (codec_ctx, codec_ctx->width, codec_ctx->height,
455 frame->linesize, codec_ctx->pix_fmt, 514 frame->linesize, codec_ctx->pix_fmt,
456 (const uint8_t * const*) frame->data, 515 (const uint8_t * const*) frame->data,
457 thumb_width, thumb_height, 516 thumb_width, thumb_height,
@@ -465,6 +524,25 @@ extract_image (ENUM_CODEC_ID image_codec_id,
465 "image/png", 524 "image/png",
466 (const char*) encoded_thumbnail, 525 (const char*) encoded_thumbnail,
467 err); 526 err);
527
528 #if OUTPUT_FILE
529 FILE *f;
530 #ifdef USE_JPEG
531 f = fopen("thumb.jpg", "wb");
532 #else
533 f = fopen("thumb.png", "wb");
534 #endif
535 if (!f) {
536 fprintf(stderr, "Could not open %s\n", "file");
537 exit(1);
538 }
539
540 fwrite(encoded_thumbnail, 1, err, f);
541 fclose(f);
542
543 #endif
544
545
468 av_free (encoded_thumbnail); 546 av_free (encoded_thumbnail);
469 } 547 }
470 av_free (frame); 548 av_free (frame);
@@ -574,18 +652,33 @@ extract_video (struct EXTRACTOR_ExtractContext *ec)
574 av_free (io_ctx); 652 av_free (io_ctx);
575 return; 653 return;
576 } 654 }
577#if DEBUG 655 int duration;
578 if (format_ctx->duration == AV_NOPTS_VALUE) 656 if (format_ctx->duration == AV_NOPTS_VALUE)
657 {
658 duration = -1;
659#if DEBUG
579 fprintf (stderr, 660 fprintf (stderr,
580 "Duration unknown\n"); 661 "Duration unknown\n");
662#endif
663 }
581 else 664 else
665 {
666 #if DEBUG
667 duration = format_ctx->duration;
582 fprintf (stderr, 668 fprintf (stderr,
583 "Duration: %lld\n", 669 "Duration: %lld\n",
584 format_ctx->duration); 670 format_ctx->duration);
585#endif 671#endif
586 /* TODO: if duration is known, seek to some better place, 672 }
587 * but use 10 sec into stream for now */ 673
588 err = av_seek_frame (format_ctx, -1, 10 * AV_TIME_BASE, 0); 674 /* if duration is known, seek to first tried,
675 * else use 10 sec into stream */
676
677 if(-1 != duration)
678 err = av_seek_frame (format_ctx, -1, (duration/3), 0);
679 else
680 err = av_seek_frame (format_ctx, -1, 10 * AV_TIME_BASE, 0);
681
589 if (err >= 0) 682 if (err >= 0)
590 avcodec_flush_buffers (codec_ctx); 683 avcodec_flush_buffers (codec_ctx);
591 frame_finished = 0; 684 frame_finished = 0;
@@ -626,7 +719,8 @@ extract_video (struct EXTRACTOR_ExtractContext *ec)
626 codec_ctx->sample_aspect_ratio.num, 719 codec_ctx->sample_aspect_ratio.num,
627 codec_ctx->sample_aspect_ratio.den, 720 codec_ctx->sample_aspect_ratio.den,
628 &thumb_width, &thumb_height); 721 &thumb_width, &thumb_height);
629 err = create_thumbnail (codec_ctx->width, codec_ctx->height, 722
723 err = create_thumbnail (codec_ctx, codec_ctx->width, codec_ctx->height,
630 frame->linesize, codec_ctx->pix_fmt, 724 frame->linesize, codec_ctx->pix_fmt,
631 (const uint8_t* const *) frame->data, 725 (const uint8_t* const *) frame->data,
632 thumb_width, thumb_height, 726 thumb_width, thumb_height,
@@ -641,6 +735,22 @@ extract_video (struct EXTRACTOR_ExtractContext *ec)
641 "image/png", 735 "image/png",
642 (const char*) encoded_thumbnail, 736 (const char*) encoded_thumbnail,
643 err); 737 err);
738 #if OUTPUT_FILE
739 FILE *f;
740 #ifdef USE_JPEG
741 f = fopen("thumb.jpg", "wb");
742 #else
743 f = fopen("thumb.png", "wb");
744 #endif
745 if (!f) {
746 fprintf(stderr, "Could not open %s\n", "file");
747 exit(1);
748 }
749
750 fwrite(encoded_thumbnail, 1, err, f);
751 fclose(f);
752
753 #endif
644 av_free (encoded_thumbnail); 754 av_free (encoded_thumbnail);
645 } 755 }
646 av_free (frame); 756 av_free (frame);