On x86 compilers without fastcall, simulate it when invoking traces and un-simulate...
[wine-gecko.git] / content / media / video / src / nsChannelReader.cpp
blobb14ad80bb9097d6fc500219ae4e7aaf2c9d13841
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is Mozilla code.
18 * The Initial Developer of the Original Code is the Mozilla Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2007
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Chris Double <chris.double@double.co.nz>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
38 #include "nsAString.h"
39 #include "nsThreadUtils.h"
40 #include "nsNetUtil.h"
41 #include "prlog.h"
42 #include "nsOggDecoder.h"
43 #include "nsChannelReader.h"
45 nsChannelToPipeListener::nsChannelToPipeListener(nsOggDecoder* aDecoder) :
46 mDecoder(aDecoder),
47 mIntervalStart(0),
48 mIntervalEnd(0),
49 mTotalBytes(0)
53 nsresult nsChannelToPipeListener::Init()
55 nsresult rv = NS_NewPipe(getter_AddRefs(mInput),
56 getter_AddRefs(mOutput),
57 0,
58 PR_UINT32_MAX);
59 NS_ENSURE_SUCCESS(rv, rv);
61 return NS_OK;
64 void nsChannelToPipeListener::Stop()
66 mDecoder = nsnull;
67 mInput = nsnull;
68 mOutput = nsnull;
69 mDecoder = nsnull;
72 double nsChannelToPipeListener::BytesPerSecond() const
74 return mTotalBytes / ((PR_IntervalToMilliseconds(mIntervalEnd-mIntervalStart)) / 1000.0);
77 void nsChannelToPipeListener::GetInputStream(nsIInputStream** aStream)
79 if (aStream) {
80 NS_IF_ADDREF(*aStream = mInput);
84 nsresult nsChannelToPipeListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
86 mIntervalStart = PR_IntervalNow();
87 mIntervalEnd = mIntervalStart;
88 mTotalBytes = 0;
89 mDecoder->UpdateBytesDownloaded(mTotalBytes);
90 return NS_OK;
93 nsresult nsChannelToPipeListener::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatus)
95 mOutput = nsnull;
96 if (mDecoder) {
97 mDecoder->ResourceLoaded();
99 return NS_OK;
102 nsresult nsChannelToPipeListener::OnDataAvailable(nsIRequest* aRequest,
103 nsISupports* aContext,
104 nsIInputStream* aStream,
105 PRUint32 aOffset,
106 PRUint32 aCount)
108 if (mOutput) {
109 PRUint32 bytes = 0;
111 do {
112 nsresult rv = mOutput->WriteFrom(aStream, aCount, &bytes);
113 NS_ENSURE_SUCCESS(rv, rv);
115 aCount -= bytes;
116 mTotalBytes += bytes;
117 mDecoder->UpdateBytesDownloaded(mTotalBytes);
118 } while (aCount) ;
120 nsresult rv = mOutput->Flush();
121 NS_ENSURE_SUCCESS(rv, rv);
122 mIntervalEnd = PR_IntervalNow();
124 return NS_OK;
127 NS_IMPL_ISUPPORTS2(nsChannelToPipeListener, nsIRequestObserver, nsIStreamListener)
129 PRUint32 nsChannelReader::Available()
131 PRUint32 available = 0;
132 mInput->Available(&available);
133 return available;
136 double nsChannelReader::BytesPerSecond() const
138 return mListener->BytesPerSecond();
141 OggPlayErrorCode nsChannelReader::initialise(int aBlock)
143 return E_OGGPLAY_OK;
146 OggPlayErrorCode nsChannelReader::destroy()
148 mChannel->Cancel(NS_BINDING_ABORTED);
149 mChannel = nsnull;
150 mInput->Close();
151 mInput = nsnull;
152 mListener->Stop();
153 mListener = nsnull;
155 return E_OGGPLAY_OK;
158 size_t nsChannelReader::io_read(char* aBuffer, size_t aCount)
160 PRUint32 bytes = 0;
161 nsresult rv = mInput->Read(aBuffer, aCount, &bytes);
162 if (!NS_SUCCEEDED(rv)) {
163 bytes = 0;
166 mCurrentPosition += bytes;
167 return bytes == 0 ? static_cast<size_t>(OGGZ_ERR_SYSTEM) : bytes;
170 int nsChannelReader::io_seek(long aOffset, int aWhence)
172 // How to implement seek in channels?
173 // fseek(file, offset, whence);
175 return -1;
178 long nsChannelReader::io_tell()
180 return mCurrentPosition;
183 static OggPlayErrorCode oggplay_channel_reader_initialise(OggPlayReader* aReader, int aBlock)
185 nsChannelReader * me = static_cast<nsChannelReader*>(aReader);
187 if (me == NULL) {
188 return E_OGGPLAY_BAD_READER;
190 return me->initialise(aBlock);
193 static OggPlayErrorCode oggplay_channel_reader_destroy(OggPlayReader* aReader)
195 nsChannelReader* me = static_cast<nsChannelReader*>(aReader);
196 OggPlayErrorCode result = me->destroy();
197 delete me;
198 return result;
201 static size_t oggplay_channel_reader_io_read(void* aReader, void* aBuffer, size_t aCount)
203 nsChannelReader* me = static_cast<nsChannelReader*>(aReader);
204 return me->io_read(static_cast<char*>(aBuffer), aCount);
207 static int oggplay_channel_reader_io_seek(void* aReader, long aOffset, int aWhence)
209 nsChannelReader* me = static_cast<nsChannelReader*>(aReader);
210 return me->io_seek(aOffset, aWhence);
213 static long oggplay_channel_reader_io_tell(void* aReader)
215 nsChannelReader* me = static_cast<nsChannelReader*>(aReader);
216 return me->io_tell();
219 nsresult nsChannelReader::Init(nsOggDecoder* aDecoder, nsIURI* aURI)
221 nsresult rv;
223 mCurrentPosition = 0;
224 mListener = new nsChannelToPipeListener(aDecoder);
225 NS_ENSURE_TRUE(mListener, NS_ERROR_OUT_OF_MEMORY);
227 rv = mListener->Init();
228 NS_ENSURE_SUCCESS(rv, rv);
230 rv = NS_NewChannel(getter_AddRefs(mChannel),
231 aURI,
232 nsnull,
233 nsnull,
234 nsnull,
235 nsIRequest::LOAD_NORMAL);
236 NS_ENSURE_SUCCESS(rv, rv);
238 rv = mChannel->AsyncOpen(mListener, nsnull);
239 NS_ENSURE_SUCCESS(rv, rv);
241 mListener->GetInputStream(getter_AddRefs(mInput));
243 return NS_OK;
246 nsChannelReader::nsChannelReader()
248 OggPlayReader* reader = this;
249 reader->initialise = &oggplay_channel_reader_initialise;
250 reader->destroy = &oggplay_channel_reader_destroy;
251 reader->seek = nsnull;
252 reader->io_read = &oggplay_channel_reader_io_read;
253 reader->io_seek = &oggplay_channel_reader_io_seek;
254 reader->io_tell = &oggplay_channel_reader_io_tell;