1 /*
2  *  decode_lavc.c
3  *
4  *  Copyright (C) Tilmann Bitterberg - March 2003
5  *  Copyright (C) Thomas Oestreich - June 2001
6  *  Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
7  *
8  *  This file is part of transcode, a video stream  processing tool
9  *
10  *  transcode is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  *  transcode is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with GNU Make; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 
30 #include "transcode.h"
31 #include "tcinfo.h"
32 
33 #include "aclib/imgconvert.h"
34 #include "ioaux.h"
35 #include "tc.h"
36 
37 #include "libtc/libtc.h"
38 
39 
40 #define READ_BUFFER_SIZE (10*1024*1024)
41 #define MOD_NAME "decode_ffmpeg"
42 
43 #define MAX_BUF 1024
44 
45 #ifdef HAVE_FFMPEG
46 
47 #include "libtc/tcavcodec.h"
48 
49 
50 static int verbose_flag=TC_QUIET;
51 
52 struct ffmpeg_codec {
53     int           id;
54     unsigned int  tc_id;
55     char          *name;
56     char          fourCCs[10][5];
57 };
58 
59 // fourCC to ID mapping taken from MPlayer's codecs.conf
60 static struct ffmpeg_codec ffmpeg_codecs[] = {
61   {AV_CODEC_ID_MSMPEG4V1, TC_CODEC_ERROR, "mp41",
62     {"MP41", "DIV1", ""}},
63   {AV_CODEC_ID_MSMPEG4V2, TC_CODEC_MP42, "mp42",
64     {"MP42", "DIV2", ""}},
65   {AV_CODEC_ID_MSMPEG4V3, TC_CODEC_DIVX3, "msmpeg4",
66     {"DIV3", "DIV5", "AP41", "MPG3", "MP43", ""}},
67   {AV_CODEC_ID_MPEG4, TC_CODEC_DIVX4, "mpeg4",
68     {"DIVX", "XVID", "MP4S", "M4S2", "MP4V", "UMP4", "DX50", ""}},
69   {AV_CODEC_ID_MJPEG, TC_CODEC_MJPEG, "mjpeg",
70     {"MJPG", "AVRN", "AVDJ", "JPEG", "MJPA", "JFIF", ""}},
71   {AV_CODEC_ID_MPEG1VIDEO, TC_CODEC_MPEG1VIDEO, "mpeg1video",
72     {"MPG1", ""}},
73   {AV_CODEC_ID_DVVIDEO, TC_CODEC_DV, "dvvideo",
74     {"DVSD", ""}},
75   {AV_CODEC_ID_WMV1, TC_CODEC_WMV1, "wmv1",
76     {"WMV1", ""}},
77   {AV_CODEC_ID_WMV2, TC_CODEC_WMV2, "wmv2",
78     {"WMV2", ""}},
79   {AV_CODEC_ID_HUFFYUV, TC_CODEC_HUFFYUV, "hfyu",
80     {"HFYU", ""}},
81   {AV_CODEC_ID_H263I, TC_CODEC_H263I, "h263i",
82     {"I263", ""}},
83   {AV_CODEC_ID_H263P, TC_CODEC_H263P, "h263p",
84     {"H263", "U263", "VIV1", ""}},
85   {AV_CODEC_ID_RV10, TC_CODEC_RV10, "rv10",
86     {"RV10", "RV13", ""}},
87   {AV_CODEC_ID_SVQ1, TC_CODEC_SVQ1, "svq1",
88     {"SVQ1", ""}},
89   {AV_CODEC_ID_SVQ3, TC_CODEC_SVQ3, "svq3",
90     {"SVQ3", ""}},
91   {AV_CODEC_ID_MPEG2VIDEO, TC_CODEC_MPEG2, "mpeg2video",
92     {"MPG2", ""}},
93   {0, TC_CODEC_UNKNOWN, NULL, {""}}};
94 
95 
find_ffmpeg_codec_id(unsigned int transcode_id)96 static struct ffmpeg_codec *find_ffmpeg_codec_id(unsigned int transcode_id)
97 {
98     struct ffmpeg_codec *cdc = &ffmpeg_codecs[0];
99     while (cdc->name != NULL) {
100         if (cdc->tc_id == transcode_id)
101 	        return cdc;
102         cdc++;
103     }
104 
105     return NULL;
106 }
107 
108 
109 /* ------------------------------------------------------------
110  *
111  * decoder thread
112  *
113  * ------------------------------------------------------------*/
114 
decode_lavc(decode_t * decode)115 void decode_lavc(decode_t *decode)
116 {
117   uint8_t           *out_buffer = NULL;
118   int                 pass_through = 0;
119   char               *buffer =  NULL;
120   char               *yuv2rgb_buffer = NULL;
121   AVCodec            *lavc_dec_codec = NULL;
122   AVCodecContext     *lavc_dec_context;
123   int                 x_dim = 0, y_dim = 0;
124   int                 pix_fmt, frame_size = 0, bpp = 8;
125   struct ffmpeg_codec *codec;
126 
127   char   *fourCC = NULL;
128   char *mp4_ptr=NULL;
129   int flush = 0;
130   int mp4_size=0;
131   int buf_len=0;
132   int run=0;
133 
134   // decoder
135   int        len = 0;
136   long       bytes_read = 0;
137   uint8_t   *planes[3];
138 
139   verbose_flag = decode->verbose;
140 
141   x_dim = decode->width;
142   y_dim = decode->height;
143 
144   fourCC="DIVX";
145 
146   //----------------------------------------
147   //
148   // setup decoder
149   //
150   //----------------------------------------
151 
152   TC_INIT_LIBAVCODEC;
153 
154   codec = find_ffmpeg_codec_id(decode->codec);
155   if (codec == NULL) {
156       tc_log_error(__FILE__, "No codec is known for the TAG '%lx'.",
157 		   decode->codec);
158       goto decoder_error;
159   }
160   if (decode->verbose & TC_DEBUG) {
161       tc_log_msg(__FILE__, "Using Codec %s id 0x%x",
162 		 codec->name, codec->tc_id);
163   }
164 
165   lavc_dec_codec = avcodec_find_decoder(codec->id);
166   if (!lavc_dec_codec) {
167       tc_log_error(__FILE__, "No codec found for the FOURCC '%s'.", fourCC);
168       goto decoder_error;
169   }
170 
171   // Set these to the expected values so that ffmpeg's decoder can
172   // properly detect interlaced input.
173   lavc_dec_context = avcodec_alloc_context3(NULL);
174   if (lavc_dec_context == NULL) {
175       tc_log_error(__FILE__, "Could not allocate enough memory.");
176       goto decoder_error;
177   }
178   lavc_dec_context->width  = x_dim;
179   lavc_dec_context->height = y_dim;
180 
181 #if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
182   lavc_dec_context->error_resilience  = 2;
183 #else
184   lavc_dec_context->err_recognition = 2;
185 #endif
186   lavc_dec_context->error_concealment = 3;
187   lavc_dec_context->workaround_bugs = FF_BUG_AUTODETECT;
188 
189   if (avcodec_open2(lavc_dec_context, lavc_dec_codec, NULL) < 0) {
190       tc_log_error(__FILE__, "Could not initialize the '%s' codec.",
191 		   codec->name);
192       goto decoder_error;
193   }
194 
195   pix_fmt = decode->format;
196 
197   frame_size = (x_dim * y_dim * 3)/2;
198   switch (pix_fmt)
199   {
200       case TC_CODEC_YUV420P:
201         frame_size = (x_dim * y_dim * 3)/2;
202         break;
203 
204       case TC_CODEC_RGB:
205         frame_size = x_dim * y_dim * 3;
206         bpp = 24;
207 
208         if (yuv2rgb_buffer == NULL)
209 	    yuv2rgb_buffer = tc_bufalloc(frame_size);
210 
211         if (yuv2rgb_buffer == NULL)
212 	{
213             tc_log_perror(__FILE__, "out of memory");
214             goto decoder_error;
215         }
216 	else
217 	    memset(yuv2rgb_buffer, 0, frame_size);
218         break;
219 
220       case TC_CODEC_RAW:
221 	pass_through = 1;
222 	break;
223   }
224 
225   if(buffer == NULL) buffer=tc_bufalloc(READ_BUFFER_SIZE);
226   if(buffer == NULL) {
227       tc_log_perror(__FILE__, "out of memory");
228       goto decoder_error;
229   }
230 
231   if(out_buffer == NULL) out_buffer=tc_bufalloc(frame_size);
232   if(out_buffer == NULL) {
233       tc_log_perror(__FILE__, "out of memory");
234       goto decoder_error;
235   }
236 
237   memset(buffer, 0, READ_BUFFER_SIZE);
238   memset(out_buffer, 0, frame_size);
239 
240   // DECODE MAIN LOOP
241 
242   bytes_read = tc_pread(decode->fd_in, (uint8_t*) buffer, READ_BUFFER_SIZE);
243 
244   if (bytes_read < 0) {
245       tc_log_warn(__FILE__, "EOF?");
246       goto decoder_error;
247   }
248   mp4_ptr = buffer;
249   mp4_size = bytes_read;
250   buf_len = 0;
251 
252   do {
253       AVFrame  picture;
254       int got_picture = 0;
255 
256       if (buf_len >= mp4_size) {
257 	  if (verbose_flag & TC_DEBUG)
258 	      tc_log_warn(__FILE__, "EOF?");
259 	  break;
260       }
261 
262       //tc_log_msg(__FILE__, "SIZE: (%d) MP4(%d) blen(%d) BUF(%d) read(%ld)", len, mp4_size, buf_len, READ_BUFFER_SIZE, bytes_read);
263       do {
264           AVPacket avpkt;
265           av_init_packet(&avpkt);
266           avpkt.data = NULL;
267           avpkt.size = 0;
268 	  len = avcodec_decode_video2(lavc_dec_context, &picture,
269 		  &got_picture, &avpkt);
270 
271 	  if (len < 0) {
272 	      tc_log_error(__FILE__, "frame decoding failed");
273 	      goto decoder_error;
274 	  }
275 	  if (verbose_flag & TC_DEBUG) {
276 	      tc_log_msg(__FILE__, "here frame pic %d run %d len %d",
277 			 got_picture, run, len);
278 	  }
279 	  if (run++ > 10000) {
280 	      tc_log_error(__FILE__, "Fatal decoder error");
281 	      goto decoder_error;
282 	  }
283       } while (!got_picture);
284       run = 0;
285 
286       buf_len += len;
287 
288       YUV_INIT_PLANES(planes, out_buffer, IMG_YUV420P,
289 		      lavc_dec_context->width, lavc_dec_context->height);
290 
291       // Convert avcodec image to the requested YUV or RGB format
292       switch (lavc_dec_context->pix_fmt) {
293 	case AV_PIX_FMT_YUVJ420P:
294 	case AV_PIX_FMT_YUV420P:
295 	    // Remove "dead space" at right edge of planes, if any
296 	    if (picture.linesize[0] != lavc_dec_context->width) {
297 		int y;
298 		for (y = 0; y < lavc_dec_context->height; y++) {
299 		    ac_memcpy(picture.data[0] + y*lavc_dec_context->width,
300 			      picture.data[0] + y*picture.linesize[0],
301 			      lavc_dec_context->width);
302 		    if (y%2 == 0) {
303 			ac_memcpy(picture.data[1] + y*(lavc_dec_context->width/2),
304 				  picture.data[1] + y*picture.linesize[1],
305 				  lavc_dec_context->width/2);
306 			ac_memcpy(picture.data[2] + y*(lavc_dec_context->width/2),
307 				  picture.data[2] + y*picture.linesize[2],
308 				  lavc_dec_context->width/2);
309 		    }
310 		}
311 	    }
312             /* FIXME: we can't use tcv_convert here because it assumes
313              * contiguous planes, which libavcodec might not give us  --AC */
314 	    ac_imgconvert(picture.data, IMG_YUV420P, planes,
315 			  pix_fmt==TC_CODEC_YUV420P ? IMG_YUV420P : IMG_RGB_DEFAULT,
316 			  lavc_dec_context->width, lavc_dec_context->height);
317 	    break;
318 	case AV_PIX_FMT_YUV411P:
319 	    if (picture.linesize[0] != lavc_dec_context->width) {
320 		int y;
321 		for (y = 0; y < lavc_dec_context->height; y++) {
322 		    ac_memcpy(picture.data[0] + y*lavc_dec_context->width,
323 			      picture.data[0] + y*picture.linesize[0],
324 			      lavc_dec_context->width);
325 		    ac_memcpy(picture.data[1] + y*(lavc_dec_context->width/4),
326 			      picture.data[1] + y*picture.linesize[1],
327 			      lavc_dec_context->width/4);
328 		    ac_memcpy(picture.data[2] + y*(lavc_dec_context->width/4),
329 			      picture.data[2] + y*picture.linesize[2],
330 			      lavc_dec_context->width/4);
331 		}
332 	    }
333 	    ac_imgconvert(picture.data, IMG_YUV411P, planes,
334 			  pix_fmt==TC_CODEC_YUV420P ? IMG_YUV420P : IMG_RGB_DEFAULT,
335 			  lavc_dec_context->width, lavc_dec_context->height);
336 	    break;
337 	case AV_PIX_FMT_YUVJ422P:
338 	case AV_PIX_FMT_YUV422P:
339 	    if (picture.linesize[0] != lavc_dec_context->width) {
340 		int y;
341 		for (y = 0; y < lavc_dec_context->height; y++) {
342 		    ac_memcpy(picture.data[0] + y*lavc_dec_context->width,
343 			      picture.data[0] + y*picture.linesize[0],
344 			      lavc_dec_context->width);
345 		    ac_memcpy(picture.data[1] + y*(lavc_dec_context->width/2),
346 			      picture.data[1] + y*picture.linesize[1],
347 			      lavc_dec_context->width/2);
348 		    ac_memcpy(picture.data[2] + y*(lavc_dec_context->width/2),
349 			      picture.data[2] + y*picture.linesize[2],
350 			      lavc_dec_context->width/2);
351 		}
352 	    }
353 	    ac_imgconvert(picture.data, IMG_YUV422P, planes,
354 			  pix_fmt==TC_CODEC_YUV420P ? IMG_YUV420P : IMG_RGB_DEFAULT,
355 			  lavc_dec_context->width, lavc_dec_context->height);
356 	    break;
357 	case AV_PIX_FMT_YUVJ444P:
358 	case AV_PIX_FMT_YUV444P:
359 	    if (picture.linesize[0] != lavc_dec_context->width) {
360 		int y;
361 		for (y = 0; y < lavc_dec_context->height; y++) {
362 		    ac_memcpy(picture.data[0] + y*lavc_dec_context->width,
363 			      picture.data[0] + y*picture.linesize[0],
364 			      lavc_dec_context->width);
365 		    ac_memcpy(picture.data[1] + y*lavc_dec_context->width,
366 			      picture.data[1] + y*picture.linesize[1],
367 			      lavc_dec_context->width);
368 		    ac_memcpy(picture.data[2] + y*lavc_dec_context->width,
369 			      picture.data[2] + y*picture.linesize[2],
370 			      lavc_dec_context->width);
371 		}
372 	    }
373 	    ac_imgconvert(picture.data, IMG_YUV444P, planes,
374 			  pix_fmt==TC_CODEC_YUV420P ? IMG_YUV420P : IMG_RGB_DEFAULT,
375 			  lavc_dec_context->width, lavc_dec_context->height);
376 	    break;
377 	default:
378 	    tc_log_error(__FILE__, "Unsupported decoded frame format");
379 	    goto decoder_error;
380       }
381 
382       /* buffer more than half empty -> Fill it */
383       if (!flush && buf_len > mp4_size/2+1) {
384 	  int rest = mp4_size - buf_len;
385 	  if (verbose_flag & TC_DEBUG)
386 	      tc_log_msg(__FILE__, "FILL rest %d", rest);
387 
388 	  /* Move data if needed */
389 	  if (rest)
390 	      memmove(buffer, buffer+buf_len, READ_BUFFER_SIZE-buf_len);
391 
392 	  /* read new data */
393 	  if ( (bytes_read = tc_pread(decode->fd_in, (uint8_t*) (buffer+(READ_BUFFER_SIZE-buf_len)), buf_len) )  != buf_len) {
394 	      if (verbose_flag & TC_DEBUG)
395 		  tc_log_msg(__FILE__, "read failed read (%ld) should (%d)", bytes_read, buf_len);
396 	      flush = 1;
397 	      mp4_size -= buf_len;
398 	      mp4_size += bytes_read;
399 	  }
400 	  buf_len = 0;
401       }
402       //tc_log_msg(__FILE__, "SIZE: (%d) MP4(%d) blen(%d) BUF(%d) read(%ld)", len, mp4_size, buf_len, READ_BUFFER_SIZE, bytes_read);
403       if (mp4_size<=0) {
404 
405 	  if (verbose_flag & TC_DEBUG)
406 	      tc_log_msg(__FILE__, "no more bytes");
407 	  break;
408       }
409 
410       if (tc_pwrite(decode->fd_out, out_buffer, frame_size) != frame_size) {
411 	  goto decoder_error;
412       }
413 
414   } while (1);
415 
416   import_exit(0);
417   return;
418 
419 decoder_error:
420   import_exit(1);
421 }
422 
423 
424 #else /* HAVE_FFMPEG */
425 
decode_lavc(decode_t * decode)426 void decode_lavc(decode_t *decode)
427 {
428     tc_log_error(__FILE__, "No support for FFmpeg configured -- exiting");
429     import_exit(1);
430 }
431 
432 
433 #endif /* HAVE_FFMPEG */
434 
435 /*************************************************************************/
436 
437 /*
438  * Local variables:
439  *   c-file-style: "stroustrup"
440  *   c-file-offsets: ((case-label . *) (statement-case-intro . *))
441  *   indent-tabs-mode: nil
442  * End:
443  *
444  * vim: expandtab shiftwidth=4:
445  */
446 
447