diff options
author | Bruno Cabral <brataoufba@gmail.com> | 2013-12-23 19:38:16 +0000 |
---|---|---|
committer | Bruno Cabral <brataoufba@gmail.com> | 2013-12-23 19:38:16 +0000 |
commit | 9b9c978b5387e89a10e8c062ec0e3546c66e05f9 (patch) | |
tree | f7a94ab45ac2847f5a0d6688a4cf9c3250f54ef5 | |
parent | b8ac0311229a3beb64cb47c70f54e3776c633c02 (diff) | |
download | libextractor-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.c | 150 |
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 | */ |
153 | static size_t | 164 | static size_t |
154 | create_thumbnail (int src_width, int src_height, | 165 | create_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); |