@@ -101,12 +101,14 @@ CFFmpegImage::CFFmpegImage()
101101{
102102 m_hasAlpha = false ;
103103 m_pFrame = nullptr ;
104-
104+ m_outputBuffer = nullptr ;
105105}
106106
107107CFFmpegImage::~CFFmpegImage ()
108108{
109109 av_frame_free (&m_pFrame);
110+ // someone could have forgotten to call us
111+ free (m_outputBuffer);
110112}
111113
112114bool CFFmpegImage::LoadImageFromMemory (unsigned char * buffer, unsigned int bufSize,
@@ -243,7 +245,7 @@ bool CFFmpegImage::Decode(unsigned char * const pixels, unsigned int width, unsi
243245
244246 bool needsCopy = false ;
245247 int pixelsSize = pitch * height;
246- if (size == pixelsSize && pitch == pictureRGB->linesize [0 ])
248+ if (size == pixelsSize && ( int ) pitch == pictureRGB->linesize [0 ])
247249 {
248250 // We can use the pixels buffer directly
249251 pictureRGB->data [0 ] = pixels;
@@ -309,9 +311,92 @@ bool CFFmpegImage::CreateThumbnailFromSurface(unsigned char* bufferin, unsigned
309311 unsigned char * &bufferout,
310312 unsigned int &bufferoutSize)
311313{
312- return false ;
314+
315+ if (format != XB_FMT_A8R8G8B8)
316+ {
317+ CLog::Log (LOGNOTICE, " Supplied format: %d is not supported." , format);
318+ }
319+ AVCodec* codec = avcodec_find_encoder (CODEC_ID_MJPEG);
320+ if (!codec)
321+ return false ;
322+
323+ AVCodecContext* avOutctx = avcodec_alloc_context3 (codec);
324+ if (!avOutctx)
325+ return false ;
326+
327+ avOutctx->height = height;
328+ avOutctx->width = width;
329+ avOutctx->time_base .num = 1 ;
330+ avOutctx->time_base .den = 1 ;
331+ avOutctx->pix_fmt = PIX_FMT_YUVJ420P;
332+
333+ unsigned int internalBufOutSize = 0 ;
334+
335+ internalBufOutSize = avpicture_get_size (avOutctx->pix_fmt , avOutctx->width , avOutctx->height );
336+ m_outputBuffer = (uint8_t *) av_malloc (internalBufOutSize);
337+ if (!m_outputBuffer)
338+ {
339+ avcodec_free_context (&avOutctx);
340+ return false ;
341+ }
342+
343+ if (avcodec_open2 (avOutctx, codec, NULL ) < 0 )
344+ {
345+ CLog::Log (LOGERROR, " Could not generate thumbnail: %s" , destFile.c_str ());
346+ av_free (m_outputBuffer);
347+ m_outputBuffer = NULL ;
348+ avcodec_free_context (&avOutctx);
349+ return false ;
350+ }
351+
352+ AVFrame* frame = av_frame_alloc ();
353+ if (!frame)
354+ {
355+ CLog::Log (LOGERROR, " Could not generate thumbnail: %s" , destFile.c_str ());
356+ av_free (m_outputBuffer);
357+ m_outputBuffer = NULL ;
358+ avcodec_close (avOutctx);
359+ avcodec_free_context (&avOutctx);
360+ return false ;
361+ }
362+
363+ frame->pts = 1 ;
364+ frame->quality = avOutctx->global_quality ;
365+ frame->data [0 ] = (uint8_t *) bufferin;
366+ frame->height = height;
367+ frame->width = width;
368+ frame->linesize [0 ] = pitch;
369+ frame->format = AV_PIX_FMT_ARGB;
370+
371+ int got_package = 0 ;
372+ AVPacket avpkt;
373+ av_init_packet (&avpkt);
374+ avpkt.data = m_outputBuffer;
375+ avpkt.size = internalBufOutSize;
376+
377+ if ((avcodec_encode_video2 (avOutctx, &avpkt, frame, &got_package) < 0 ) || (got_package == 0 ))
378+ {
379+ CLog::Log (LOGERROR, " Could not generate thumbnail: %s" , destFile.c_str ());
380+ av_free (m_outputBuffer);
381+ m_outputBuffer = NULL ;
382+ av_frame_free (&frame);
383+ avcodec_close (avOutctx);
384+ avcodec_free_context (&avOutctx);
385+ return false ;
386+ }
387+
388+ bufferoutSize = avpkt.size ;
389+ bufferout = m_outputBuffer;
390+
391+ av_frame_free (&frame);
392+ avcodec_close (avOutctx);
393+ avcodec_free_context (&avOutctx);
394+
395+ return true ;
313396}
314397
315398void CFFmpegImage::ReleaseThumbnailBuffer ()
316399{
400+ av_free (m_outputBuffer);
401+ m_outputBuffer = NULL ;
317402}
0 commit comments