Ejemplo n.º 1
0
  void Decode_w (GMPVideoEncodedFrame* inputFrame,
                 bool missingFrames,
                 DECODING_STATE& dState,
                 int64_t renderTimeMs = -1) {
    GMPLOG (GL_DEBUG, "Frame decode on worker thread length = "
            << inputFrame->Size());

    SBufferInfo decoded;
    bool valid = false;
    memset (&decoded, 0, sizeof (decoded));
    unsigned char* data[3] = {nullptr, nullptr, nullptr};

    dState = decoder_->DecodeFrameNoDelay (inputFrame->Buffer(),
                                     inputFrame->Size(),
                                     data,
                                     &decoded);

    if (dState) {
      GMPLOG (GL_ERROR, "Decoding error dState=" << dState);
    } else {
      valid = true;
    }

    TrySyncRunOnMainThread (WrapTask (
                                 this,
                                 &OpenH264VideoDecoder::Decode_m,
                                 inputFrame,
                                 &decoded,
                                 data,
                                 renderTimeMs,
                                 valid));
  }
Ejemplo n.º 2
0
  virtual void Decode (GMPVideoEncodedFrame* inputFrame,
                       bool missingFrames,
                       const uint8_t* aCodecSpecificInfo,
                       uint32_t aCodecSpecificInfoLength,
                       int64_t renderTimeMs = -1) {
    GMPLOG (GL_DEBUG, __FUNCTION__
            << "Decoding frame size=" << inputFrame->Size()
            << " timestamp=" << inputFrame->TimeStamp());
    stats_.FrameIn();
    //const GMPCodecSpecificInfo *codecSpecificInfo = (GMPCodecSpecificInfo) aCodecSpecificInfo;

    // Convert to H.264 start codes
    switch (inputFrame->BufferType()) {
    case GMP_BufferSingle:
    case GMP_BufferLength8:
    case GMP_BufferLength16:
    case GMP_BufferLength24:
      // We should look to support these, especially GMP_BufferSingle
      assert (false);
      break;

    case GMP_BufferLength32: {
      uint8_t* start_code = inputFrame->Buffer();
      while (start_code < inputFrame->Buffer() + inputFrame->Size()) {
        static const uint8_t code[] = { 0x00, 0x00, 0x00, 0x01 };
        uint8_t* lenp = start_code;
        start_code += * (reinterpret_cast<int32_t*> (lenp));
        memcpy (lenp, code, 4);
      }
    }
    break;

    default:
      assert (false);
      break;
    }
    DECODING_STATE dState = dsErrorFree;
    worker_thread_->Post (WrapTask (
                            this, &OpenH264VideoDecoder::Decode_w,
                            inputFrame,
                            missingFrames,
                            dState,
                            renderTimeMs));
    if (dState) {
      Error(GMPGenericErr);
    }
  }
Ejemplo n.º 3
0
  virtual void Encode (GMPVideoi420Frame* inputImage,
                       const uint8_t* aCodecSpecificInfo,
                       uint32_t aCodecSpecificInfoLength,
                       const GMPVideoFrameType* aFrameTypes,
                       uint32_t aFrameTypesLength) {
    GMPLOG (GL_DEBUG,
            __FUNCTION__
            << " size="
            << inputImage->Width() << "x" << inputImage->Height());

    stats_.FrameIn();

    assert (aFrameTypesLength != 0);

    worker_thread_->Post (WrapTask (
                            this, &OpenH264VideoEncoder::Encode_w,
                            inputImage,
                            (aFrameTypes)[0]));
  }
Ejemplo n.º 4
0
  void Encode_w (GMPVideoi420Frame* inputImage,
                 GMPVideoFrameType frame_type) {
    SFrameBSInfo encoded;

    if (frame_type  == kGMPKeyFrame) {
      encoder_->ForceIntraFrame (true);
      if (!inputImage)
        return;
    }
    if (!inputImage) {
      GMPLOG (GL_ERROR, "no input image");
      return;
    }
    SSourcePicture src;

    src.iColorFormat = videoFormatI420;
    src.iStride[0] = inputImage->Stride (kGMPYPlane);
    src.pData[0] = reinterpret_cast<unsigned char*> (
                     const_cast<uint8_t*> (inputImage->Buffer (kGMPYPlane)));
    src.iStride[1] = inputImage->Stride (kGMPUPlane);
    src.pData[1] = reinterpret_cast<unsigned char*> (
                     const_cast<uint8_t*> (inputImage->Buffer (kGMPUPlane)));
    src.iStride[2] = inputImage->Stride (kGMPVPlane);
    src.pData[2] = reinterpret_cast<unsigned char*> (
                     const_cast<uint8_t*> (inputImage->Buffer (kGMPVPlane)));
    src.iStride[3] = 0;
    src.pData[3] = nullptr;
    src.iPicWidth = inputImage->Width();
    src.iPicHeight = inputImage->Height();
    src.uiTimeStamp = inputImage->Timestamp() / 1000; //encoder needs millisecond
    const SSourcePicture* pics = &src;

    int result = encoder_->EncodeFrame (pics, &encoded);
    if (result != cmResultSuccess) {
      GMPLOG (GL_ERROR, "Couldn't encode frame. Error = " << result);
    }


    // Translate int to enum
    GMPVideoFrameType encoded_type;
    bool has_frame = false;

    switch (encoded.eFrameType) {
    case videoFrameTypeIDR:
      encoded_type = kGMPKeyFrame;
      has_frame = true;
      break;
    case videoFrameTypeI:
      encoded_type = kGMPKeyFrame;
      has_frame = true;
      break;
    case videoFrameTypeP:
      encoded_type = kGMPDeltaFrame;
      has_frame = true;
      break;
    case videoFrameTypeSkip:
      // Can skip the call back since no actual bitstream will be generated
      break;
    case videoFrameTypeIPMixed://this type is currently not suppported
    case videoFrameTypeInvalid:
      GMPLOG (GL_ERROR, "Couldn't encode frame. Type = "
              << encoded.eFrameType);
      break;
    default:
      // The API is defined as returning a type.
      assert (false);
      break;
    }

    if (!has_frame) {
      // This frame must be destroyed on the main thread.
      TrySyncRunOnMainThread (WrapTask (
                                   this,
                                   &OpenH264VideoEncoder::DestroyInputFrame_m,
                                   inputImage));
      return;
    }

    // Synchronously send this back to the main thread for delivery.
    TrySyncRunOnMainThread (WrapTask (
                                   this,
                                   &OpenH264VideoEncoder::Encode_m,
                                   inputImage,
                                   &encoded,
                                   encoded_type));
  }