xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/FlvHandler.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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