void FakeDecoderTask::Run() { decoder_->Decode_m(frame_, time_); frame_->Destroy(); }
void Encode_m (GMPVideoi420Frame* frame, SFrameBSInfo* encoded, GMPVideoFrameType frame_type) { // Attach a self-destructor so that this dies on return. SelfDestruct<GMPVideoi420Frame> ifd (frame); if (!host_) { return; } // Now return the encoded data back to the parent. GMPVideoFrame* ftmp; GMPErr err = host_->CreateFrame (kGMPEncodedVideoFrame, &ftmp); if (err != GMPNoErr) { GMPLOG (GL_ERROR, "Error creating encoded frame"); return; } GMPVideoEncodedFrame* f = static_cast<GMPVideoEncodedFrame*> (ftmp); // Buffer up the data. uint32_t length = 0; std::vector<uint32_t> lengths; for (int i = 0; i < encoded->iLayerNum; ++i) { lengths.push_back (0); uint8_t* tmp = encoded->sLayerInfo[i].pBsBuf; for (int j = 0; j < encoded->sLayerInfo[i].iNalCount; ++j) { lengths[i] += encoded->sLayerInfo[i].pNalLengthInByte[j]; // Convert from 4-byte start codes to GMP_BufferLength32 (NAL lengths) assert (* (reinterpret_cast<uint32_t*> (tmp)) == 0x01000000); // BufferType32 doesn't include the length of the length itself! * (reinterpret_cast<uint32_t*> (tmp)) = encoded->sLayerInfo[i].pNalLengthInByte[j] - sizeof (uint32_t); length += encoded->sLayerInfo[i].pNalLengthInByte[j]; tmp += encoded->sLayerInfo[i].pNalLengthInByte[j]; } } err = f->CreateEmptyFrame (length); if (err != GMPNoErr) { GMPLOG (GL_ERROR, "Error allocating frame data"); f->Destroy(); return; } // Copy the data. // Here we concatenate into one big buffer uint8_t* tmp = f->Buffer(); for (int i = 0; i < encoded->iLayerNum; ++i) { memcpy (tmp, encoded->sLayerInfo[i].pBsBuf, lengths[i]); tmp += lengths[i]; } f->SetEncodedWidth (frame->Width()); f->SetEncodedHeight (frame->Height()); f->SetTimeStamp (frame->Timestamp()); f->SetFrameType (frame_type); f->SetCompleteFrame (true); f->SetBufferType (GMP_BufferLength32); GMPLOG (GL_DEBUG, "Encoding complete. type= " << f->FrameType() << " length=" << f->Size() << " timestamp=" << f->TimeStamp()); // Return the encoded frame. GMPCodecSpecificInfo info; memset (&info, 0, sizeof (info)); // shouldn't be needed, we init everything info.mCodecType = kGMPVideoCodecH264; info.mBufferType = GMP_BufferLength32; info.mCodecSpecific.mH264.mSimulcastIdx = 0; if (callback_) { callback_->Encoded (f, reinterpret_cast<uint8_t*> (&info), sizeof (info)); } stats_.FrameOut(); }
void Encode_m (GMPVideoi420Frame* inputImage, GMPVideoFrameType frame_type) { if (frame_type == kGMPKeyFrame) { if (!inputImage) return; } if (!inputImage) { GMPLOG (GL_ERROR, "no input image"); return; } // Now return the encoded data back to the parent. GMPVideoFrame* ftmp; GMPErr err = host_->CreateFrame (kGMPEncodedVideoFrame, &ftmp); if (err != GMPNoErr) { GMPLOG (GL_ERROR, "Error creating encoded frame"); return; } GMPVideoEncodedFrame* f = static_cast<GMPVideoEncodedFrame*> (ftmp); // Encode this in a frame that looks a little bit like H.264. // Note that we don't do PPS or SPS. // Copy the data. This really should convert this to network byte order. EncodedFrame eframe; eframe.length_ = sizeof(eframe) - sizeof(uint32_t); eframe.h264_compat_ = 5; // Emulate a H.264 IDR NAL. eframe.magic_ = ENCODED_FRAME_MAGIC; eframe.width_ = inputImage->Width(); eframe.height_ = inputImage->Height(); eframe.y_ = AveragePlane(inputImage->Buffer(kGMPYPlane), inputImage->AllocatedSize(kGMPYPlane)); eframe.u_ = AveragePlane(inputImage->Buffer(kGMPUPlane), inputImage->AllocatedSize(kGMPUPlane)); eframe.v_ = AveragePlane(inputImage->Buffer(kGMPVPlane), inputImage->AllocatedSize(kGMPVPlane)); eframe.timestamp_ = inputImage->Timestamp(); err = f->CreateEmptyFrame (sizeof(eframe)); if (err != GMPNoErr) { GMPLOG (GL_ERROR, "Error allocating frame data"); f->Destroy(); return; } memcpy(f->Buffer(), &eframe, sizeof(eframe)); f->SetEncodedWidth (inputImage->Width()); f->SetEncodedHeight (inputImage->Height()); f->SetTimeStamp (inputImage->Timestamp()); f->SetFrameType (frame_type); f->SetCompleteFrame (true); f->SetBufferType(GMP_BufferLength32); GMPLOG (GL_DEBUG, "Encoding complete. type= " << f->FrameType() << " length=" << f->Size() << " timestamp=" << f->TimeStamp()); // Return the encoded frame. GMPCodecSpecificInfo info; memset (&info, 0, sizeof (info)); info.mCodecType = kGMPVideoCodecH264; info.mBufferType = GMP_BufferLength32; info.mCodecSpecific.mH264.mSimulcastIdx = 0; GMPLOG (GL_DEBUG, "Calling callback"); callback_->Encoded (f, reinterpret_cast<uint8_t*> (&info), sizeof(info)); GMPLOG (GL_DEBUG, "Callback called"); }