Exemplo n.º 1
0
nsresult
ChannelMediaResource::CacheClientSeek(int64_t aOffset, bool aResume)
{
  NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");

  CMLOG("CacheClientSeek requested for aOffset [%lld] for decoder [%p]",
        aOffset, mDecoder);

  CloseChannel();

  if (aResume) {
    NS_ASSERTION(mSuspendCount > 0, "Too many resumes!");
    // No need to mess with the channel, since we're making a new one
    --mSuspendCount;
  }

  mOffset = aOffset;

  if (mSuspendCount > 0) {
    // Close the existing channel to force the channel to be recreated at
    // the correct offset upon resume.
    if (mChannel) {
      mIgnoreClose = true;
      CloseChannel();
    }
    return NS_OK;
  }

  nsresult rv = RecreateChannel();
  if (NS_FAILED(rv))
    return rv;

  return OpenChannel(nullptr);
}
Exemplo n.º 2
0
void ChannelMediaResource::Suspend(bool aCloseImmediately)
{
  NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");

  MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
  if (!owner) {
    // Shutting down; do nothing.
    return;
  }
  dom::HTMLMediaElement* element = owner->GetMediaElement();
  if (!element) {
    // Shutting down; do nothing.
    return;
  }

  if (mChannel) {
    if (aCloseImmediately && mCacheStream.IsTransportSeekable()) {
      // Kill off our channel right now, but don't tell anyone about it.
      mIgnoreClose = true;
      CloseChannel();
      element->DownloadSuspended();
    } else if (mSuspendCount == 0) {
      {
        MutexAutoLock lock(mLock);
        mChannelStatistics->Stop();
      }
      PossiblySuspend();
      element->DownloadSuspended();
    }
  }

  ++mSuspendCount;
}
Exemplo n.º 3
0
nsresult ChannelMediaResource::Close()
{
  NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");

  mCacheStream.Close();
  CloseChannel();
  return NS_OK;
}
Exemplo n.º 4
0
void NetManager::ProcPendingClose()
{
	std::deque<int32> vToClose;

	{
		AUTOLOCK(m_closingQueueLock);

		while (!m_closingQueue.empty())
		{
			int32 nChannelID = m_closingQueue.front();
			m_closingQueue.pop_front();
			vToClose.push_back(nChannelID);
		}
	}

	for (auto itr = vToClose.begin(); itr != vToClose.end(); ++itr)
	{
		CloseChannel(*itr);
	}
}
Exemplo n.º 5
0
//析构函数
CChannelService::~CChannelService()
{
	CloseChannel(true,false);
	return;
}
Exemplo n.º 6
0
//IPC 消息
LRESULT CChannelService::OnIPCMessage(WPARAM wParam, LPARAM lParam)
{
	//提取数据
	tagDataHead DataHead;
	tagIPCPacket IPCPacket;
	bool bSuccess=m_DataStorage.GetData(DataHead,&IPCPacket,sizeof(IPCPacket));

	//效验数据
	ASSERT(bSuccess==true);
	ASSERT(DataHead.wDataSize>=IPCPacketSize(IPCPacket));
	ASSERT(DataHead.wDataSize==IPCPacket.Head.wDataSize+IPCPacketSize(IPCPacket));
	if (DataHead.wDataSize<IPCPacketSize(IPCPacket)) return 0;
	if (DataHead.wDataSize!=IPCPacket.Head.wDataSize+IPCPacketSize(IPCPacket)) return 0;

	//处理数据
	try
	{
		if (IPCPacket.Head.wMainCmdID==IPC_MIAN_IPC_KERNEL)	
		{
			//内核消息
			switch (IPCPacket.Head.wSubCmdID)
			{
			case IPC_SUB_IPC_CLIENT_CONNECT:	//连接消息
				{
					//处理通知
					if (m_pIChannelEventSink!=NULL) m_pIChannelEventSink->OnChannelConnect(IPCPacket.hWndSend);

					//发送通知
					CIPCSendCopyData SendCopyData;
					SendCopyData.SetClientHwnd(m_hWnd);
					SendCopyData.SetServerHwnd(IPCPacket.hWndSend);
					SendCopyData.SendData(IPC_MIAN_IPC_KERNEL,IPC_SUB_IPC_SERVER_ACCEPT);

					break;
				}
			case IPC_SUB_IPC_SERVER_ACCEPT:		//应答消息
				{
					//处理通知
					if (m_pIChannelEventSink!=NULL)	m_pIChannelEventSink->OnChannelAccept(IPCPacket.hWndSend);

					break;
				}
			case IPC_SUB_IPC_CLIENT_CLOSE:		//关闭消息
				{
					//关闭连接
					CloseChannel(false,true);

					break;
				}
			default: ASSERT(0);
			}
		}
		else	//外围消息
		{
			if (m_pIChannelMessageSink!=NULL)
			{
				WORD wDataSize=IPCPacket.Head.wDataSize;
				m_pIChannelMessageSink->OnChannelMessage(&IPCPacket.Head,IPCPacket.cbBuffer,wDataSize,IPCPacket.hWndSend);
			}
		}
	}
	catch (...)	{ }

	return 0;
}
	void ChannelsManager::CloseAllChannels ()
	{
		Q_FOREACH (auto ich, ChannelHandlers_.values ())
			ich->CloseChannel ();
	}
Exemplo n.º 8
0
nsresult
ChannelMediaResource::OnStartRequest(nsIRequest* aRequest)
{
  NS_ASSERTION(mChannel.get() == aRequest, "Wrong channel!");

  MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
  NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
  dom::HTMLMediaElement* element = owner->GetMediaElement();
  NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
  nsresult status;
  nsresult rv = aRequest->GetStatus(&status);
  NS_ENSURE_SUCCESS(rv, rv);

  if (element->ShouldCheckAllowOrigin()) {
    // If the request was cancelled by nsCORSListenerProxy due to failing
    // the CORS security check, send an error through to the media element.
    if (status == NS_ERROR_DOM_BAD_URI) {
      mDecoder->NetworkError();
      return NS_ERROR_DOM_BAD_URI;
    }
  }

  nsCOMPtr<nsIHttpChannel> hc = do_QueryInterface(aRequest);
  bool seekable = false;
  if (hc) {
    uint32_t responseStatus = 0;
    hc->GetResponseStatus(&responseStatus);
    bool succeeded = false;
    hc->GetRequestSucceeded(&succeeded);

    if (!succeeded && NS_SUCCEEDED(status)) {
      // HTTP-level error (e.g. 4xx); treat this as a fatal network-level error.
      // We might get this on a seek.
      // (Note that lower-level errors indicated by NS_FAILED(status) are
      // handled in OnStopRequest.)
      // A 416 error should treated as EOF here... it's possible
      // that we don't get Content-Length, we read N bytes, then we
      // suspend and resume, the resume reopens the channel and we seek to
      // offset N, but there are no more bytes, so we get a 416
      // "Requested Range Not Satisfiable".
      if (responseStatus == HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE) {
        // OnStopRequest will not be fired, so we need to do some of its
        // work here.
        mCacheStream.NotifyDataEnded(status);
      } else {
        mDecoder->NetworkError();
      }

      // This disconnects our listener so we don't get any more data. We
      // certainly don't want an error page to end up in our cache!
      CloseChannel();
      return NS_OK;
    }

    nsAutoCString ranges;
    hc->GetResponseHeader(NS_LITERAL_CSTRING("Accept-Ranges"),
                          ranges);
    bool acceptsRanges = ranges.EqualsLiteral("bytes");
    // True if this channel will not return an unbounded amount of data
    bool dataIsBounded = false;

    int64_t contentLength = -1;
    hc->GetContentLength(&contentLength);
    if (contentLength >= 0 && responseStatus == HTTP_OK_CODE) {
      // "OK" status means Content-Length is for the whole resource.
      // Since that's bounded, we know we have a finite-length resource.
      dataIsBounded = true;
    }

    if (mOffset == 0) {
      // Look for duration headers from known Ogg content systems.
      // In the case of multiple options for obtaining the duration
      // the order of precedence is:
      // 1) The Media resource metadata if possible (done by the decoder itself).
      // 2) Content-Duration message header.
      // 3) X-AMZ-Meta-Content-Duration.
      // 4) X-Content-Duration.
      // 5) Perform a seek in the decoder to find the value.
      nsAutoCString durationText;
      nsresult ec = NS_OK;
      rv = hc->GetResponseHeader(NS_LITERAL_CSTRING("Content-Duration"), durationText);
      if (NS_FAILED(rv)) {
        rv = hc->GetResponseHeader(NS_LITERAL_CSTRING("X-AMZ-Meta-Content-Duration"), durationText);
      }
      if (NS_FAILED(rv)) {
        rv = hc->GetResponseHeader(NS_LITERAL_CSTRING("X-Content-Duration"), durationText);
      }

      // If there is a Content-Duration header with a valid value, record
      // the duration.
      if (NS_SUCCEEDED(rv)) {
        double duration = durationText.ToDouble(&ec);
        if (ec == NS_OK && duration >= 0) {
          mDecoder->SetDuration(duration);
          // We know the resource must be bounded.
          dataIsBounded = true;
        }
      }
    }

    // Assume Range requests have a bounded upper limit unless the
    // Content-Range header tells us otherwise.
    bool boundedSeekLimit = true;
    // Check response code for byte-range requests (seeking, chunk requests).
    if (!mByteRange.IsNull() && (responseStatus == HTTP_PARTIAL_RESPONSE_CODE)) {
      // Parse Content-Range header.
      int64_t rangeStart = 0;
      int64_t rangeEnd = 0;
      int64_t rangeTotal = 0;
      rv = ParseContentRangeHeader(hc, rangeStart, rangeEnd, rangeTotal);
      if (NS_FAILED(rv)) {
        // Content-Range header text should be parse-able.
        CMLOG("Error processing \'Content-Range' for "
              "HTTP_PARTIAL_RESPONSE_CODE: rv[%x] channel[%p] decoder[%p]",
              rv, hc.get(), mDecoder);
        mDecoder->NetworkError();
        CloseChannel();
        return NS_OK;
      }

      // Give some warnings if the ranges are unexpected.
      // XXX These could be error conditions.
      NS_WARN_IF_FALSE(mByteRange.mStart == rangeStart,
                       "response range start does not match request");
      NS_WARN_IF_FALSE(mOffset == rangeStart,
                       "response range start does not match current offset");
      NS_WARN_IF_FALSE(mByteRange.mEnd == rangeEnd,
                       "response range end does not match request");
      // Notify media cache about the length and start offset of data received.
      // Note: If aRangeTotal == -1, then the total bytes is unknown at this stage.
      //       For now, tell the decoder that the stream is infinite.
      if (rangeTotal == -1) {
        boundedSeekLimit = false;
      } else {
        mCacheStream.NotifyDataLength(rangeTotal);
      }
      mCacheStream.NotifyDataStarted(rangeStart);

      mOffset = rangeStart;
      // We received 'Content-Range', so the server accepts range requests.
      acceptsRanges = true;
    } else if (((mOffset > 0) || !mByteRange.IsNull())
               && (responseStatus == HTTP_OK_CODE)) {
      // If we get an OK response but we were seeking, or requesting a byte
      // range, then we have to assume that seeking doesn't work. We also need
      // to tell the cache that it's getting data for the start of the stream.
      mCacheStream.NotifyDataStarted(0);
      mOffset = 0;

      // The server claimed it supported range requests.  It lied.
      acceptsRanges = false;
    } else if (mOffset == 0 &&
               (responseStatus == HTTP_OK_CODE ||
                responseStatus == HTTP_PARTIAL_RESPONSE_CODE)) {
      if (contentLength >= 0) {
        mCacheStream.NotifyDataLength(contentLength);
      }
    }
    // XXX we probably should examine the Content-Range header in case
    // the server gave us a range which is not quite what we asked for

    // If we get an HTTP_OK_CODE response to our byte range request,
    // and the server isn't sending Accept-Ranges:bytes then we don't
    // support seeking.
    seekable =
      responseStatus == HTTP_PARTIAL_RESPONSE_CODE || acceptsRanges;
    if (seekable && boundedSeekLimit) {
      // If range requests are supported, and we did not see an unbounded
      // upper range limit, we assume the resource is bounded.
      dataIsBounded = true;
    }

    mDecoder->SetInfinite(!dataIsBounded);
  }
  mDecoder->SetTransportSeekable(seekable);
  mCacheStream.SetTransportSeekable(seekable);

  {
    MutexAutoLock lock(mLock);
    mIsTransportSeekable = seekable;
    mChannelStatistics->Start();
  }

  mReopenOnError = false;
  // If we are seeking to get metadata, because we are playing an OGG file,
  // ignore if the channel gets closed without us suspending it explicitly. We
  // don't want to tell the element that the download has finished whereas we
  // just happended to have reached the end of the media while seeking.
  mIgnoreClose = mSeekingForMetadata;

  if (mSuspendCount > 0) {
    // Re-suspend the channel if it needs to be suspended
    // No need to call PossiblySuspend here since the channel is
    // definitely in the right state for us in OnStartRequest.
    mChannel->Suspend();
    mIgnoreResume = false;
  }

  // Fires an initial progress event and sets up the stall counter so stall events
  // fire if no download occurs within the required time frame.
  mDecoder->Progress(false);

  return NS_OK;
}
Exemplo n.º 9
0
	void ChannelHandler::Leave (const QString& msg)
	{
		CM_->LeaveChannel (ChannelOptions_.ChannelName_.toLower (), msg);
		CloseChannel ();
	}
Exemplo n.º 10
0
void stopRadio(){
	DestroyAnalyzer(CHANNEL_RX);
	SetChannelState(CHANNEL_RX,0,0);
	CloseChannel(CHANNEL_RX);
}