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_MPEGMUXER_H
22 #define _DVBCUT_MPEGMUXER_H
23 
24 #define MINPACKSIZE 64
25 #define DTSMAXDELAY 90000
26 
27 #include <list>
28 #include "defines.h"
29 #include "muxer.h"
30 #include "mpgfile.h"
31 
32 typedef int64_t scr_t;
33 #define pts2scr(x) (((scr_t)(x))*300)
34 #define scr2pts(x) ((pts_t)((x)/300))
35 
36 /**
37 @author Sven Over
38 */
39 class mpegmuxer : public muxer
40   {
41 public:
42   class bufferremoval
43     {
44     scr_t _scr;
45     int _bytes;
46   public:
bufferremoval(scr_t scr,int bytes)47     bufferremoval(scr_t scr, int bytes) : _scr(scr),_bytes(bytes)
48       {}
bytes()49     int bytes()
50       {
51       return _bytes;
52       }
scr()53     scr_t scr()
54       {
55       return _scr;
56       }
57     };
58 
59   class au
60     {
61   protected:
62     void *data;
63     int size;
64     pts_t pts,dts;
65     int flags;
66     int pos;
67   public:
68     au(const void *_data,int _size, pts_t _pts, pts_t _dts, int _flags);
69     ~au();
getdata()70     const void *getdata() const
71       {
72       return data;
73       }
getdata()74     void *getdata()
75       {
76       return (void*)((char*)data+pos);
77       }
getsize()78     int getsize()
79       {
80       return size-pos;
81       }
incomplete()82     bool incomplete()
83       {
84       return pos;
85       }
getpos()86     int getpos()
87       {
88       return pos;
89       }
addpos(int p)90     void addpos(int p)
91       {
92       pos+=p;
93       if (pos>size)
94         pos=size;
95       }
getpts()96     pts_t getpts()
97       {
98       return pts;
99       }
getdts()100     pts_t getdts()
101       {
102       return dts;
103       }
getflags()104     int getflags()
105       {
106       return flags;
107       }
addflags(int fl)108     void addflags(int fl)
109       {
110       flags|=fl;
111       }
unsetflags(int fl)112     void unsetflags(int fl)
113       {
114       flags &= ~fl;
115       }
116     };
117 
118   class pack
119     {
120   protected:
121     void *data;
122     int size;
123     scr_t minscr,maxscr;
124     pts_t dts;
125     int payloadpos;
126     int payloadlen;
127     int aupayloadlen;
128     friend class mpegmuxer;
129 
130   public:
131     pack(int packsize, int payloadsize, int muxrate, pts_t _dts);
132     ~pack();
133 
getdata()134     const void *getdata() const
135       {
136       return data;
137       }
getsize()138     int getsize() const
139       {
140       return size;
141       }
getpayload()142     void *getpayload()
143       {
144       return (void*)((char*)data+payloadpos);
145       }
getpayloadlen()146     int getpayloadlen() const
147       {
148       return payloadlen;
149       }
addaupayload(int p)150     void addaupayload(int p)
151       {
152       aupayloadlen+=p;
153       }
getaupayloadlen()154     int getaupayloadlen() const
155       {
156       return aupayloadlen;
157       }
158     void setscr(scr_t scr);
setlastdts(pts_t dts)159     void setlastdts(pts_t dts)
160       {
161       setminscr(pts2scr(dts-DTSMAXDELAY));
162       }
setminscr(scr_t scr)163     void setminscr(scr_t scr)
164       {
165       if (scr>minscr)
166 	minscr=scr;
167       }
setmaxscr(scr_t scr)168     void setmaxscr(scr_t scr)
169       {
170       if (scr<maxscr)
171         maxscr=scr;
172       }
getminscr()173     scr_t getminscr() const
174       {
175       return minscr;
176       }
getmaxscr()177     scr_t getmaxscr() const
178       {
179       return maxscr;
180       }
getdts()181     pts_t getdts() const
182       {
183       return dts;
184       }
nopayload()185     void nopayload()
186       {
187       payloadlen=0;
188       }
189 
maxpayload(int packsize)190     static int maxpayload(int packsize)
191       {
192       return packsize-14;
193       }
194 
195     bool operator<(const pack &p)
196       {
197       return maxscr<p.maxscr;
198       }
199 
200     bool write(int fd);
201     };
202 
203   class stream
204     {
205   protected:
206     std::list<au*> aulist;
207     std::list<pack*> packlist;
208     std::list<bufferremoval> bufferremovals;
209     streamtype::type type;
210     int id;
211     int bufsize;
212     int filllevel;
213     int packet;
214     uint32_t startcode;
215     uint16_t pstdbuffer;
216     friend class mpegmuxer;
217 
218   public:
219     stream(streamtype::type _type, int _id, int _bufsize, int _pstdbuffer, bool bufferscale=true) :
type(_type)220         type(_type), id(_id&0x3ff), bufsize(_bufsize), filllevel(0), packet(0)
221       {
222       if (bufferscale)
223         pstdbuffer=htom16(0x6000|((_pstdbuffer/1024)&0x1fff));
224       else
225         pstdbuffer=htom16(0x4000|((_pstdbuffer/128)&0x1fff));
226 
227       if ( (id&~0xff)==0x100 )
228         startcode=mbo32(0x1bd);
229       else if ( (id&~0xff)==0x200 )
230         startcode=mbo32(0x1bf);
231       else
232         startcode=htom32(0x100|id);
233       }
~stream()234     ~stream()
235       {
236       for(std::list<au*>::iterator it=aulist.begin();it!=aulist.end();++it)
237         delete *it;
238       for(std::list<pack*>::iterator it=packlist.begin();it!=packlist.end();++it)
239         delete *it;
240       }
getbufsize()241     int getbufsize() const
242       {
243       return bufsize;
244       }
getbuffree()245     int getbuffree() const
246       {
247       return bufsize-filllevel;
248       }
getstartcode()249     uint32_t getstartcode() const
250       {
251       return startcode;
252       }
getpstdbuffer()253     uint16_t getpstdbuffer() const
254       {
255       return pstdbuffer;
256       }
getid()257     int getid() const
258       {
259       return id;
260       }
fill(int bytes)261     void fill(int bytes)
262       {
263       filllevel+=bytes;
264       }
unfill(int bytes)265     void unfill(int bytes)
266       {
267       filllevel-=bytes;
268       if (filllevel<0)
269         filllevel=0;
270       }
zerofill()271     void zerofill()
272       {
273       filllevel=0;
274       }
getfill()275     int getfill() const
276       {
277       return filllevel;
278       }
279     bool operator<(const stream &s) const
280       {
281       if (packlist.empty())
282         return false;
283       if (s.packlist.empty())
284         return true;
285       return packlist.front()->getmaxscr()<s.packlist.front()->getmaxscr();
286       }
287     bool operator<(const scr_t &s) const
288       {
289       if (packlist.empty())
290         return false;
291       return packlist.front()->getmaxscr()<s;
292       }
293     };
294 
295 protected:
296   int fd;
297   stream *st[MAXAVSTREAMS];
298   int muxrate;
299   int packsize;
300   pts_t ptsoffset;
301   int aucounter;
302   void *systemhdr;
303   int systemhdrlen;
304   bool pespacket_setlength;
305   scr_t scr;
306   int scrpack;
307 
308   bool flush(bool flushall);
309   void packetizer(int str, pts_t maxdts);
310 
311 public:
312   mpegmuxer(uint32_t audiostreammask, mpgfile &mpg, const char *filename, bool dvdnavpackets=true, int packsize_bytes=2048, int muxrate_bitsps=10080000);
313   ~mpegmuxer();
314 
315   virtual bool putpacket(int str, const void *data, int len, pts_t pts, pts_t dts, uint32_t flags=0);
ready()316   virtual bool ready()
317     {
318     return fd>=0;
319     }
finish()320   virtual void finish()
321     {
322     flush(true);
323     }
324   };
325 
326 #endif
327 
328