version update
[goodguy/cinelerra.git] / cinelerra-5.1 / libzmpeg3 / vtrack.C
1 #include "libzmpeg3.h"
2
3 zvtrack_t::
4 vtrack_t(zmpeg3_t *zsrc, int custom_id, demuxer_t *demux, int no)
5 {
6   demuxer = new demuxer_t(zsrc, 0, this, custom_id);
7   frame_cache = new cache_t();
8   if( zsrc->seekable ) {
9     demux->copy_titles(demuxer);
10   }
11
12   current_position = 0;
13   number = no;
14   pid = custom_id;
15   pts_origin = -1.;
16   reset_pts();
17
18 // Copy pointers
19   if( zsrc->frame_offsets ) {
20     frame_offsets = zsrc->frame_offsets[number];
21     total_frame_offsets = zsrc->total_frame_offsets[number];
22     keyframe_numbers = zsrc->keyframe_numbers[number];
23     total_keyframe_numbers = zsrc->total_keyframe_numbers[number];
24     demuxer->stream_end = zsrc->video_eof[number];
25   }
26 }
27
28 zvtrack_t *zmpeg3_t::
29 new_vtrack_t(int custom_id, demuxer_t *demux, int number)
30 {
31   vtrack_t *new_vtrack = new vtrack_t(this,custom_id,demux,number);
32
33 /* Get information about the track here. */
34   new_vtrack->video = new_video_t(new_vtrack);
35
36   if( !new_vtrack->video ) { /* Failed */
37     delete new_vtrack;
38     new_vtrack = 0;
39   }
40
41   return new_vtrack;
42 }
43
44 zvtrack_t::
45 ~vtrack_t()
46 {
47   if( video ) delete video;
48   if( demuxer ) delete demuxer;
49   if( private_offsets ) {
50     if( frame_offsets_allocated ) delete [] frame_offsets;
51     if( keyframe_numbers_allocated ) delete [] keyframe_numbers;
52   }
53   delete frame_cache;
54 }
55
56 void zvtrack_t::
57 extend_frame_offsets()
58 {
59   if( frame_offsets_allocated <= total_frame_offsets ) {
60     long new_allocation = ZMAX(2*total_frame_offsets, 1024);
61     int64_t *new_offsets = new int64_t[new_allocation];
62     for( int i=0; i<total_frame_offsets; ++i )
63       new_offsets[i] = frame_offsets[i];
64     delete [] frame_offsets;
65     frame_offsets = new_offsets;
66     frame_offsets_allocated = new_allocation;
67   }
68 }
69
70 void zvtrack_t::
71 extend_keyframe_numbers()
72 {
73   if( keyframe_numbers_allocated <= total_keyframe_numbers ) {
74     long new_allocation = ZMAX(2*total_keyframe_numbers, 1024);
75     int *new_numbers = new int[new_allocation];
76     for( int i=0; i<total_keyframe_numbers; ++i )
77       new_numbers[i] = keyframe_numbers[i];
78     delete [] keyframe_numbers;
79     keyframe_numbers = new_numbers;
80     keyframe_numbers_allocated = new_allocation;
81   }
82 }
83
84 void zvtrack_t::
85 append_frame(int64_t offset, int is_keyframe)
86 {
87   extend_frame_offsets();
88   frame_offsets[total_frame_offsets] = offset;
89
90   if( is_keyframe || total_frame_offsets == 0 ) {
91     extend_keyframe_numbers();
92     keyframe_numbers[total_keyframe_numbers++] = total_frame_offsets;
93   }
94
95   ++total_frame_offsets;
96   private_offsets = 1;
97 }
98
99 int zvtrack_t::
100 find_keyframe_index(int64_t frame)
101 {
102   /* l,r boundarys are exclusive (not included) */
103   int l = -1;
104   int r = total_keyframe_numbers;
105   while( (r-l) > 1 ) {
106     int m = (r+l) >> 1;
107     int mframe = keyframe_numbers[m];
108     if( frame == mframe ) return m;
109     if( frame > mframe ) l = m;
110     else r = m;
111   }
112   return l;
113 }
114
115 void zvtrack_t::update_video_time()
116 {
117   double pts = frame_pts;
118   if( video->is_refframe() ) {
119     pts = refframe_pts;
120     refframe_pts = frame_pts;
121   }
122   frame_pts = -1.;
123   if( pts < 0 ) return;
124   if( pts_starttime < 0 && frame_rate > 0 ) {
125     pts_starttime = pts;
126     pts_offset = (double)video->framenum / frame_rate;
127     if( pts_origin < 0. ) pts_origin = pts_starttime - pts_offset;
128   }
129   else if( pts < pts_starttime ) { // check for pts rollover
130     if( pts_starttime-pts > 0x100000000ll / 90000 )
131       pts += 0x200000000ll / 90000;
132   }
133   /* update track time */
134   double vtime = pts_video_time(pts);
135   if( vtime > video_time ) {
136     video_time = vtime;
137     pts_position = video->framenum;
138 //zmsgs("track %02x video_time=%f\n",track->pid, vtime);
139   }
140 }
141
142 double zvtrack_t::get_video_time()
143 {
144   double vtime = video_time; 
145   if( vtime >= 0 && frame_rate > 0 ) {
146     vtime += (video->framenum - pts_position) / frame_rate;
147   }
148   return vtime;
149 }
150
151 void zvtrack_t::
152 reset_pts()
153 {
154   vskip = 0;
155   demuxer->pes_video_time = -1.;
156   pts_starttime = demuxer->src->pts_padding >= 0 ? -1. : 0.;
157   video_time = -1.;
158   refframe_pts = -1.;
159   frame_pts = -1.;
160   pts_position = 0;
161   pts_offset = 0;
162 }
163
164 int zvtrack_t::apparent_position()
165 {
166   if( !frame_offsets ) return 0;
167   int64_t pos = demuxer->absolute_position();
168   int l = -1;
169   int r = total_frame_offsets;
170   while( (r-l) > 1 ) {
171     int m = (r+l) >> 1;
172     int64_t mpos = frame_offsets[m];
173     if( pos == mpos ) return m;
174     if( pos > mpos ) l = m;
175     else r = m;
176   }   
177   return l;
178 }
179