/* dvbcut Copyright (c) 2005 Sven Over This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _DVBCUT_STREAMDATA_H #define _DVBCUT_STREAMDATA_H #include #include extern "C" { #include } #include "port.h" #include "tsfile.h" #include "psfile.h" #include "buffer.h" #include "types.h" #include "pts.h" #define STREAM_ITEM_FLAG_DATA_ALIGNMENT_INDICATOR (1<<0) #define STREAM_ITEM_FLAG_HAS_PTS (1<<1) /** @author Sven Over */ class streamdata { public: struct item { filepos_t fileposition; uint32_t bufferposition; uint32_t flags; pts_t pts; item(filepos_t fp, uint32_t fl, pts_t p, uint32_t bp) : fileposition(fp), bufferposition(bp), flags(fl), pts(p) { if (!(flags&STREAM_ITEM_FLAG_HAS_PTS)) pts=(pts_t)AV_NOPTS_VALUE; } ~item() {} void setpts(pts_t p) { if (p!=(pts_t)AV_NOPTS_VALUE) flags |= STREAM_ITEM_FLAG_HAS_PTS; else flags &=~ STREAM_ITEM_FLAG_HAS_PTS; pts=p; } bool headerhaspts() const { return flags & STREAM_ITEM_FLAG_HAS_PTS; } pts_t headerpts() const { return pts; } pts_t headerpts(pts_t reference) const { if (flags & STREAM_ITEM_FLAG_HAS_PTS) return ptsreference(pts,reference); return AV_NOPTS_VALUE; } void clearpts() { flags &=~ STREAM_ITEM_FLAG_HAS_PTS; pts=AV_NOPTS_VALUE; } bool data_alignment_indicator() const { return flags & STREAM_ITEM_FLAG_DATA_ALIGNMENT_INDICATOR; } void setdata_alignment_indicator(bool set =true) { if (set ) flags |= STREAM_ITEM_FLAG_DATA_ALIGNMENT_INDICATOR; else flags &=~ STREAM_ITEM_FLAG_DATA_ALIGNMENT_INDICATOR; } } ; typedef std::list itemlisttype; protected: itemlisttype items; unsigned int itemlistsize; buffer data; uint32_t offset; std::string header; filepos_t curpos; const streamtype::type type; bool transportstream; dvbcut_off_t nextfilepos; public: streamdata(streamtype::type t, bool transport_stream, uint32_t buffersize=256<<10) : itemlistsize(0), data(buffersize), offset(0), curpos(0), type(t), transportstream(transport_stream) {} ~streamdata() {} const std::list &itemlist() const { return items; } bool empty() const { return items.empty(); } void pop() { items.pop_front(); --itemlistsize; if (items.empty()) { itemlistsize=0; // ...should be redundant offset=0; curpos+=data.inbytes(); data.clear(); } else { data.discard(items.front().bufferposition-offset); offset=items.front().bufferposition; curpos=items.front().fileposition; if (offset & (1ul<<31)) { for(std::list::iterator it=items.begin();it!=items.end();++it) it->bufferposition-=offset; offset=0; } } } void pop(unsigned int number) { if (number==0) return; if (number>=itemlistsize) { itemlistsize=0; offset=0; curpos+=data.inbytes(); data.clear(); return; } --number; for (unsigned int i=0;i=data.inbytes()) { curpos+=data.inbytes(); data.clear(); items.clear(); itemlistsize=0; offset=0; return; } data.discard(bytes); offset+=bytes; curpos+=bytes; if (items.empty()) return; std::list::iterator it=items.begin(); std::list::iterator nx=it; ++nx; while(nx!=items.end()) { if (nx->bufferposition>offset) break; ++nx; it=items.erase(it); --itemlistsize; } if (it->bufferpositionfileposition += offset-it->bufferposition; it->bufferposition=offset; } curpos=items.front().fileposition; if (offset & (1ul<<31)) { for(std::list::iterator it=items.begin();it!=items.end();++it) it->bufferposition-=offset; offset=0; } } void append(const void *d, int s) { data.putdata(d,s,true); } void appenditem(filepos_t fp, const std::string &header, const void *d, int s); void appenditem(filepos_t fp, int flags, pts_t pts, const void *d, int s) { if (items.empty()) curpos=fp; items.push_back(item(fp,flags,pts,offset+data.inbytes())); ++itemlistsize; data.putdata(d,s,true); } const void *getdata() const { return data.data(); } void *getdata() { return data.data(); } const void *getdata(uint32_t bufferpos) const { return (char*)data.data()+(bufferpos-offset); } void *getdata(uint32_t bufferpos) { return (char*)data.data()+(bufferpos-offset); } const buffer &getbuffer() const { return data; } uint32_t getoffset() const { return offset; } unsigned int inbytes() const { return data.inbytes(); } void discardheader() { if (!items.empty()) items.front().clearpts(); } const filepos_t &getcurpos() const { return curpos; } const unsigned int getitemlistsize() const { return itemlistsize; } void audio_addpts(uint32_t startbufferpos=0, bool onepacket=false); uint32_t ptsbufferpos(pts_t pts); uint32_t closestptsbufferpos(pts_t pts); uint32_t fileposbufferpos(filepos_t pos) { for (itemlisttype::iterator it=items.begin();it!=items.end();++it) if (it->fileposition.packetposition() > pos.packetposition()) return it->bufferposition; else if (it->fileposition.packetposition() == pos.packetposition()) return it->bufferposition+(pos.packetoffset()-it->fileposition.packetoffset()); return offset+inbytes(); } const item &filepositem(filepos_t pos) { for (itemlisttype::iterator it=items.begin();it!=items.end();++it) if (it->fileposition.packetposition() >= pos.packetposition()) return *it; return items.back(); } const item &bufferpositem(uint32_t bpos) const { const item *i=&items.front(); for (itemlisttype::const_iterator it=++items.begin();it!=items.end();++it) if (it->bufferposition > bpos) break; else i=&(*it); return *i; } friend int tsfile::streamreader(class streamhandle &s); friend int psfile::streamreader(class streamhandle &s); }; #endif