diff options
| author | Michele Calgaro <michele.calgaro@yahoo.it> | 2020-09-11 14:38:47 +0900 |
|---|---|---|
| committer | Michele Calgaro <michele.calgaro@yahoo.it> | 2020-09-11 14:38:47 +0900 |
| commit | 884c8093d63402a1ad0b502244b791e3c6782be3 (patch) | |
| tree | a600d4ab0d431a2bdfe4c15b70df43c14fbd8dd0 /debian/transcode/transcode-1.1.7/import/decode_lavc.c | |
| parent | 14e1aa2006796f147f3f4811fb908a6b01e79253 (diff) | |
| download | extra-dependencies-884c8093d63402a1ad0b502244b791e3c6782be3.tar.gz extra-dependencies-884c8093d63402a1ad0b502244b791e3c6782be3.zip | |
Added debian extra dependency packages.
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
Diffstat (limited to 'debian/transcode/transcode-1.1.7/import/decode_lavc.c')
| -rw-r--r-- | debian/transcode/transcode-1.1.7/import/decode_lavc.c | 446 |
1 files changed, 446 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/import/decode_lavc.c b/debian/transcode/transcode-1.1.7/import/decode_lavc.c new file mode 100644 index 00000000..5ef73d67 --- /dev/null +++ b/debian/transcode/transcode-1.1.7/import/decode_lavc.c @@ -0,0 +1,446 @@ +/* + * decode_lavc.c + * + * Copyright (C) Tilmann Bitterberg - March 2003 + * Copyright (C) Thomas Oestreich - June 2001 + * Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * + * This file is part of transcode, a video stream processing tool + * + * transcode is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * transcode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "transcode.h" +#include "tcinfo.h" + +#include "aclib/imgconvert.h" +#include "ioaux.h" +#include "tc.h" + +#include "libtc/libtc.h" + + +#define READ_BUFFER_SIZE (10*1024*1024) +#define MOD_NAME "decode_ffmpeg" + +#define MAX_BUF 1024 + +#ifdef HAVE_FFMPEG + +#include "libtc/tcavcodec.h" + + +static int verbose_flag=TC_QUIET; + +struct ffmpeg_codec { + int id; + unsigned int tc_id; + char *name; + char fourCCs[10][5]; +}; + +// fourCC to ID mapping taken from MPlayer's codecs.conf +static struct ffmpeg_codec ffmpeg_codecs[] = { + {CODEC_ID_MSMPEG4V1, TC_CODEC_ERROR, "mp41", + {"MP41", "DIV1", ""}}, + {CODEC_ID_MSMPEG4V2, TC_CODEC_MP42, "mp42", + {"MP42", "DIV2", ""}}, + {CODEC_ID_MSMPEG4V3, TC_CODEC_DIVX3, "msmpeg4", + {"DIV3", "DIV5", "AP41", "MPG3", "MP43", ""}}, + {CODEC_ID_MPEG4, TC_CODEC_DIVX4, "mpeg4", + {"DIVX", "XVID", "MP4S", "M4S2", "MP4V", "UMP4", "DX50", ""}}, + {CODEC_ID_MJPEG, TC_CODEC_MJPEG, "mjpeg", + {"MJPG", "AVRN", "AVDJ", "JPEG", "MJPA", "JFIF", ""}}, + {CODEC_ID_MPEG1VIDEO, TC_CODEC_MPEG1VIDEO, "mpeg1video", + {"MPG1", ""}}, + {CODEC_ID_DVVIDEO, TC_CODEC_DV, "dvvideo", + {"DVSD", ""}}, + {CODEC_ID_WMV1, TC_CODEC_WMV1, "wmv1", + {"WMV1", ""}}, + {CODEC_ID_WMV2, TC_CODEC_WMV2, "wmv2", + {"WMV2", ""}}, + {CODEC_ID_HUFFYUV, TC_CODEC_HUFFYUV, "hfyu", + {"HFYU", ""}}, + {CODEC_ID_H263I, TC_CODEC_H263I, "h263i", + {"I263", ""}}, + {CODEC_ID_H263P, TC_CODEC_H263P, "h263p", + {"H263", "U263", "VIV1", ""}}, + {CODEC_ID_RV10, TC_CODEC_RV10, "rv10", + {"RV10", "RV13", ""}}, + {CODEC_ID_SVQ1, TC_CODEC_SVQ1, "svq1", + {"SVQ1", ""}}, + {CODEC_ID_SVQ3, TC_CODEC_SVQ3, "svq3", + {"SVQ3", ""}}, + {CODEC_ID_MPEG2VIDEO, TC_CODEC_MPEG2, "mpeg2video", + {"MPG2", ""}}, + {0, TC_CODEC_UNKNOWN, NULL, {""}}}; + + +static struct ffmpeg_codec *find_ffmpeg_codec_id(unsigned int transcode_id) +{ + struct ffmpeg_codec *cdc = &ffmpeg_codecs[0]; + while (cdc->name != NULL) { + if (cdc->tc_id == transcode_id) + return cdc; + cdc++; + } + + return NULL; +} + + +/* ------------------------------------------------------------ + * + * decoder thread + * + * ------------------------------------------------------------*/ + +void decode_lavc(decode_t *decode) +{ + uint8_t *out_buffer = NULL; + int pass_through = 0; + char *buffer = NULL; + char *yuv2rgb_buffer = NULL; + AVCodec *lavc_dec_codec = NULL; + AVCodecContext *lavc_dec_context; + int x_dim = 0, y_dim = 0; + int pix_fmt, frame_size = 0, bpp = 8; + struct ffmpeg_codec *codec; + + char *fourCC = NULL; + char *mp4_ptr=NULL; + int flush = 0; + int mp4_size=0; + int buf_len=0; + int run=0; + + // decoder + int len = 0; + long bytes_read = 0; + uint8_t *planes[3]; + + verbose_flag = decode->verbose; + + x_dim = decode->width; + y_dim = decode->height; + + fourCC="DIVX"; + + //---------------------------------------- + // + // setup decoder + // + //---------------------------------------- + + TC_INIT_LIBAVCODEC; + + codec = find_ffmpeg_codec_id(decode->codec); + if (codec == NULL) { + tc_log_error(__FILE__, "No codec is known for the TAG '%lx'.", + decode->codec); + goto decoder_error; + } + if (decode->verbose & TC_DEBUG) { + tc_log_msg(__FILE__, "Using Codec %s id 0x%x", + codec->name, codec->tc_id); + } + + lavc_dec_codec = avcodec_find_decoder(codec->id); + if (!lavc_dec_codec) { + tc_log_error(__FILE__, "No codec found for the FOURCC '%s'.", fourCC); + goto decoder_error; + } + + // Set these to the expected values so that ffmpeg's decoder can + // properly detect interlaced input. + lavc_dec_context = avcodec_alloc_context(); + if (lavc_dec_context == NULL) { + tc_log_error(__FILE__, "Could not allocate enough memory."); + goto decoder_error; + } + lavc_dec_context->width = x_dim; + lavc_dec_context->height = y_dim; + +#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0) + lavc_dec_context->error_resilience = 2; +#else + lavc_dec_context->error_recognition = 2; +#endif + lavc_dec_context->error_concealment = 3; + lavc_dec_context->workaround_bugs = FF_BUG_AUTODETECT; + + if (avcodec_open(lavc_dec_context, lavc_dec_codec) < 0) { + tc_log_error(__FILE__, "Could not initialize the '%s' codec.", + codec->name); + goto decoder_error; + } + + pix_fmt = decode->format; + + frame_size = (x_dim * y_dim * 3)/2; + switch (pix_fmt) + { + case TC_CODEC_YUV420P: + frame_size = (x_dim * y_dim * 3)/2; + break; + + case TC_CODEC_RGB: + frame_size = x_dim * y_dim * 3; + bpp = 24; + + if (yuv2rgb_buffer == NULL) + yuv2rgb_buffer = tc_bufalloc(frame_size); + + if (yuv2rgb_buffer == NULL) + { + tc_log_perror(__FILE__, "out of memory"); + goto decoder_error; + } + else + memset(yuv2rgb_buffer, 0, frame_size); + break; + + case TC_CODEC_RAW: + pass_through = 1; + break; + } + + if(buffer == NULL) buffer=tc_bufalloc(READ_BUFFER_SIZE); + if(buffer == NULL) { + tc_log_perror(__FILE__, "out of memory"); + goto decoder_error; + } + + if(out_buffer == NULL) out_buffer=tc_bufalloc(frame_size); + if(out_buffer == NULL) { + tc_log_perror(__FILE__, "out of memory"); + goto decoder_error; + } + + memset(buffer, 0, READ_BUFFER_SIZE); + memset(out_buffer, 0, frame_size); + + // DECODE MAIN LOOP + + bytes_read = tc_pread(decode->fd_in, (uint8_t*) buffer, READ_BUFFER_SIZE); + + if (bytes_read < 0) { + tc_log_warn(__FILE__, "EOF?"); + goto decoder_error; + } + mp4_ptr = buffer; + mp4_size = bytes_read; + buf_len = 0; + + do { + AVFrame picture; + int got_picture = 0; + + if (buf_len >= mp4_size) { + if (verbose_flag & TC_DEBUG) + tc_log_warn(__FILE__, "EOF?"); + break; + } + + //tc_log_msg(__FILE__, "SIZE: (%d) MP4(%d) blen(%d) BUF(%d) read(%ld)", len, mp4_size, buf_len, READ_BUFFER_SIZE, bytes_read); + do { + AVPacket avpkt; + av_init_packet(&avpkt); + avpkt.data = NULL; + avpkt.size = 0; + len = avcodec_decode_video2(lavc_dec_context, &picture, + &got_picture, &avpkt); + + if (len < 0) { + tc_log_error(__FILE__, "frame decoding failed"); + goto decoder_error; + } + if (verbose_flag & TC_DEBUG) { + tc_log_msg(__FILE__, "here frame pic %d run %d len %d", + got_picture, run, len); + } + if (run++ > 10000) { + tc_log_error(__FILE__, "Fatal decoder error"); + goto decoder_error; + } + } while (!got_picture); + run = 0; + + buf_len += len; + + YUV_INIT_PLANES(planes, out_buffer, IMG_YUV420P, + lavc_dec_context->width, lavc_dec_context->height); + + // Convert avcodec image to the requested YUV or RGB format + switch (lavc_dec_context->pix_fmt) { + case PIX_FMT_YUVJ420P: + case PIX_FMT_YUV420P: + // Remove "dead space" at right edge of planes, if any + if (picture.linesize[0] != lavc_dec_context->width) { + int y; + for (y = 0; y < lavc_dec_context->height; y++) { + ac_memcpy(picture.data[0] + y*lavc_dec_context->width, + picture.data[0] + y*picture.linesize[0], + lavc_dec_context->width); + if (y%2 == 0) { + ac_memcpy(picture.data[1] + y*(lavc_dec_context->width/2), + picture.data[1] + y*picture.linesize[1], + lavc_dec_context->width/2); + ac_memcpy(picture.data[2] + y*(lavc_dec_context->width/2), + picture.data[2] + y*picture.linesize[2], + lavc_dec_context->width/2); + } + } + } + /* FIXME: we can't use tcv_convert here because it assumes + * contiguous planes, which libavcodec might not give us --AC */ + ac_imgconvert(picture.data, IMG_YUV420P, planes, + pix_fmt==TC_CODEC_YUV420P ? IMG_YUV420P : IMG_RGB_DEFAULT, + lavc_dec_context->width, lavc_dec_context->height); + break; + case PIX_FMT_YUV411P: + if (picture.linesize[0] != lavc_dec_context->width) { + int y; + for (y = 0; y < lavc_dec_context->height; y++) { + ac_memcpy(picture.data[0] + y*lavc_dec_context->width, + picture.data[0] + y*picture.linesize[0], + lavc_dec_context->width); + ac_memcpy(picture.data[1] + y*(lavc_dec_context->width/4), + picture.data[1] + y*picture.linesize[1], + lavc_dec_context->width/4); + ac_memcpy(picture.data[2] + y*(lavc_dec_context->width/4), + picture.data[2] + y*picture.linesize[2], + lavc_dec_context->width/4); + } + } + ac_imgconvert(picture.data, IMG_YUV411P, planes, + pix_fmt==TC_CODEC_YUV420P ? IMG_YUV420P : IMG_RGB_DEFAULT, + lavc_dec_context->width, lavc_dec_context->height); + break; + case PIX_FMT_YUVJ422P: + case PIX_FMT_YUV422P: + if (picture.linesize[0] != lavc_dec_context->width) { + int y; + for (y = 0; y < lavc_dec_context->height; y++) { + ac_memcpy(picture.data[0] + y*lavc_dec_context->width, + picture.data[0] + y*picture.linesize[0], + lavc_dec_context->width); + ac_memcpy(picture.data[1] + y*(lavc_dec_context->width/2), + picture.data[1] + y*picture.linesize[1], + lavc_dec_context->width/2); + ac_memcpy(picture.data[2] + y*(lavc_dec_context->width/2), + picture.data[2] + y*picture.linesize[2], + lavc_dec_context->width/2); + } + } + ac_imgconvert(picture.data, IMG_YUV422P, planes, + pix_fmt==TC_CODEC_YUV420P ? IMG_YUV420P : IMG_RGB_DEFAULT, + lavc_dec_context->width, lavc_dec_context->height); + break; + case PIX_FMT_YUVJ444P: + case PIX_FMT_YUV444P: + if (picture.linesize[0] != lavc_dec_context->width) { + int y; + for (y = 0; y < lavc_dec_context->height; y++) { + ac_memcpy(picture.data[0] + y*lavc_dec_context->width, + picture.data[0] + y*picture.linesize[0], + lavc_dec_context->width); + ac_memcpy(picture.data[1] + y*lavc_dec_context->width, + picture.data[1] + y*picture.linesize[1], + lavc_dec_context->width); + ac_memcpy(picture.data[2] + y*lavc_dec_context->width, + picture.data[2] + y*picture.linesize[2], + lavc_dec_context->width); + } + } + ac_imgconvert(picture.data, IMG_YUV444P, planes, + pix_fmt==TC_CODEC_YUV420P ? IMG_YUV420P : IMG_RGB_DEFAULT, + lavc_dec_context->width, lavc_dec_context->height); + break; + default: + tc_log_error(__FILE__, "Unsupported decoded frame format"); + goto decoder_error; + } + + /* buffer more than half empty -> Fill it */ + if (!flush && buf_len > mp4_size/2+1) { + int rest = mp4_size - buf_len; + if (verbose_flag & TC_DEBUG) + tc_log_msg(__FILE__, "FILL rest %d", rest); + + /* Move data if needed */ + if (rest) + memmove(buffer, buffer+buf_len, READ_BUFFER_SIZE-buf_len); + + /* read new data */ + if ( (bytes_read = tc_pread(decode->fd_in, (uint8_t*) (buffer+(READ_BUFFER_SIZE-buf_len)), buf_len) ) != buf_len) { + if (verbose_flag & TC_DEBUG) + tc_log_msg(__FILE__, "read failed read (%ld) should (%d)", bytes_read, buf_len); + flush = 1; + mp4_size -= buf_len; + mp4_size += bytes_read; + } + buf_len = 0; + } + //tc_log_msg(__FILE__, "SIZE: (%d) MP4(%d) blen(%d) BUF(%d) read(%ld)", len, mp4_size, buf_len, READ_BUFFER_SIZE, bytes_read); + if (mp4_size<=0) { + + if (verbose_flag & TC_DEBUG) + tc_log_msg(__FILE__, "no more bytes"); + break; + } + + if (tc_pwrite(decode->fd_out, out_buffer, frame_size) != frame_size) { + goto decoder_error; + } + + } while (1); + + import_exit(0); + return; + +decoder_error: + import_exit(1); +} + + +#else /* HAVE_FFMPEG */ + +void decode_lavc(decode_t *decode) +{ + tc_log_error(__FILE__, "No support for FFmpeg configured -- exiting"); + import_exit(1); +} + + +#endif /* HAVE_FFMPEG */ + +/*************************************************************************/ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ + |
