OSDN Git Service

Fixed dvd_seek for titles which are not linear
[handbrake-jp/handbrake-jp-git.git] / libhb / declpcm.c
1 /* $Id: declpcm.c,v 1.8 2005/11/04 14:44:01 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 struct hb_work_object_s
10 {
11     HB_WORK_COMMON;
12
13     hb_job_t    * job;
14     hb_audio_t  * audio;
15
16     int64_t       pts_last;
17 };
18
19 static int Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
20                  hb_buffer_t ** buf_out )
21 {
22     hb_buffer_t * in = *buf_in, * out;
23     int samplerate = 0;
24     int count;
25     uint8_t * samples_u8;
26     float   * samples_fl32;
27     int i;
28     uint64_t duration;
29
30     *buf_out = NULL;
31
32     if( in->data[5] != 0x80 )
33     {
34         hb_log( "no LPCM frame sync (%02x)", in->data[5] );
35         return HB_WORK_OK;
36     }
37
38     switch( ( in->data[4] >> 4 ) & 0x3 )
39     {
40         case 0:
41             samplerate = 48000;
42             break;
43         case 1:
44             samplerate = 96000;//32000; /* FIXME vlc says it is 96000 */
45             break;
46         case 2:
47             samplerate = 44100;
48             break;
49         case 3:
50             samplerate = 32000;
51             break;
52     }
53
54     count      = ( in->size - 6 ) / 2;
55     out        = hb_buffer_init( count * sizeof( float ) );
56     duration   = count * 90000 / samplerate / 2;
57     if( w->pts_last > 0 &&
58         in->start < w->pts_last + duration / 6 &&
59         in->start > w->pts_last - duration / 6 )
60     {
61         /* Workaround for DVDs where dates aren't exact */
62         out->start = w->pts_last;
63     }
64     else
65     {
66         out->start = in->start;
67     }
68     out->stop   = out->start + duration;
69     w->pts_last = out->stop;
70
71     samples_u8   = in->data + 6;
72     samples_fl32 = (float *) out->data;
73
74     /* Big endian int16 -> float conversion */
75     for( i = 0; i < count; i++ )
76     {
77 #ifdef WORDS_BIGENDIAN
78         samples_fl32[0] = *( (int16_t *) samples_u8 );
79 #else
80         samples_fl32[0] = (int16_t) ( ( samples_u8[0] << 8 ) | samples_u8[1] );
81 #endif
82         samples_u8   += 2;
83         samples_fl32 += 1;
84     }
85
86     *buf_out = out;
87
88     return HB_WORK_OK;
89 }
90
91 static void Close( hb_work_object_t ** _w )
92 {
93     hb_work_object_t * w = *_w;
94     free( w->name );
95     free( w );
96     *_w = NULL;
97 }
98
99 hb_work_object_t * hb_work_declpcm_init( hb_job_t * job, hb_audio_t * audio )
100 {
101     hb_work_object_t * w = calloc( sizeof( hb_work_object_t ), 1 );
102     w->name  = strdup( "LPCM decoder" );
103     w->work  = Work;
104     w->close = Close;
105
106     w->job   = job;
107     w->audio = audio;
108
109     w->pts_last = -1;
110
111     return w;
112 }
113