1 /*
2  * OggPacket will carry all relevant information of an ogg packet
3  *
4  * Copyright (C) 2008 Joern Seger
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  */
21 
22 #include <iostream>
23 #include <sstream>
24 #include <cstring>
25 #include <ogg/ogg.h>
26 
27 #include "oggPacket.h"
28 
OggPacketInternal()29 OggPacketInternal::OggPacketInternal()
30   : m_streamType(OggType::unknown), m_streamNo(255), m_streamHeader(false)
31 {
32   // create a packet without any extra data
33   memset(&m_oggPacket,0, sizeof(m_oggPacket));
34   m_oggPacket.granulepos = -1;
35 
36 }
37 
OggPacketInternal(const ogg_packet & pkt)38 OggPacketInternal::OggPacketInternal(const ogg_packet& pkt)
39   : m_streamType(OggType::unknown), m_streamNo(255), m_streamHeader(false)
40 {
41 
42   m_oggPacket = pkt;
43 
44   // it is unclear, who is the owner of the data!?
45   uint8_t* tmp = new uint8_t [pkt.bytes];
46   memcpy(tmp, pkt.packet, pkt.bytes);
47   m_oggPacket.packet = tmp;
48 
49 }
50 
OggPacketInternal(uint8 * data,uint32 length,uint32 packetNo,int64 granulePos,PacketType packetType)51 OggPacketInternal::OggPacketInternal(uint8 *data, uint32 length,
52                                      uint32 packetNo, int64 granulePos, PacketType packetType)
53   : m_streamType(OggType::unknown), m_streamNo(255), m_streamHeader(false)
54 {
55   uint8_t* tmp_data(0);
56 
57   tmp_data = new uint8_t[length];
58   memcpy(tmp_data, data, length);
59 
60   m_oggPacket.packet     = tmp_data;
61   m_oggPacket.bytes      = length;
62   m_oggPacket.b_o_s      = 0;
63   m_oggPacket.e_o_s      = 0;
64   m_oggPacket.granulepos = granulePos;
65   m_oggPacket.packetno   = packetNo;
66 
67   switch (packetType) {
68   case PacketType::bos:
69     m_oggPacket.b_o_s = 256;
70     break;
71   case PacketType::eos:
72     m_oggPacket.e_o_s = 256;
73     break;
74   default: {
75   }
76   }
77 
78 }
79 
OggPacketInternal(std::vector<uint8> data,uint32 packetNo,int64 granulePos,PacketType packetType)80 OggPacketInternal::OggPacketInternal(std::vector<uint8> data, uint32 packetNo, int64 granulePos, PacketType packetType)
81   : m_streamType(OggType::unknown), m_streamNo(255), m_streamHeader(false)
82 {
83   uint8_t* tmp_data(0);
84 
85   if (data.size() > 0) {
86     tmp_data = new uint8_t[data.size()];
87     memcpy(tmp_data, &data[0], data.size());
88   }
89 
90   m_oggPacket.packet     = tmp_data;
91   m_oggPacket.bytes      = data.size();
92   m_oggPacket.b_o_s      = 0;
93   m_oggPacket.e_o_s      = 0;
94   m_oggPacket.granulepos = granulePos;
95   m_oggPacket.packetno   = packetNo;
96 
97   switch (packetType) {
98   case PacketType::bos:
99     m_oggPacket.b_o_s = 256;
100     break;
101   case PacketType::eos:
102     m_oggPacket.e_o_s = 256;
103     break;
104   default: {
105   }
106   }
107 
108 }
109 
110 
111 
clone()112 OggPacket OggPacketInternal::clone()
113 {
114   OggPacket pkt = std::make_shared<OggPacketInternal>(m_oggPacket);
115 
116   /* a bit nasty, as ogg_packet is c */
117 //  uint8* data = new uint8[m_oggPacket.bytes];
118 //  memcpy(data, m_oggPacket.packet, m_oggPacket.bytes);
119 //
120 //  PacketType packetType(PacketType::normal);
121 //
122 //  if (m_oggPacket.b_o_s)
123 //    packetType = PacketType::bos;
124 //
125 //  if (m_oggPacket.e_o_s)
126 //    packetType = PacketType::eos;
127 //
128 //  OggPacket pkt = std::make_shared<OggPacketInternal>(data, m_oggPacket.bytes, m_oggPacket.packetno, m_oggPacket.granulepos, packetType);
129 //
130 //  pkt->m_streamNo = m_streamNo;
131 //  pkt->m_streamType = m_streamType;
132 //  pkt->m_streamHeader = m_streamHeader;
133 
134   return pkt;
135 }
136 
liboggDelivery()137 void OggPacketInternal::liboggDelivery()
138 {
139   uint8_t* tmp(new uint8_t [m_oggPacket.bytes]);
140   memcpy(tmp, m_oggPacket.packet, m_oggPacket.bytes);
141   m_oggPacket.packet = tmp;
142 
143   // libtheora/libvorbis or whatever - do whatever is neccessary with your memory
144   // I have my copy to use it wherever I like ;-)
145 
146 }
147 
getPtr()148 OggPacket OggPacketInternal::getPtr()
149 {
150   return shared_from_this();
151 }
152 
create(uint8 * data,uint32 length,uint32 packetNo,int64 granulePos,OggPacketInternal::PacketType packetType)153 OggPacket OggPacketInternal::create(uint8 *data, uint32 length, uint32 packetNo, int64 granulePos, OggPacketInternal::PacketType packetType)
154 {
155   return std::make_shared<OggPacketInternal>(data, length, packetNo, granulePos, packetType);
156 }
157 
158 
~OggPacketInternal()159 OggPacketInternal::~OggPacketInternal()
160 {
161   if (!m_streamHeader)
162     delete[] m_oggPacket.packet;
163 }
164 
165 
granulepos()166 int64 OggPacketInternal::granulepos()
167 {
168   return m_oggPacket.granulepos;
169 }
170 
setGranulepos(int64 pos)171 void OggPacketInternal::setGranulepos(int64 pos)
172 {
173   m_oggPacket.granulepos = pos;
174 }
175 
setStreamHeader()176 void OggPacketInternal::setStreamHeader()
177 {
178   m_streamHeader = true;
179 }
180 
isStreamHeader()181 bool OggPacketInternal::isStreamHeader()
182 {
183   return m_streamHeader;
184 }
185 
getPacketNo()186 uint32 OggPacketInternal::getPacketNo()
187 {
188   return m_oggPacket.packetno;
189 }
190 
length()191 uint32 OggPacketInternal::length()
192 {
193   return (uint32) m_oggPacket.bytes;
194 }
195 
isBOS()196 bool OggPacketInternal::isBOS()
197 {
198   return m_oggPacket.b_o_s != 0;
199 }
200 
isEOS()201 bool OggPacketInternal::isEOS()
202 {
203   return m_oggPacket.e_o_s != 0;
204 }
205 
setBOS()206 void OggPacketInternal::setBOS()
207 {
208   m_oggPacket.b_o_s = 1;
209 }
210 
setEOS()211 void OggPacketInternal::setEOS()
212 {
213   m_oggPacket.e_o_s = 1;
214 }
215 
unsetBOS()216 void OggPacketInternal::unsetBOS()
217 {
218   m_oggPacket.b_o_s = 0;
219 }
220 
unsetEOS()221 void OggPacketInternal::unsetEOS()
222 {
223   m_oggPacket.e_o_s = 0;
224 }
225 
226 /*
227 ogg_packet OggPacketInternal::toLibogg()
228 {
229   return(*objPtr);
230 }
231 */
getStreamNo()232 uint8 OggPacketInternal::getStreamNo()
233 {
234   return m_streamNo;
235 }
236 
getStreamType()237 OggType OggPacketInternal::getStreamType()
238 {
239   return m_streamType;
240 }
241 
setStreamNo(uint8 no)242 void OggPacketInternal::setStreamNo(uint8 no)
243 {
244   m_streamNo = no;
245 }
246 
setStreamType(OggType type)247 void OggPacketInternal::setStreamType(OggType type)
248 {
249   m_streamType = type;
250 }
251 
data()252 uint8* OggPacketInternal::data()
253 {
254   return m_oggPacket.packet;
255 }
256 
257 /* toString levels:
258  * 1) only data length information
259  * 2) header information
260  * 3) additional header information
261  * 4) header dump
262  * 5) body dump
263  */
toString(uint8 level)264 std::string OggPacketInternal::toString(uint8 level)
265 {
266   std::stringstream retStream;
267 
268   retStream << "\nOgg Packet: packet length = " << m_oggPacket.bytes << std::endl;
269 
270   if (level < 1)
271     return(retStream.str());
272 
273   retStream << "\nHeader Information:"
274             << "\n\tBegin of Stream     : ";
275 
276   if (m_oggPacket.b_o_s)
277     retStream << "true";
278   else
279     retStream << "false";
280 
281   retStream << "\n\tEnd of Stream       : ";
282 
283   if (m_oggPacket.e_o_s)
284     retStream << "true";
285   else
286     retStream << "false";
287 
288   retStream << "\n\tGranule Position    : " << m_oggPacket.granulepos;
289   retStream << "\n\tPacket Number       : " << m_oggPacket.packetno;
290 
291   retStream << std::endl;
292 
293   if (level < 3)
294     return(retStream.str());
295 
296   retStream << "\n\tStream Number       : " << (int)m_streamNo;
297   retStream << "\n\tStream Type         : ";
298 
299   switch (m_streamType) {
300   case OggType::vorbis:
301     retStream << "Vorbis";
302     break;
303   case OggType::theora:
304     retStream << "Theora";
305     break;
306   case OggType::kate:
307     retStream << "Kate";
308     break;
309   case OggType::unknown:
310   default:
311     retStream << "unknown";
312     break;
313   }
314   retStream << std::endl;
315 
316   if (level < 4)
317     return(retStream.str());
318 
319   retStream << "\nPacket Hex dump:" << std::hex;
320 
321   for (int32 c(0); c<m_oggPacket.bytes; ++c) {
322     if ((c%32) == 0)
323       retStream << std::endl;
324     if (((unsigned) (m_oggPacket.packet[c])) < 16)
325       retStream << " 0";
326     else
327       retStream << " ";
328 
329     retStream << (unsigned) (m_oggPacket.packet[c]);
330   }
331 
332   retStream << std::dec << std::endl;
333 
334   return(retStream.str());
335 }
336