Changes of Revision 85

lightspark.spec Changed
x
 
1
@@ -24,7 +24,7 @@
2
 %bcond_with rtmp
3
 %endif
4
 Name:           lightspark
5
-Version:        0.7.2.99+git20151003.1109
6
+Version:        0.7.2.99+git20151010.1946
7
 Release:        0
8
 Summary:        Modern, free, open-source flash player implementation
9
 License:        LGPL-3.0+
10
lightspark.tar.xz/src/backends/netutils.cpp Changed
46
 
1
@@ -245,7 +245,8 @@
2
    cache(_cache),                                                //CACHING
3
    owner(o),                                                     //PROGRESS
4
    redirected(false),requestStatus(0),                           //HTTP REDIR, STATUS & HEADERS
5
-   length(0)                                                     //DOWNLOADED DATA
6
+   length(0),                                                    //DOWNLOADED DATA
7
+   emptyanswer(false)
8
 {
9
 }
10
 
11
@@ -261,7 +262,8 @@
12
    cache(_cache),                                                   //CACHING
13
    owner(o),                                                        //PROGRESS
14
    redirected(false),requestStatus(0),requestHeaders(h),data(_data),//HTTP REDIR, STATUS & HEADERS
15
-   length(0)                                                        //DOWNLOADED DATA
16
+   length(0),                                                       //DOWNLOADED DATA
17
+   emptyanswer(false)
18
 {
19
 }
20
 
21
@@ -391,7 +393,11 @@
22
            setFailed();
23
        }
24
        else if(getRequestStatus()/100 == 3) {;} //HTTP redirect
25
-       else if(getRequestStatus()/100 == 2) {;} //HTTP OK
26
+       else if(getRequestStatus()/100 == 2) //HTTP OK
27
+       {
28
+           if (getRequestStatus() == 204)
29
+               emptyanswer = true;
30
+       } 
31
    }
32
    else
33
    {
34
@@ -423,7 +429,10 @@
35
                //Only read the length when we're not redirecting
36
                if(getRequestStatus()/100 != 3)
37
                {
38
-                   setLength(atoi(headerValue.c_str()));
39
+                   int len = atoi(headerValue.c_str());
40
+                   if (len == 0)
41
+                       emptyanswer = true;
42
+                   setLength(len);
43
                    return;
44
                }
45
            }
46
lightspark.tar.xz/src/backends/netutils.h Changed
20
 
1
@@ -127,6 +127,8 @@
2
    uint32_t length;
3
    //Set the length of the downloaded file, can be called multiple times to accomodate a growing file
4
    void setLength(uint32_t _length);
5
+   
6
+   bool emptyanswer;
7
 public:
8
    //This class can only get destroyed by DownloadManager derivate classes
9
    virtual ~Downloader();
10
@@ -138,6 +140,9 @@
11
    //True if the download has finished
12
    //Can be used in conjunction with failed to find out if it finished successfully
13
    bool hasFinished() { return cache->hasTerminated(); }
14
+   
15
+   // true if status header is 204 or content-length header is 0
16
+   bool hasEmptyAnswer() { return emptyanswer; }
17
 
18
    const tiny_string& getURL() { return url; }
19
 
20
lightspark.tar.xz/src/scripting/flash/display/flashdisplay.cpp Changed
14
 
1
@@ -330,8 +330,11 @@
2
        
3
        // Wait for some data, making sure our check for failure is working
4
        sbuf->sgetc(); // peek one byte
5
-       if(downloader->getRequestStatus() == 204) // empty answer
6
+       if(downloader->hasEmptyAnswer())
7
+       {
8
+           LOG(LOG_INFO,"empty answer:"<<url);
9
            return;
10
+       }
11
 
12
        if(cache->hasFailed()) //Check to see if the download failed for some reason
13
        {
14
lightspark.tar.xz/src/scripting/flash/net/NetStreamInfo.cpp Changed
34
 
1
@@ -81,17 +81,17 @@
2
 ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,audioBufferByteLength);
3
 ASFUNCTIONBODY_GETTER(NetStreamInfo,audioBufferLength);
4
 ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,audioByteCount);
5
-ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,audioBytesPerSecond);
6
+ASFUNCTIONBODY_GETTER(NetStreamInfo,audioBytesPerSecond);
7
 ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,audioLossRate);
8
-ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,byteCount);
9
-ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,currentBytesPerSecond);
10
+ASFUNCTIONBODY_GETTER(NetStreamInfo,byteCount);
11
+ASFUNCTIONBODY_GETTER(NetStreamInfo,currentBytesPerSecond);
12
 ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,dataBufferByteLength);
13
-ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,dataBufferLength);
14
+ASFUNCTIONBODY_GETTER(NetStreamInfo,dataBufferLength);
15
 ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,dataByteCount);
16
-ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,dataBytesPerSecond);
17
+ASFUNCTIONBODY_GETTER(NetStreamInfo,dataBytesPerSecond);
18
 ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,droppedFrames);
19
 ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,isLive);
20
-ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,maxBytesPerSecond);
21
+ASFUNCTIONBODY_GETTER(NetStreamInfo,maxBytesPerSecond);
22
 ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,metaData);
23
 ASFUNCTIONBODY_GETTER(NetStreamInfo,playbackBytesPerSecond);
24
 ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,resourceName);
25
@@ -100,7 +100,7 @@
26
 ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,videoBufferByteLength);
27
 ASFUNCTIONBODY_GETTER(NetStreamInfo,videoBufferLength);
28
 ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,videoByteCount);
29
-ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,videoBytesPerSecond);
30
+ASFUNCTIONBODY_GETTER(NetStreamInfo,videoBytesPerSecond);
31
 ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,videoLossRate);
32
 ASFUNCTIONBODY_GETTER_NOT_IMPLEMENTED(NetStreamInfo,xmpData);
33
 
34
lightspark.tar.xz/src/scripting/flash/net/URLStream.cpp Changed
17
 
1
@@ -62,6 +62,7 @@
2
    _R<MemoryStreamCache> cache(_MR(new MemoryStreamCache));
3
    if(!createDownloader(cache, loader,this))
4
        return;
5
+   data->setLength(0);
6
 
7
    bool success=false;
8
    if(!downloader->hasFailed())
9
@@ -116,7 +117,6 @@
10
    CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
11
    c->setDeclaredMethodByQName("load","",Class<IFunction>::getFunction(load),NORMAL_METHOD,true);
12
    c->setDeclaredMethodByQName("close","",Class<IFunction>::getFunction(close),NORMAL_METHOD,true);
13
-   c->setDeclaredMethodByQName("load","",Class<IFunction>::getFunction(load),NORMAL_METHOD,true);
14
    c->setDeclaredMethodByQName("bytesAvailable","",Class<IFunction>::getFunction(bytesAvailable),GETTER_METHOD,true);
15
    c->setDeclaredMethodByQName("endian","",Class<IFunction>::getFunction(_getEndian),GETTER_METHOD,true);
16
    c->setDeclaredMethodByQName("endian","",Class<IFunction>::getFunction(_setEndian),SETTER_METHOD,true);
17
lightspark.tar.xz/src/scripting/flash/net/flashnet.cpp Changed
201
 
1
@@ -1032,7 +1032,7 @@
2
 NetStream::NetStream(Class_base* c):EventDispatcher(c),tickStarted(false),paused(false),closed(true),
3
    streamTime(0),frameRate(0),connection(),downloader(NULL),videoDecoder(NULL),
4
    audioDecoder(NULL),audioStream(NULL),datagenerationfile(NULL),datagenerationthreadstarted(false),client(NullRef),
5
-   oldVolume(-1.0),checkPolicyFile(false),rawAccessAllowed(false),framesdecoded(0),playbackBytesPerSecond(0),
6
+   oldVolume(-1.0),checkPolicyFile(false),rawAccessAllowed(false),framesdecoded(0),playbackBytesPerSecond(0),maxBytesPerSecond(0),datagenerationexpecttype(DATAGENERATION_HEADER),datagenerationbuffer(Class<ByteArray>::getInstanceS()),
7
    backBufferLength(0),backBufferTime(30),bufferLength(0),bufferTime(0.1),bufferTimeMax(0),
8
    maxPauseBufferTime(0)
9
 {
10
@@ -1104,6 +1104,41 @@
11
 {
12
    NetStream* th=Class<NetStream>::cast(obj);
13
    NetStreamInfo* res = Class<NetStreamInfo>::getInstanceS();
14
+   if(th->isReady())
15
+   {
16
+       res->byteCount = th->getReceivedLength();
17
+       res->dataBufferLength = th->getReceivedLength();
18
+   }
19
+   if (th->datagenerationfile)
20
+   {
21
+       int curbps = 0;
22
+       uint64_t cur=compat_msectiming();
23
+       th->countermutex.lock();
24
+       while (th->currentBytesPerSecond.size() > 0 && (cur - th->currentBytesPerSecond.front().timestamp > 1000))
25
+       {
26
+           th->currentBytesPerSecond.pop_front();
27
+       }
28
+       auto it = th->currentBytesPerSecond.cbegin();
29
+       while (it != th->currentBytesPerSecond.cend())
30
+       {
31
+           curbps += it->bytesread;
32
+           it++;
33
+       }
34
+       if (th->maxBytesPerSecond < curbps)
35
+           th->maxBytesPerSecond = curbps;
36
+
37
+       res->currentBytesPerSecond = curbps;
38
+       res->dataBytesPerSecond = curbps;
39
+       res->maxBytesPerSecond = th->maxBytesPerSecond;
40
+       
41
+       //TODO compute video/audio BytesPerSecond correctly
42
+       res->videoBytesPerSecond = curbps*3/4;
43
+       res->audioBytesPerSecond = curbps/4;
44
+       
45
+       th->countermutex.unlock();
46
+   }
47
+   else
48
+       LOG(LOG_NOT_IMPLEMENTED,"NetStreamInfo.currentBytesPerSecond/maxBytesPerSecond/dataBytesPerSecond is only implemented for data generation mode");
49
    res->playbackBytesPerSecond = th->playbackBytesPerSecond;
50
    res->audioBufferLength = th->bufferLength;
51
    res->videoBufferLength = th->bufferLength;
52
@@ -1332,8 +1367,9 @@
53
 ASFUNCTIONBODY(NetStream,seek)
54
 {
55
    //NetStream* th=Class<NetStream>::cast(obj);
56
-   LOG(LOG_NOT_IMPLEMENTED,"NetStream.seek is not implemented yet");
57
-   assert_and_throw(argslen == 1);
58
+   int pos;
59
+   ARG_UNPACK(pos);
60
+   LOG(LOG_NOT_IMPLEMENTED,"NetStream.seek is not implemented yet:"<<pos);
61
    return NULL;
62
 }
63
 
64
@@ -1357,7 +1393,138 @@
65
    {
66
        if (th->datagenerationfile)
67
        {
68
-           th->datagenerationfile->append(bytearray->getBuffer(bytearray->getLength(),false),bytearray->getLength());
69
+           //th->datagenerationfile->append(bytearray->getBuffer(bytearray->getLength(),false),bytearray->getLength());
70
+           th->datagenerationbuffer->setPosition(th->datagenerationbuffer->getLength());
71
+           th->datagenerationbuffer->writeBytes(bytearray->getBuffer(bytearray->getLength(),false),bytearray->getLength());
72
+           th->datagenerationbuffer->setPosition(0);
73
+           uint8_t tmp_byte = 0;
74
+           uint32_t processedlength = th->datagenerationbuffer->getPosition();
75
+           bool done = false;
76
+           while (!done)
77
+           {
78
+               switch (th->datagenerationexpecttype)
79
+               {
80
+                   case DATAGENERATION_HEADER:
81
+                   {
82
+                       // TODO check for correct header?
83
+                       // skip flv header
84
+                       th->datagenerationbuffer->setPosition(5);
85
+                       uint32_t headerlen = 0;
86
+                       // header length is always in big endian
87
+                       if (!th->datagenerationbuffer->readByte(tmp_byte))
88
+                       {
89
+                           done = true; 
90
+                           break;
91
+                       }
92
+                       headerlen |= tmp_byte<<24;
93
+                       if (!th->datagenerationbuffer->readByte(tmp_byte))
94
+                       {
95
+                           done = true; 
96
+                           break;
97
+                       }
98
+                       headerlen |= tmp_byte<<16;
99
+                       if (!th->datagenerationbuffer->readByte(tmp_byte))
100
+                       {
101
+                           done = true; 
102
+                           break;
103
+                       }
104
+                       headerlen |= tmp_byte<<8;
105
+                       if (!th->datagenerationbuffer->readByte(tmp_byte))
106
+                       {
107
+                           done = true; 
108
+                           break;
109
+                       }
110
+                       headerlen |= tmp_byte;
111
+                       if (headerlen > 0)
112
+                       {
113
+                           th->datagenerationbuffer->setPosition(headerlen);
114
+                           th->datagenerationexpecttype = DATAGENERATION_PREVTAG;
115
+                           processedlength+= headerlen;
116
+                       }
117
+                       else
118
+                           done = true;
119
+                       break;
120
+                   }
121
+                   case DATAGENERATION_PREVTAG:
122
+                   {
123
+                       uint32_t tmp_uint32;
124
+                       if (!th->datagenerationbuffer->readUnsignedInt(tmp_uint32)) // prevtag (value may be wrong as we don't check for big endian)
125
+                       {
126
+                           done = true;
127
+                           break;
128
+                       }
129
+                       processedlength += 4;
130
+                       th->datagenerationexpecttype = DATAGENERATION_FLVTAG;
131
+                       break;
132
+                   }
133
+                   case DATAGENERATION_FLVTAG:
134
+                   {
135
+                       if (!th->datagenerationbuffer->readByte(tmp_byte)) // tag type
136
+                       {
137
+                           done = true;
138
+                           break;
139
+                       }
140
+                       uint32_t datalen = 0;
141
+                       if (!th->datagenerationbuffer->readByte(tmp_byte)) // data len 1
142
+                       {
143
+                           done = true;
144
+                           break;
145
+                       }
146
+                       datalen |= tmp_byte<<16;
147
+                       if (!th->datagenerationbuffer->readByte(tmp_byte)) // data len 2
148
+                       {
149
+                           done = true;
150
+                           break;
151
+                       }
152
+                       datalen |= tmp_byte<<8;
153
+                       if (!th->datagenerationbuffer->readByte(tmp_byte)) // data len 3
154
+                       {
155
+                           done = true;
156
+                           break;
157
+                       }
158
+                       datalen |= tmp_byte;
159
+                       datalen += 1 + 3 + 3 + 1 + 3; 
160
+                       if (datalen + processedlength< th->datagenerationbuffer->getLength())
161
+                       {
162
+                           processedlength += datalen;
163
+                           th->datagenerationbuffer->setPosition(processedlength);
164
+                           th->datagenerationexpecttype = DATAGENERATION_PREVTAG;
165
+                       }
166
+                       break;
167
+                   }
168
+                   default:
169
+                       LOG(LOG_ERROR,"invalid DATAGENERATION_EXPECT_TYPE:"<<th->datagenerationexpecttype);
170
+                       done = true;
171
+                       break;
172
+               }
173
+           }
174
+           if (processedlength > 0)
175
+           {
176
+               th->datagenerationfile->append(th->datagenerationbuffer->getBuffer(processedlength,false),processedlength);
177
+               if (processedlength!=th->datagenerationbuffer->getLength())
178
+                   th->datagenerationbuffer->removeFrontBytes(processedlength);
179
+               else
180
+                   th->datagenerationbuffer->setLength(0);
181
+               uint64_t cur=compat_msectiming();
182
+               struct bytespertime b;
183
+               b.timestamp = cur;
184
+               b.bytesread = processedlength;
185
+               th->countermutex.lock();
186
+               th->currentBytesPerSecond.push_back(b);
187
+               while (cur - th->currentBytesPerSecond.front().timestamp > 60000)
188
+                   th->currentBytesPerSecond.pop_front();
189
+               uint32_t curbps = 0;
190
+               auto it = th->currentBytesPerSecond.cbegin();
191
+               while (it != th->currentBytesPerSecond.cend())
192
+               {
193
+                   curbps += it->bytesread;
194
+                   it++;
195
+               }
196
+               if (th->maxBytesPerSecond < curbps)
197
+                   th->maxBytesPerSecond = curbps;
198
+               
199
+               th->countermutex.unlock();
200
+           }
201
lightspark.tar.xz/src/scripting/flash/net/flashnet.h Changed
27
 
1
@@ -29,6 +29,7 @@
2
 #include "backends/decoder.h"
3
 #include "backends/interfaces/audio/IAudioPlugin.h"
4
 #include "NetStreamInfo.h"
5
+#include "scripting/flash/utils/ByteArray.h"
6
 
7
 namespace lightspark
8
 {
9
@@ -276,7 +277,16 @@
10
    uint32_t framesdecoded;
11
    uint32_t prevstreamtime;
12
    number_t playbackBytesPerSecond;
13
-   
14
+   number_t maxBytesPerSecond;
15
+
16
+   struct bytespertime {
17
+       uint64_t timestamp;
18
+       uint32_t bytesread;
19
+   };
20
+   std::deque<bytespertime> currentBytesPerSecond;
21
+   enum DATAGENERATION_EXPECT_TYPE { DATAGENERATION_HEADER=0,DATAGENERATION_PREVTAG,DATAGENERATION_FLVTAG };
22
+   DATAGENERATION_EXPECT_TYPE datagenerationexpecttype;
23
+   _NR<ByteArray> datagenerationbuffer;
24
    
25
    ASObject *createMetaDataObject(StreamDecoder* streamDecoder);
26
    ASObject *createPlayStatusObject(const tiny_string& code);
27
lightspark.tar.xz/src/scripting/flash/utils/ByteArray.cpp Changed
29
 
1
@@ -633,6 +633,13 @@
2
    bytes[position++] = b;
3
 }
4
 
5
+void ByteArray::writeBytes(uint8_t *data, int length)
6
+{
7
+   getBuffer(position+length,true);
8
+   memcpy(bytes+position,data,length);
9
+   position+=length;
10
+}
11
+
12
 ASFUNCTIONBODY(ByteArray,writeByte)
13
 {
14
    ByteArray* th=static_cast<ByteArray*>(obj);
15
@@ -1224,6 +1231,13 @@
16
    s.read((char*)bytes+oldlen,length);
17
    unlock();
18
 }
19
+void ByteArray::removeFrontBytes(int count)
20
+{
21
+   memmove(bytes,bytes+count,count);
22
+   position -= count;
23
+   len -= count;
24
+}
25
+
26
 
27
 
28
 void ByteArray::compress_zlib()
29
lightspark.tar.xz/src/scripting/flash/utils/ByteArray.h Changed
21
 
1
@@ -57,6 +57,7 @@
2
    bool readU29(uint32_t& ret);
3
    bool readUTF(tiny_string& ret);
4
    void writeByte(uint8_t b);
5
+   void writeBytes(uint8_t* data, int length);
6
    void writeShort(uint16_t val);
7
    void writeUnsignedInt(uint32_t val);
8
    void writeUTF(const tiny_string& str);
9
@@ -73,6 +74,11 @@
10
    void setPosition(uint32_t p);
11
    
12
    void append(std::streambuf* data, int length);
13
+   /**
14
+    * @brief remove bytes from front of buffer
15
+    * @param count number of bytes to remove
16
+    */
17
+   void removeFrontBytes(int count);
18
 
19
    uint8_t getObjectEncoding() const { return objectEncoding; }
20
    uint8_t getCurrentObjectEncoding() const { return currentObjectEncoding; }
21
lightspark.tar.xz/src/scripting/toplevel/Date.cpp Changed
19
 
1
@@ -181,7 +181,7 @@
2
    }
3
    if (argslen == 0) {
4
        GDateTime* tmp = g_date_time_new_now_utc();
5
-       int64_t ms = g_date_time_to_unix(tmp)*1000;
6
+       int64_t ms = g_date_time_to_unix(tmp)*1000 + g_date_time_get_microsecond (tmp)/1000;
7
        g_date_time_unref(tmp);
8
        th->MakeDateFromMilliseconds(ms);
9
    } else
10
@@ -275,7 +275,7 @@
11
 {
12
    Date* th=Class<Date>::getInstanceS();
13
    GDateTime* tmp = g_date_time_new_now_utc();
14
-   th->MakeDateFromMilliseconds(g_date_time_to_unix(tmp)*1000);
15
+   th->MakeDateFromMilliseconds(g_date_time_to_unix(tmp)*1000 + g_date_time_get_microsecond (tmp)/1000);
16
    g_date_time_unref(tmp);
17
 
18
    return Class<ASString>::getInstanceS(th->toString());
19