Refer to transitions in the presence-or-lack-thereof of progressive flags on MPEG...
[HandBrake.git] / libhb / decavcodec.c
blob4301f43db1da8fc78ee41d701e7c3c5dbe730fc6
1 /* $Id: decavcodec.c,v 1.6 2005/03/06 04:08:54 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.m0k.org/>.
5 It may be used under the terms of the GNU General Public License. */
7 #include "hb.h"
9 #include "ffmpeg/avcodec.h"
11 int decavcodecInit( hb_work_object_t *, hb_job_t * );
12 int decavcodecWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
13 void decavcodecClose( hb_work_object_t * );
15 hb_work_object_t hb_decavcodec =
17 WORK_DECAVCODEC,
18 "MPGA decoder (libavcodec)",
19 decavcodecInit,
20 decavcodecWork,
21 decavcodecClose
24 struct hb_work_private_s
26 hb_job_t * job;
28 AVCodecContext * context;
29 int64_t pts_last;
30 AVCodecParserContext *parser;
34 /***********************************************************************
35 * hb_work_decavcodec_init
36 ***********************************************************************
38 **********************************************************************/
39 int decavcodecInit( hb_work_object_t * w, hb_job_t * job )
41 AVCodec * codec;
43 hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
44 w->private_data = pv;
46 pv->job = job;
48 codec = avcodec_find_decoder( CODEC_ID_MP2 );
49 pv->parser = av_parser_init(CODEC_ID_MP2);
51 pv->context = avcodec_alloc_context();
52 avcodec_open( pv->context, codec );
53 pv->pts_last = -1;
55 return 0;
58 /***********************************************************************
59 * Close
60 ***********************************************************************
62 **********************************************************************/
63 void decavcodecClose( hb_work_object_t * w )
65 hb_work_private_t * pv = w->private_data;
66 av_parser_close(pv->parser);
67 avcodec_close( pv->context );
70 /***********************************************************************
71 * Work
72 ***********************************************************************
74 **********************************************************************/
75 int decavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
76 hb_buffer_t ** buf_out )
78 hb_work_private_t * pv = w->private_data;
79 hb_buffer_t * in = *buf_in, * buf, * last = NULL;
80 int pos, len, out_size, i, uncompressed_len;
81 short buffer[AVCODEC_MAX_AUDIO_FRAME_SIZE];
82 uint64_t cur;
83 unsigned char *parser_output_buffer;
84 int parser_output_buffer_len;
86 *buf_out = NULL;
88 if( in->start < 0 ||
89 ( pv->pts_last > 0 &&
90 in->start > pv->pts_last &&
91 in->start - pv->pts_last < 5000 ) ) /* Hacky */
93 cur = pv->pts_last;
95 else
97 cur = in->start;
100 pos = 0;
101 while( pos < in->size )
103 len = av_parser_parse(pv->parser, pv->context,&parser_output_buffer,&parser_output_buffer_len,in->data + pos,in->size - pos,cur,cur);
105 out_size = 0;
106 uncompressed_len = 0;
107 if (parser_output_buffer_len)
108 uncompressed_len = avcodec_decode_audio( pv->context, buffer, &out_size,
109 parser_output_buffer, parser_output_buffer_len );
110 if( out_size )
112 short * s16;
113 float * fl32;
115 buf = hb_buffer_init( 2 * out_size );
117 int sample_size_in_bytes = 2; // Default to 2 bytes
118 switch (pv->context->sample_fmt)
120 case SAMPLE_FMT_S16:
121 sample_size_in_bytes = 2;
122 break;
123 /* We should handle other formats here - but that needs additional format conversion work below */
124 /* For now we'll just report the error and try to carry on */
125 default:
126 hb_log("decavcodecWork - Unknown Sample Format from avcodec_decode_audio (%d) !", pv->context->sample_fmt);
127 break;
130 buf->start = cur;
131 buf->stop = cur + 90000 * ( out_size / (sample_size_in_bytes * pv->context->channels) ) /
132 pv->context->sample_rate;
133 cur = buf->stop;
135 s16 = buffer;
136 fl32 = (float *) buf->data;
137 for( i = 0; i < out_size / 2; i++ )
139 fl32[i] = s16[i];
142 if( last )
144 last = last->next = buf;
146 else
148 *buf_out = last = buf;
152 pos += len;
155 pv->pts_last = cur;
157 return HB_WORK_OK;