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