1 /*  dvbcut
2     Copyright (c) 2005 Sven Over <svenover@svenover.de>
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18 
19 /* $Id$ */
20 
21 #ifndef _DVBCUT_STREAMDATA_H
22 #define _DVBCUT_STREAMDATA_H
23 
24 #include <string>
25 #include <list>
26 extern "C" {
27 #include <libavformat/avformat.h>
28 }
29 
30 #include "port.h"
31 #include "tsfile.h"
32 #include "psfile.h"
33 #include "buffer.h"
34 #include "types.h"
35 #include "pts.h"
36 
37 /* obsolete, do not use --mr
38 #define STREAM_ITEM_FLAG_DATA_ALIGNMENT_INDICATOR (1<<0)
39 */
40 #define STREAM_ITEM_FLAG_HAS_PTS                  (1<<1)
41 #define STREAM_ITEM_FLAG_FRAME                    (1<<2)
42 
43 /**
44 @author Sven Over
45 */
46 class streamdata
47   {
48 public:
49   struct item
50     {
51     filepos_t fileposition;
52 
53     uint32_t bufferposition;
54     uint32_t flags;
55     pts_t pts;
56 
itemitem57     item(filepos_t fp, uint32_t fl, pts_t p, uint32_t bp) : fileposition(fp), bufferposition(bp), flags(fl), pts(p)
58       {
59       if (!(flags&STREAM_ITEM_FLAG_HAS_PTS))
60         pts=(pts_t)AV_NOPTS_VALUE;
61       }
~itemitem62     ~item()
63     {}
64 
setptsitem65     void setpts(pts_t p)
66       {
67       if (p!=(pts_t)AV_NOPTS_VALUE)
68         flags |= STREAM_ITEM_FLAG_HAS_PTS;
69       else
70         flags &=~ STREAM_ITEM_FLAG_HAS_PTS;
71       pts=p;
72       }
headerhasptsitem73     bool headerhaspts() const
74       {
75       return flags & STREAM_ITEM_FLAG_HAS_PTS;
76       }
headerptsitem77     pts_t headerpts() const
78       {
79       return pts;
80       }
headerptsitem81     pts_t headerpts(pts_t reference) const
82       {
83       if (flags & STREAM_ITEM_FLAG_HAS_PTS)
84         return ptsreference(pts,reference);
85       return AV_NOPTS_VALUE;
86       }
clearptsitem87     void clearpts()
88       {
89       flags &=~ STREAM_ITEM_FLAG_HAS_PTS;
90       pts=AV_NOPTS_VALUE;
91       }
is_frameitem92     bool is_frame() const
93       {
94       return flags & STREAM_ITEM_FLAG_FRAME;
95       }
96     }
97   ;
98   typedef std::list<item> itemlisttype;
99 
100 protected:
101   itemlisttype items;
102   unsigned int itemlistsize;
103   buffer data;
104   uint32_t offset;
105   std::string header;
106   filepos_t curpos;
107   const streamtype::type type;
108   bool transportstream;
109   dvbcut_off_t nextfilepos;
110 
111 public:
112   streamdata(streamtype::type t, bool transport_stream, uint32_t buffersize=256<<10) :
113       itemlistsize(0), data(buffersize), offset(0), curpos(0), type(t), transportstream(transport_stream)
114   {}
~streamdata()115   ~streamdata()
116     {}
117 
itemlist()118   const std::list<item> &itemlist() const
119     {
120     return items;
121     }
empty()122   bool empty() const
123     {
124     return items.empty();
125     }
pop()126   void pop()
127     {
128     items.pop_front();
129     --itemlistsize;
130     if (items.empty()) {
131       itemlistsize=0; // ...should be redundant
132       offset=0;
133       curpos+=data.inbytes();
134       data.clear();
135       } else {
136       data.discard(items.front().bufferposition-offset);
137       offset=items.front().bufferposition;
138       curpos=items.front().fileposition;
139       if (offset & (1ul<<31)) {
140         for(std::list<item>::iterator it=items.begin();it!=items.end();++it)
141           it->bufferposition-=offset;
142         offset=0;
143         }
144       }
145     }
pop(unsigned int number)146   void pop(unsigned int number)
147     {
148     if (number==0)
149       return;
150     if (number>=itemlistsize) {
151       itemlistsize=0;
152       offset=0;
153       curpos+=data.inbytes();
154       data.clear();
155       return;
156       }
157 
158     --number;
159     for (unsigned int i=0;i<number;++i)
160       items.pop_front();
161     itemlistsize-=number;
162 
163     pop();
164     }
discard(uint32_t bytes)165   void discard(uint32_t bytes)
166     {
167     if (bytes==0)
168       return;
169     if (bytes>=data.inbytes()) {
170       curpos+=data.inbytes();
171       data.clear();
172       items.clear();
173       itemlistsize=0;
174       offset=0;
175       return;
176       }
177     data.discard(bytes);
178     offset+=bytes;
179     curpos+=bytes;
180     if (items.empty())
181       return;
182     std::list<item>::iterator it=items.begin();
183     std::list<item>::iterator nx=it;
184     ++nx;
185     while(nx!=items.end()) {
186       if (nx->bufferposition>offset)
187         break;
188       ++nx;
189       it=items.erase(it);
190       --itemlistsize;
191       }
192     if (it->bufferposition<offset) {
193       it->fileposition += offset-it->bufferposition;
194       it->bufferposition=offset;
195       }
196     curpos=items.front().fileposition;
197     if (offset & (1ul<<31)) {
198       for(std::list<item>::iterator it=items.begin();it!=items.end();++it)
199 	it->bufferposition-=offset;
200       offset=0;
201       }
202     }
append(const void * d,int s)203   void append(const void *d, int s)
204     {
205     data.putdata(d,s,true);
206     }
207   void appenditem(filepos_t fp, const std::string &header, const void *d, int s);
appenditem(filepos_t fp,int flags,pts_t pts,const void * d,int s)208   void appenditem(filepos_t fp, int flags, pts_t pts, const void *d, int s)
209     {
210     if (items.empty())
211       curpos=fp;
212     items.push_back(item(fp,flags,pts,offset+data.inbytes()));
213     ++itemlistsize;
214     data.putdata(d,s,true);
215     }
getdata()216   const void *getdata() const
217     {
218     return data.data();
219     }
getdata()220   void *getdata()
221     {
222     return data.data();
223     }
getdata(uint32_t bufferpos)224   const void *getdata(uint32_t bufferpos) const
225     {
226     return (char*)data.data()+(bufferpos-offset);
227     }
getdata(uint32_t bufferpos)228   void *getdata(uint32_t bufferpos)
229     {
230     return (char*)data.data()+(bufferpos-offset);
231     }
getbuffer()232   const buffer &getbuffer() const
233     {
234     return data;
235     }
getoffset()236   uint32_t getoffset() const
237     {
238     return offset;
239     }
inbytes()240   unsigned int inbytes() const
241     {
242     return data.inbytes();
243     }
discardheader()244   void discardheader()
245     {
246     if (!items.empty())
247       items.front().clearpts();
248     }
getcurpos()249   const filepos_t &getcurpos() const
250     {
251     return curpos;
252     }
getitemlistsize()253   unsigned int getitemlistsize() const
254     {
255     return itemlistsize;
256     }
257   void audio_addpts(uint32_t startbufferpos=0, bool onepacket=false);
258   uint32_t ptsbufferpos(pts_t pts);
259   uint32_t closestptsbufferpos(pts_t pts);
fileposbufferpos(filepos_t pos)260   uint32_t fileposbufferpos(filepos_t pos)
261     {
262     for (itemlisttype::iterator it=items.begin();it!=items.end();++it)
263       if (it->fileposition.packetposition() > pos.packetposition())
264         return it->bufferposition;
265       else if (it->fileposition.packetposition() == pos.packetposition())
266         return it->bufferposition+(pos.packetoffset()-it->fileposition.packetoffset());
267     return offset+inbytes();
268     }
filepositem(filepos_t pos)269   const item &filepositem(filepos_t pos)
270     {
271     for (itemlisttype::iterator it=items.begin();it!=items.end();++it)
272       if (it->fileposition.packetposition() >= pos.packetposition())
273         return *it;
274     return items.back();
275     }
bufferpositem(uint32_t bpos)276   const item &bufferpositem(uint32_t bpos) const
277     {
278     const item *i=&items.front();
279     for (itemlisttype::const_iterator it=++items.begin();it!=items.end();++it)
280       if (it->bufferposition > bpos)
281         break;
282       else
283         i=&(*it);
284     return *i;
285     }
286 
287   friend int tsfile::streamreader(streamhandle &s);
288   friend int psfile::streamreader(streamhandle &s);
289   };
290 
291 #endif
292