OSDN Git Service

git-svn-id: svn://localhost/HandBrake/trunk@590 b64f7644-9d1e-0410-96f1-a4d463321fa5
[handbrake-jp/handbrake-jp-git.git] / libhb / decavcodec.c
1 /* $Id: decavcodec.c,v 1.6 2005/03/06 04:08:54 titer Exp $
2
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. */
6
7 #include "hb.h"
8
9 #include "ffmpeg/avcodec.h"
10
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 * );
14
15 hb_work_object_t hb_decavcodec =
16 {
17     WORK_DECAVCODEC,
18     "MPGA decoder (libavcodec)",
19     decavcodecInit,
20     decavcodecWork,
21     decavcodecClose
22 };
23
24 struct hb_work_private_s
25 {
26     hb_job_t       * job;
27
28     AVCodecContext * context;
29     int64_t          pts_last;
30     AVCodecParserContext *parser;
31 };
32
33
34 /***********************************************************************
35  * hb_work_decavcodec_init
36  ***********************************************************************
37  *
38  **********************************************************************/
39 int decavcodecInit( hb_work_object_t * w, hb_job_t * job )
40 {
41     AVCodec * codec;
42     
43     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
44     w->private_data = pv;
45
46     pv->job   = job;
47     
48     codec = avcodec_find_decoder( CODEC_ID_MP2 );
49     pv->parser = av_parser_init(CODEC_ID_MP2);
50     
51     pv->context = avcodec_alloc_context();
52     avcodec_open( pv->context, codec );
53     pv->pts_last = -1;
54
55     return 0;
56 }
57
58 /***********************************************************************
59  * Close
60  ***********************************************************************
61  *
62  **********************************************************************/
63 void decavcodecClose( hb_work_object_t * w )
64 {
65     hb_work_private_t * pv = w->private_data;
66     av_parser_close(pv->parser);
67     avcodec_close( pv->context );
68 }
69
70 /***********************************************************************
71  * Work
72  ***********************************************************************
73  *
74  **********************************************************************/
75 int decavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
76                     hb_buffer_t ** buf_out )
77 {
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;
85     
86     *buf_out = NULL;
87
88     if( in->start < 0 ||
89         ( pv->pts_last > 0 &&
90           in->start > pv->pts_last &&
91           in->start - pv->pts_last < 5000 ) ) /* Hacky */
92     {
93         cur = pv->pts_last;
94     }
95     else
96     {
97         cur = in->start;
98     }
99
100     pos = 0;
101     while( pos < in->size )
102     {
103         len = av_parser_parse(pv->parser, pv->context,&parser_output_buffer,&parser_output_buffer_len,in->data + pos,in->size - pos,cur,cur);
104         
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 )
111         {
112             short * s16;
113             float * fl32;
114
115             buf = hb_buffer_init( 2 * out_size );
116
117             int sample_size_in_bytes = 2;   // Default to 2 bytes
118             switch (pv->context->sample_fmt)
119             {
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;
128             }
129             
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;
134
135             s16  = buffer;
136             fl32 = (float *) buf->data;
137             for( i = 0; i < out_size / 2; i++ )
138             {
139                 fl32[i] = s16[i];
140             }
141
142             if( last )
143             {
144                 last = last->next = buf;
145             }
146             else
147             {
148                 *buf_out = last = buf;
149             }
150         }
151
152         pos += len;
153     }
154
155     pv->pts_last = cur;
156
157     return HB_WORK_OK;
158 }
159