1*f6dc9357SAndroid Build Coastguard Worker // FlvHandler.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker // #include <stdio.h>
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
8*f6dc9357SAndroid Build Coastguard Worker
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyBuffer.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyString.h"
12*f6dc9357SAndroid Build Coastguard Worker
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariant.h"
14*f6dc9357SAndroid Build Coastguard Worker
15*f6dc9357SAndroid Build Coastguard Worker #include "../Common/InBuffer.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ProgressUtils.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamObjects.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
20*f6dc9357SAndroid Build Coastguard Worker
21*f6dc9357SAndroid Build Coastguard Worker #define GetBe24(p) ( \
22*f6dc9357SAndroid Build Coastguard Worker ((UInt32)((const Byte *)(p))[0] << 16) | \
23*f6dc9357SAndroid Build Coastguard Worker ((UInt32)((const Byte *)(p))[1] << 8) | \
24*f6dc9357SAndroid Build Coastguard Worker ((const Byte *)(p))[2] )
25*f6dc9357SAndroid Build Coastguard Worker
26*f6dc9357SAndroid Build Coastguard Worker // #define Get16(p) GetBe16(p)
27*f6dc9357SAndroid Build Coastguard Worker #define Get24(p) GetBe24(p)
28*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetBe32(p)
29*f6dc9357SAndroid Build Coastguard Worker
30*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
31*f6dc9357SAndroid Build Coastguard Worker namespace NFlv {
32*f6dc9357SAndroid Build Coastguard Worker
33*f6dc9357SAndroid Build Coastguard Worker // static const UInt32 kFileSizeMax = (UInt32)1 << 30;
34*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kNumChunksMax = (UInt32)1 << 23;
35*f6dc9357SAndroid Build Coastguard Worker
36*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kTagHeaderSize = 11;
37*f6dc9357SAndroid Build Coastguard Worker
38*f6dc9357SAndroid Build Coastguard Worker static const Byte kFlag_Video = 1;
39*f6dc9357SAndroid Build Coastguard Worker static const Byte kFlag_Audio = 4;
40*f6dc9357SAndroid Build Coastguard Worker
41*f6dc9357SAndroid Build Coastguard Worker static const Byte kType_Audio = 8;
42*f6dc9357SAndroid Build Coastguard Worker static const Byte kType_Video = 9;
43*f6dc9357SAndroid Build Coastguard Worker static const Byte kType_Meta = 18;
44*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumTypes = 19;
45*f6dc9357SAndroid Build Coastguard Worker
46*f6dc9357SAndroid Build Coastguard Worker struct CItem
47*f6dc9357SAndroid Build Coastguard Worker {
48*f6dc9357SAndroid Build Coastguard Worker CByteBuffer Data;
49*f6dc9357SAndroid Build Coastguard Worker Byte Type;
50*f6dc9357SAndroid Build Coastguard Worker };
51*f6dc9357SAndroid Build Coastguard Worker
52*f6dc9357SAndroid Build Coastguard Worker struct CItem2
53*f6dc9357SAndroid Build Coastguard Worker {
54*f6dc9357SAndroid Build Coastguard Worker Byte Type;
55*f6dc9357SAndroid Build Coastguard Worker Byte SubType;
56*f6dc9357SAndroid Build Coastguard Worker Byte Props;
57*f6dc9357SAndroid Build Coastguard Worker bool SameSubTypes;
58*f6dc9357SAndroid Build Coastguard Worker unsigned NumChunks;
59*f6dc9357SAndroid Build Coastguard Worker size_t Size;
60*f6dc9357SAndroid Build Coastguard Worker
61*f6dc9357SAndroid Build Coastguard Worker CReferenceBuf *BufSpec;
62*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IUnknown> RefBuf;
63*f6dc9357SAndroid Build Coastguard Worker
IsAudioNArchive::NFlv::CItem264*f6dc9357SAndroid Build Coastguard Worker bool IsAudio() const { return Type == kType_Audio; }
65*f6dc9357SAndroid Build Coastguard Worker };
66*f6dc9357SAndroid Build Coastguard Worker
67*f6dc9357SAndroid Build Coastguard Worker
68*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_CHandler_IInArchive_1(
69*f6dc9357SAndroid Build Coastguard Worker IInArchiveGetStream
70*f6dc9357SAndroid Build Coastguard Worker )
71*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> _stream;
72*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CItem2> _items2;
73*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _metadata;
74*f6dc9357SAndroid Build Coastguard Worker bool _isRaw;
75*f6dc9357SAndroid Build Coastguard Worker UInt64 _phySize;
76*f6dc9357SAndroid Build Coastguard Worker
77*f6dc9357SAndroid Build Coastguard Worker HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
78*f6dc9357SAndroid Build Coastguard Worker // AString GetComment();
79*f6dc9357SAndroid Build Coastguard Worker };
80*f6dc9357SAndroid Build Coastguard Worker
81*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
82*f6dc9357SAndroid Build Coastguard Worker {
83*f6dc9357SAndroid Build Coastguard Worker kpidSize,
84*f6dc9357SAndroid Build Coastguard Worker kpidNumBlocks,
85*f6dc9357SAndroid Build Coastguard Worker kpidComment
86*f6dc9357SAndroid Build Coastguard Worker };
87*f6dc9357SAndroid Build Coastguard Worker
88*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
89*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps_NO_Table
90*f6dc9357SAndroid Build Coastguard Worker
91*f6dc9357SAndroid Build Coastguard Worker static const char * const g_AudioTypes[16] =
92*f6dc9357SAndroid Build Coastguard Worker {
93*f6dc9357SAndroid Build Coastguard Worker "pcm"
94*f6dc9357SAndroid Build Coastguard Worker , "adpcm"
95*f6dc9357SAndroid Build Coastguard Worker , "mp3"
96*f6dc9357SAndroid Build Coastguard Worker , "pcm_le"
97*f6dc9357SAndroid Build Coastguard Worker , "nellymoser16"
98*f6dc9357SAndroid Build Coastguard Worker , "nellymoser8"
99*f6dc9357SAndroid Build Coastguard Worker , "nellymoser"
100*f6dc9357SAndroid Build Coastguard Worker , "g711a"
101*f6dc9357SAndroid Build Coastguard Worker , "g711m"
102*f6dc9357SAndroid Build Coastguard Worker , "audio9"
103*f6dc9357SAndroid Build Coastguard Worker , "aac"
104*f6dc9357SAndroid Build Coastguard Worker , "speex"
105*f6dc9357SAndroid Build Coastguard Worker , "audio12"
106*f6dc9357SAndroid Build Coastguard Worker , "audio13"
107*f6dc9357SAndroid Build Coastguard Worker , "mp3"
108*f6dc9357SAndroid Build Coastguard Worker , "audio15"
109*f6dc9357SAndroid Build Coastguard Worker };
110*f6dc9357SAndroid Build Coastguard Worker
111*f6dc9357SAndroid Build Coastguard Worker static const char * const g_VideoTypes[16] =
112*f6dc9357SAndroid Build Coastguard Worker {
113*f6dc9357SAndroid Build Coastguard Worker "video0"
114*f6dc9357SAndroid Build Coastguard Worker , "jpeg"
115*f6dc9357SAndroid Build Coastguard Worker , "h263"
116*f6dc9357SAndroid Build Coastguard Worker , "screen"
117*f6dc9357SAndroid Build Coastguard Worker , "vp6"
118*f6dc9357SAndroid Build Coastguard Worker , "vp6alpha"
119*f6dc9357SAndroid Build Coastguard Worker , "screen2"
120*f6dc9357SAndroid Build Coastguard Worker , "avc"
121*f6dc9357SAndroid Build Coastguard Worker , "video8"
122*f6dc9357SAndroid Build Coastguard Worker , "video9"
123*f6dc9357SAndroid Build Coastguard Worker , "video10"
124*f6dc9357SAndroid Build Coastguard Worker , "video11"
125*f6dc9357SAndroid Build Coastguard Worker , "video12"
126*f6dc9357SAndroid Build Coastguard Worker , "video13"
127*f6dc9357SAndroid Build Coastguard Worker , "video14"
128*f6dc9357SAndroid Build Coastguard Worker , "video15"
129*f6dc9357SAndroid Build Coastguard Worker };
130*f6dc9357SAndroid Build Coastguard Worker
131*f6dc9357SAndroid Build Coastguard Worker static const char * const g_Rates[4] =
132*f6dc9357SAndroid Build Coastguard Worker {
133*f6dc9357SAndroid Build Coastguard Worker "5.5 kHz"
134*f6dc9357SAndroid Build Coastguard Worker , "11 kHz"
135*f6dc9357SAndroid Build Coastguard Worker , "22 kHz"
136*f6dc9357SAndroid Build Coastguard Worker , "44 kHz"
137*f6dc9357SAndroid Build Coastguard Worker };
138*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetProperty (UInt32 index,PROPID propID,PROPVARIANT * value))139*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
140*f6dc9357SAndroid Build Coastguard Worker {
141*f6dc9357SAndroid Build Coastguard Worker NWindows::NCOM::CPropVariant prop;
142*f6dc9357SAndroid Build Coastguard Worker const CItem2 &item = _items2[index];
143*f6dc9357SAndroid Build Coastguard Worker switch (propID)
144*f6dc9357SAndroid Build Coastguard Worker {
145*f6dc9357SAndroid Build Coastguard Worker case kpidExtension:
146*f6dc9357SAndroid Build Coastguard Worker prop = _isRaw ?
147*f6dc9357SAndroid Build Coastguard Worker (item.IsAudio() ? g_AudioTypes[item.SubType] : g_VideoTypes[item.SubType]) :
148*f6dc9357SAndroid Build Coastguard Worker (item.IsAudio() ? "audio.flv" : "video.flv");
149*f6dc9357SAndroid Build Coastguard Worker break;
150*f6dc9357SAndroid Build Coastguard Worker case kpidSize:
151*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize:
152*f6dc9357SAndroid Build Coastguard Worker prop = (UInt64)item.Size;
153*f6dc9357SAndroid Build Coastguard Worker break;
154*f6dc9357SAndroid Build Coastguard Worker case kpidNumBlocks: prop = (UInt32)item.NumChunks; break;
155*f6dc9357SAndroid Build Coastguard Worker case kpidComment:
156*f6dc9357SAndroid Build Coastguard Worker {
157*f6dc9357SAndroid Build Coastguard Worker char sz[64];
158*f6dc9357SAndroid Build Coastguard Worker char *s = MyStpCpy(sz, (item.IsAudio() ? g_AudioTypes[item.SubType] : g_VideoTypes[item.SubType]) );
159*f6dc9357SAndroid Build Coastguard Worker if (item.IsAudio())
160*f6dc9357SAndroid Build Coastguard Worker {
161*f6dc9357SAndroid Build Coastguard Worker *s++ = ' ';
162*f6dc9357SAndroid Build Coastguard Worker s = MyStpCpy(s, g_Rates[(item.Props >> 2) & 3]);
163*f6dc9357SAndroid Build Coastguard Worker s = MyStpCpy(s, (item.Props & 2) ? " 16-bit" : " 8-bit");
164*f6dc9357SAndroid Build Coastguard Worker s = MyStpCpy(s, (item.Props & 1) ? " stereo" : " mono");
165*f6dc9357SAndroid Build Coastguard Worker }
166*f6dc9357SAndroid Build Coastguard Worker prop = sz;
167*f6dc9357SAndroid Build Coastguard Worker break;
168*f6dc9357SAndroid Build Coastguard Worker }
169*f6dc9357SAndroid Build Coastguard Worker }
170*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
171*f6dc9357SAndroid Build Coastguard Worker return S_OK;
172*f6dc9357SAndroid Build Coastguard Worker }
173*f6dc9357SAndroid Build Coastguard Worker
174*f6dc9357SAndroid Build Coastguard Worker /*
175*f6dc9357SAndroid Build Coastguard Worker AString CHandler::GetComment()
176*f6dc9357SAndroid Build Coastguard Worker {
177*f6dc9357SAndroid Build Coastguard Worker const Byte *p = _metadata;
178*f6dc9357SAndroid Build Coastguard Worker size_t size = _metadata.Size();
179*f6dc9357SAndroid Build Coastguard Worker AString res;
180*f6dc9357SAndroid Build Coastguard Worker if (size > 0)
181*f6dc9357SAndroid Build Coastguard Worker {
182*f6dc9357SAndroid Build Coastguard Worker p++;
183*f6dc9357SAndroid Build Coastguard Worker size--;
184*f6dc9357SAndroid Build Coastguard Worker for (;;)
185*f6dc9357SAndroid Build Coastguard Worker {
186*f6dc9357SAndroid Build Coastguard Worker if (size < 2)
187*f6dc9357SAndroid Build Coastguard Worker break;
188*f6dc9357SAndroid Build Coastguard Worker int len = Get16(p);
189*f6dc9357SAndroid Build Coastguard Worker p += 2;
190*f6dc9357SAndroid Build Coastguard Worker size -= 2;
191*f6dc9357SAndroid Build Coastguard Worker if (len == 0 || (size_t)len > size)
192*f6dc9357SAndroid Build Coastguard Worker break;
193*f6dc9357SAndroid Build Coastguard Worker {
194*f6dc9357SAndroid Build Coastguard Worker AString temp;
195*f6dc9357SAndroid Build Coastguard Worker temp.SetFrom_CalcLen((const char *)p, len);
196*f6dc9357SAndroid Build Coastguard Worker if (!res.IsEmpty())
197*f6dc9357SAndroid Build Coastguard Worker res += '\n';
198*f6dc9357SAndroid Build Coastguard Worker res += temp;
199*f6dc9357SAndroid Build Coastguard Worker }
200*f6dc9357SAndroid Build Coastguard Worker p += len;
201*f6dc9357SAndroid Build Coastguard Worker size -= len;
202*f6dc9357SAndroid Build Coastguard Worker if (size < 1)
203*f6dc9357SAndroid Build Coastguard Worker break;
204*f6dc9357SAndroid Build Coastguard Worker Byte type = *p++;
205*f6dc9357SAndroid Build Coastguard Worker size--;
206*f6dc9357SAndroid Build Coastguard Worker bool ok = false;
207*f6dc9357SAndroid Build Coastguard Worker switch (type)
208*f6dc9357SAndroid Build Coastguard Worker {
209*f6dc9357SAndroid Build Coastguard Worker case 0:
210*f6dc9357SAndroid Build Coastguard Worker {
211*f6dc9357SAndroid Build Coastguard Worker if (size < 8)
212*f6dc9357SAndroid Build Coastguard Worker break;
213*f6dc9357SAndroid Build Coastguard Worker ok = true;
214*f6dc9357SAndroid Build Coastguard Worker Byte reverse[8];
215*f6dc9357SAndroid Build Coastguard Worker for (int i = 0; i < 8; i++)
216*f6dc9357SAndroid Build Coastguard Worker {
217*f6dc9357SAndroid Build Coastguard Worker bool little_endian = 1;
218*f6dc9357SAndroid Build Coastguard Worker if (little_endian)
219*f6dc9357SAndroid Build Coastguard Worker reverse[i] = p[7 - i];
220*f6dc9357SAndroid Build Coastguard Worker else
221*f6dc9357SAndroid Build Coastguard Worker reverse[i] = p[i];
222*f6dc9357SAndroid Build Coastguard Worker }
223*f6dc9357SAndroid Build Coastguard Worker double d = *(double *)reverse;
224*f6dc9357SAndroid Build Coastguard Worker char temp[32];
225*f6dc9357SAndroid Build Coastguard Worker sprintf(temp, " = %.3f", d);
226*f6dc9357SAndroid Build Coastguard Worker res += temp;
227*f6dc9357SAndroid Build Coastguard Worker p += 8;
228*f6dc9357SAndroid Build Coastguard Worker size -= 8;
229*f6dc9357SAndroid Build Coastguard Worker break;
230*f6dc9357SAndroid Build Coastguard Worker }
231*f6dc9357SAndroid Build Coastguard Worker case 8:
232*f6dc9357SAndroid Build Coastguard Worker {
233*f6dc9357SAndroid Build Coastguard Worker if (size < 4)
234*f6dc9357SAndroid Build Coastguard Worker break;
235*f6dc9357SAndroid Build Coastguard Worker ok = true;
236*f6dc9357SAndroid Build Coastguard Worker // UInt32 numItems = Get32(p);
237*f6dc9357SAndroid Build Coastguard Worker p += 4;
238*f6dc9357SAndroid Build Coastguard Worker size -= 4;
239*f6dc9357SAndroid Build Coastguard Worker break;
240*f6dc9357SAndroid Build Coastguard Worker }
241*f6dc9357SAndroid Build Coastguard Worker }
242*f6dc9357SAndroid Build Coastguard Worker if (!ok)
243*f6dc9357SAndroid Build Coastguard Worker break;
244*f6dc9357SAndroid Build Coastguard Worker }
245*f6dc9357SAndroid Build Coastguard Worker }
246*f6dc9357SAndroid Build Coastguard Worker return res;
247*f6dc9357SAndroid Build Coastguard Worker }
248*f6dc9357SAndroid Build Coastguard Worker */
249*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetArchiveProperty (PROPID propID,PROPVARIANT * value))250*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
251*f6dc9357SAndroid Build Coastguard Worker {
252*f6dc9357SAndroid Build Coastguard Worker // COM_TRY_BEGIN
253*f6dc9357SAndroid Build Coastguard Worker NWindows::NCOM::CPropVariant prop;
254*f6dc9357SAndroid Build Coastguard Worker switch (propID)
255*f6dc9357SAndroid Build Coastguard Worker {
256*f6dc9357SAndroid Build Coastguard Worker // case kpidComment: prop = GetComment(); break;
257*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: prop = (UInt64)_phySize; break;
258*f6dc9357SAndroid Build Coastguard Worker case kpidIsNotArcType: prop = true; break;
259*f6dc9357SAndroid Build Coastguard Worker }
260*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
261*f6dc9357SAndroid Build Coastguard Worker return S_OK;
262*f6dc9357SAndroid Build Coastguard Worker // COM_TRY_END
263*f6dc9357SAndroid Build Coastguard Worker }
264*f6dc9357SAndroid Build Coastguard Worker
Open2(IInStream * stream,IArchiveOpenCallback * callback)265*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
266*f6dc9357SAndroid Build Coastguard Worker {
267*f6dc9357SAndroid Build Coastguard Worker const UInt32 kHeaderSize = 13;
268*f6dc9357SAndroid Build Coastguard Worker Byte header[kHeaderSize];
269*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, header, kHeaderSize))
270*f6dc9357SAndroid Build Coastguard Worker if (header[0] != 'F' ||
271*f6dc9357SAndroid Build Coastguard Worker header[1] != 'L' ||
272*f6dc9357SAndroid Build Coastguard Worker header[2] != 'V' ||
273*f6dc9357SAndroid Build Coastguard Worker header[3] != 1 ||
274*f6dc9357SAndroid Build Coastguard Worker (header[4] & 0xFA) != 0)
275*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
276*f6dc9357SAndroid Build Coastguard Worker UInt64 offset = Get32(header + 5);
277*f6dc9357SAndroid Build Coastguard Worker if (offset != 9 || Get32(header + 9) != 0)
278*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
279*f6dc9357SAndroid Build Coastguard Worker offset = kHeaderSize;
280*f6dc9357SAndroid Build Coastguard Worker
281*f6dc9357SAndroid Build Coastguard Worker CInBuffer inBuf;
282*f6dc9357SAndroid Build Coastguard Worker if (!inBuf.Create(1 << 15))
283*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
284*f6dc9357SAndroid Build Coastguard Worker inBuf.SetStream(stream);
285*f6dc9357SAndroid Build Coastguard Worker
286*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CItem> items;
287*f6dc9357SAndroid Build Coastguard Worker int lasts[kNumTypes];
288*f6dc9357SAndroid Build Coastguard Worker unsigned i;
289*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < kNumTypes; i++)
290*f6dc9357SAndroid Build Coastguard Worker lasts[i] = -1;
291*f6dc9357SAndroid Build Coastguard Worker
292*f6dc9357SAndroid Build Coastguard Worker _phySize = offset;
293*f6dc9357SAndroid Build Coastguard Worker for (;;)
294*f6dc9357SAndroid Build Coastguard Worker {
295*f6dc9357SAndroid Build Coastguard Worker Byte buf[kTagHeaderSize];
296*f6dc9357SAndroid Build Coastguard Worker CItem item;
297*f6dc9357SAndroid Build Coastguard Worker if (inBuf.ReadBytes(buf, kTagHeaderSize) != kTagHeaderSize)
298*f6dc9357SAndroid Build Coastguard Worker break;
299*f6dc9357SAndroid Build Coastguard Worker item.Type = buf[0];
300*f6dc9357SAndroid Build Coastguard Worker UInt32 size = Get24(buf + 1);
301*f6dc9357SAndroid Build Coastguard Worker if (size < 1)
302*f6dc9357SAndroid Build Coastguard Worker break;
303*f6dc9357SAndroid Build Coastguard Worker // item.Time = Get24(buf + 4);
304*f6dc9357SAndroid Build Coastguard Worker // item.Time |= (UInt32)buf[7] << 24;
305*f6dc9357SAndroid Build Coastguard Worker if (Get24(buf + 8) != 0) // streamID
306*f6dc9357SAndroid Build Coastguard Worker break;
307*f6dc9357SAndroid Build Coastguard Worker
308*f6dc9357SAndroid Build Coastguard Worker UInt32 curSize = kTagHeaderSize + size + 4;
309*f6dc9357SAndroid Build Coastguard Worker item.Data.Alloc(curSize);
310*f6dc9357SAndroid Build Coastguard Worker memcpy(item.Data, buf, kTagHeaderSize);
311*f6dc9357SAndroid Build Coastguard Worker if (inBuf.ReadBytes(item.Data + kTagHeaderSize, size) != size)
312*f6dc9357SAndroid Build Coastguard Worker break;
313*f6dc9357SAndroid Build Coastguard Worker if (inBuf.ReadBytes(item.Data + kTagHeaderSize + size, 4) != 4)
314*f6dc9357SAndroid Build Coastguard Worker break;
315*f6dc9357SAndroid Build Coastguard Worker
316*f6dc9357SAndroid Build Coastguard Worker if (Get32(item.Data + kTagHeaderSize + size) != kTagHeaderSize + size)
317*f6dc9357SAndroid Build Coastguard Worker break;
318*f6dc9357SAndroid Build Coastguard Worker
319*f6dc9357SAndroid Build Coastguard Worker offset += curSize;
320*f6dc9357SAndroid Build Coastguard Worker
321*f6dc9357SAndroid Build Coastguard Worker // printf("\noffset = %6X type = %2d time = %6d size = %6d", (UInt32)offset, item.Type, item.Time, item.Size);
322*f6dc9357SAndroid Build Coastguard Worker
323*f6dc9357SAndroid Build Coastguard Worker if (item.Type == kType_Meta)
324*f6dc9357SAndroid Build Coastguard Worker {
325*f6dc9357SAndroid Build Coastguard Worker // _metadata = item.Buf;
326*f6dc9357SAndroid Build Coastguard Worker }
327*f6dc9357SAndroid Build Coastguard Worker else
328*f6dc9357SAndroid Build Coastguard Worker {
329*f6dc9357SAndroid Build Coastguard Worker if (item.Type != kType_Audio && item.Type != kType_Video)
330*f6dc9357SAndroid Build Coastguard Worker break;
331*f6dc9357SAndroid Build Coastguard Worker if (items.Size() >= kNumChunksMax)
332*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
333*f6dc9357SAndroid Build Coastguard Worker Byte firstByte = item.Data[kTagHeaderSize];
334*f6dc9357SAndroid Build Coastguard Worker Byte subType, props;
335*f6dc9357SAndroid Build Coastguard Worker if (item.Type == kType_Audio)
336*f6dc9357SAndroid Build Coastguard Worker {
337*f6dc9357SAndroid Build Coastguard Worker subType = (Byte)(firstByte >> 4);
338*f6dc9357SAndroid Build Coastguard Worker props = (Byte)(firstByte & 0xF);
339*f6dc9357SAndroid Build Coastguard Worker }
340*f6dc9357SAndroid Build Coastguard Worker else
341*f6dc9357SAndroid Build Coastguard Worker {
342*f6dc9357SAndroid Build Coastguard Worker subType = (Byte)(firstByte & 0xF);
343*f6dc9357SAndroid Build Coastguard Worker props = (Byte)(firstByte >> 4);
344*f6dc9357SAndroid Build Coastguard Worker }
345*f6dc9357SAndroid Build Coastguard Worker int last = lasts[item.Type];
346*f6dc9357SAndroid Build Coastguard Worker if (last < 0)
347*f6dc9357SAndroid Build Coastguard Worker {
348*f6dc9357SAndroid Build Coastguard Worker CItem2 item2;
349*f6dc9357SAndroid Build Coastguard Worker item2.RefBuf = item2.BufSpec = new CReferenceBuf;
350*f6dc9357SAndroid Build Coastguard Worker item2.Size = curSize;
351*f6dc9357SAndroid Build Coastguard Worker item2.Type = item.Type;
352*f6dc9357SAndroid Build Coastguard Worker item2.SubType = subType;
353*f6dc9357SAndroid Build Coastguard Worker item2.Props = props;
354*f6dc9357SAndroid Build Coastguard Worker item2.NumChunks = 1;
355*f6dc9357SAndroid Build Coastguard Worker item2.SameSubTypes = true;
356*f6dc9357SAndroid Build Coastguard Worker lasts[item.Type] = (int)_items2.Add(item2);
357*f6dc9357SAndroid Build Coastguard Worker }
358*f6dc9357SAndroid Build Coastguard Worker else
359*f6dc9357SAndroid Build Coastguard Worker {
360*f6dc9357SAndroid Build Coastguard Worker CItem2 &item2 = _items2[last];
361*f6dc9357SAndroid Build Coastguard Worker if (subType != item2.SubType)
362*f6dc9357SAndroid Build Coastguard Worker item2.SameSubTypes = false;
363*f6dc9357SAndroid Build Coastguard Worker item2.Size += curSize;
364*f6dc9357SAndroid Build Coastguard Worker item2.NumChunks++;
365*f6dc9357SAndroid Build Coastguard Worker }
366*f6dc9357SAndroid Build Coastguard Worker items.Add(item);
367*f6dc9357SAndroid Build Coastguard Worker }
368*f6dc9357SAndroid Build Coastguard Worker _phySize = offset;
369*f6dc9357SAndroid Build Coastguard Worker if (callback && (items.Size() & 0xFF) == 0)
370*f6dc9357SAndroid Build Coastguard Worker {
371*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->SetCompleted(NULL, &offset))
372*f6dc9357SAndroid Build Coastguard Worker }
373*f6dc9357SAndroid Build Coastguard Worker }
374*f6dc9357SAndroid Build Coastguard Worker if (items.IsEmpty())
375*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
376*f6dc9357SAndroid Build Coastguard Worker
377*f6dc9357SAndroid Build Coastguard Worker _isRaw = (_items2.Size() == 1);
378*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _items2.Size(); i++)
379*f6dc9357SAndroid Build Coastguard Worker {
380*f6dc9357SAndroid Build Coastguard Worker CItem2 &item2 = _items2[i];
381*f6dc9357SAndroid Build Coastguard Worker CByteBuffer &itemBuf = item2.BufSpec->Buf;
382*f6dc9357SAndroid Build Coastguard Worker if (_isRaw)
383*f6dc9357SAndroid Build Coastguard Worker {
384*f6dc9357SAndroid Build Coastguard Worker if (!item2.SameSubTypes)
385*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
386*f6dc9357SAndroid Build Coastguard Worker itemBuf.Alloc((size_t)item2.Size - (size_t)(kTagHeaderSize + 4 + 1) * item2.NumChunks);
387*f6dc9357SAndroid Build Coastguard Worker item2.Size = 0;
388*f6dc9357SAndroid Build Coastguard Worker }
389*f6dc9357SAndroid Build Coastguard Worker else
390*f6dc9357SAndroid Build Coastguard Worker {
391*f6dc9357SAndroid Build Coastguard Worker itemBuf.Alloc(kHeaderSize + (size_t)item2.Size);
392*f6dc9357SAndroid Build Coastguard Worker memcpy(itemBuf, header, kHeaderSize);
393*f6dc9357SAndroid Build Coastguard Worker itemBuf[4] = item2.IsAudio() ? kFlag_Audio : kFlag_Video;
394*f6dc9357SAndroid Build Coastguard Worker item2.Size = kHeaderSize;
395*f6dc9357SAndroid Build Coastguard Worker }
396*f6dc9357SAndroid Build Coastguard Worker }
397*f6dc9357SAndroid Build Coastguard Worker
398*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < items.Size(); i++)
399*f6dc9357SAndroid Build Coastguard Worker {
400*f6dc9357SAndroid Build Coastguard Worker const CItem &item = items[i];
401*f6dc9357SAndroid Build Coastguard Worker CItem2 &item2 = _items2[lasts[item.Type]];
402*f6dc9357SAndroid Build Coastguard Worker size_t size = item.Data.Size();
403*f6dc9357SAndroid Build Coastguard Worker const Byte *src = item.Data;
404*f6dc9357SAndroid Build Coastguard Worker if (_isRaw)
405*f6dc9357SAndroid Build Coastguard Worker {
406*f6dc9357SAndroid Build Coastguard Worker src += kTagHeaderSize + 1;
407*f6dc9357SAndroid Build Coastguard Worker size -= (kTagHeaderSize + 4 + 1);
408*f6dc9357SAndroid Build Coastguard Worker }
409*f6dc9357SAndroid Build Coastguard Worker if (size != 0)
410*f6dc9357SAndroid Build Coastguard Worker {
411*f6dc9357SAndroid Build Coastguard Worker memcpy(item2.BufSpec->Buf + item2.Size, src, size);
412*f6dc9357SAndroid Build Coastguard Worker item2.Size += size;
413*f6dc9357SAndroid Build Coastguard Worker }
414*f6dc9357SAndroid Build Coastguard Worker }
415*f6dc9357SAndroid Build Coastguard Worker return S_OK;
416*f6dc9357SAndroid Build Coastguard Worker }
417*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::Open (IInStream * inStream,const UInt64 *,IArchiveOpenCallback * callback))418*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback))
419*f6dc9357SAndroid Build Coastguard Worker {
420*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
421*f6dc9357SAndroid Build Coastguard Worker Close();
422*f6dc9357SAndroid Build Coastguard Worker HRESULT res;
423*f6dc9357SAndroid Build Coastguard Worker try
424*f6dc9357SAndroid Build Coastguard Worker {
425*f6dc9357SAndroid Build Coastguard Worker res = Open2(inStream, callback);
426*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK)
427*f6dc9357SAndroid Build Coastguard Worker _stream = inStream;
428*f6dc9357SAndroid Build Coastguard Worker }
429*f6dc9357SAndroid Build Coastguard Worker catch(...) { res = S_FALSE; }
430*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
431*f6dc9357SAndroid Build Coastguard Worker {
432*f6dc9357SAndroid Build Coastguard Worker Close();
433*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
434*f6dc9357SAndroid Build Coastguard Worker }
435*f6dc9357SAndroid Build Coastguard Worker return S_OK;
436*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
437*f6dc9357SAndroid Build Coastguard Worker }
438*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::Close ())439*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
440*f6dc9357SAndroid Build Coastguard Worker {
441*f6dc9357SAndroid Build Coastguard Worker _phySize = 0;
442*f6dc9357SAndroid Build Coastguard Worker _stream.Release();
443*f6dc9357SAndroid Build Coastguard Worker _items2.Clear();
444*f6dc9357SAndroid Build Coastguard Worker // _metadata.SetCapacity(0);
445*f6dc9357SAndroid Build Coastguard Worker return S_OK;
446*f6dc9357SAndroid Build Coastguard Worker }
447*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetNumberOfItems (UInt32 * numItems))448*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
449*f6dc9357SAndroid Build Coastguard Worker {
450*f6dc9357SAndroid Build Coastguard Worker *numItems = _items2.Size();
451*f6dc9357SAndroid Build Coastguard Worker return S_OK;
452*f6dc9357SAndroid Build Coastguard Worker }
453*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::Extract (const UInt32 * indices,UInt32 numItems,Int32 testMode,IArchiveExtractCallback * extractCallback))454*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
455*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback))
456*f6dc9357SAndroid Build Coastguard Worker {
457*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
458*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
459*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode)
460*f6dc9357SAndroid Build Coastguard Worker numItems = _items2.Size();
461*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0)
462*f6dc9357SAndroid Build Coastguard Worker return S_OK;
463*f6dc9357SAndroid Build Coastguard Worker UInt64 totalSize = 0;
464*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
465*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
466*f6dc9357SAndroid Build Coastguard Worker totalSize += _items2[allFilesMode ? i : indices[i]].Size;
467*f6dc9357SAndroid Build Coastguard Worker extractCallback->SetTotal(totalSize);
468*f6dc9357SAndroid Build Coastguard Worker
469*f6dc9357SAndroid Build Coastguard Worker totalSize = 0;
470*f6dc9357SAndroid Build Coastguard Worker
471*f6dc9357SAndroid Build Coastguard Worker CLocalProgress *lps = new CLocalProgress;
472*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressProgressInfo> progress = lps;
473*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false);
474*f6dc9357SAndroid Build Coastguard Worker
475*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
476*f6dc9357SAndroid Build Coastguard Worker {
477*f6dc9357SAndroid Build Coastguard Worker lps->InSize = lps->OutSize = totalSize;
478*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
479*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> outStream;
480*f6dc9357SAndroid Build Coastguard Worker const Int32 askMode = testMode ?
481*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
482*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract;
483*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
484*f6dc9357SAndroid Build Coastguard Worker const CItem2 &item = _items2[index];
485*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &outStream, askMode))
486*f6dc9357SAndroid Build Coastguard Worker totalSize += item.Size;
487*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !outStream)
488*f6dc9357SAndroid Build Coastguard Worker continue;
489*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
490*f6dc9357SAndroid Build Coastguard Worker if (outStream)
491*f6dc9357SAndroid Build Coastguard Worker {
492*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, item.BufSpec->Buf, item.BufSpec->Buf.Size()))
493*f6dc9357SAndroid Build Coastguard Worker }
494*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
495*f6dc9357SAndroid Build Coastguard Worker }
496*f6dc9357SAndroid Build Coastguard Worker return S_OK;
497*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
498*f6dc9357SAndroid Build Coastguard Worker }
499*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetStream (UInt32 index,ISequentialInStream ** stream))500*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
501*f6dc9357SAndroid Build Coastguard Worker {
502*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
503*f6dc9357SAndroid Build Coastguard Worker *stream = NULL;
504*f6dc9357SAndroid Build Coastguard Worker CBufInStream *streamSpec = new CBufInStream;
505*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
506*f6dc9357SAndroid Build Coastguard Worker streamSpec->Init(_items2[index].BufSpec);
507*f6dc9357SAndroid Build Coastguard Worker *stream = streamTemp.Detach();
508*f6dc9357SAndroid Build Coastguard Worker return S_OK;
509*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
510*f6dc9357SAndroid Build Coastguard Worker }
511*f6dc9357SAndroid Build Coastguard Worker
512*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = { 'F', 'L', 'V', 1, };
513*f6dc9357SAndroid Build Coastguard Worker
514*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
515*f6dc9357SAndroid Build Coastguard Worker "FLV", "flv", NULL, 0xD6,
516*f6dc9357SAndroid Build Coastguard Worker k_Signature,
517*f6dc9357SAndroid Build Coastguard Worker 0,
518*f6dc9357SAndroid Build Coastguard Worker 0,
519*f6dc9357SAndroid Build Coastguard Worker NULL)
520*f6dc9357SAndroid Build Coastguard Worker
521*f6dc9357SAndroid Build Coastguard Worker }}
522