| 688 | } |
| 689 | |
| 690 | void Encode_m (GMPVideoi420Frame* frame, SFrameBSInfo* encoded, |
| 691 | GMPVideoFrameType frame_type) { |
| 692 | // Attach a self-destructor so that this dies on return. |
| 693 | SelfDestruct<GMPVideoi420Frame> ifd (frame); |
| 694 | |
| 695 | if (!host_) { |
| 696 | return; |
| 697 | } |
| 698 | |
| 699 | // Now return the encoded data back to the parent. |
| 700 | GMPVideoFrame* ftmp; |
| 701 | GMPErr err = host_->CreateFrame (kGMPEncodedVideoFrame, &ftmp); |
| 702 | if (err != GMPNoErr) { |
| 703 | GMPLOG (GL_ERROR, "Error creating encoded frame"); |
| 704 | return; |
| 705 | } |
| 706 | |
| 707 | GMPVideoEncodedFrame* f = static_cast<GMPVideoEncodedFrame*> (ftmp); |
| 708 | // Buffer up the data. |
| 709 | uint32_t length = 0; |
| 710 | std::vector<uint32_t> lengths; |
| 711 | unsigned char temporalId = 0; |
| 712 | |
| 713 | for (int i = 0; i < encoded->iLayerNum; ++i) { |
| 714 | lengths.push_back (0); |
| 715 | uint8_t* tmp = encoded->sLayerInfo[i].pBsBuf; |
| 716 | assert(encoded->sLayerInfo[i].uiSpatialId == 0); |
| 717 | temporalId = encoded->sLayerInfo[i].uiTemporalId; |
| 718 | for (int j = 0; j < encoded->sLayerInfo[i].iNalCount; ++j) { |
| 719 | lengths[i] += encoded->sLayerInfo[i].pNalLengthInByte[j]; |
| 720 | // Convert from 4-byte start codes to GMP_BufferLength32 (NAL lengths) |
| 721 | assert (* (reinterpret_cast<uint32_t*> (tmp)) == 0x01000000); |
| 722 | // BufferType32 doesn't include the length of the length itself! |
| 723 | * (reinterpret_cast<uint32_t*> (tmp)) = encoded->sLayerInfo[i].pNalLengthInByte[j] - sizeof (uint32_t); |
| 724 | length += encoded->sLayerInfo[i].pNalLengthInByte[j]; |
| 725 | tmp += encoded->sLayerInfo[i].pNalLengthInByte[j]; |
| 726 | } |
| 727 | } |
| 728 | |
| 729 | err = f->CreateEmptyFrame (length); |
| 730 | if (err != GMPNoErr) { |
| 731 | GMPLOG (GL_ERROR, "Error allocating frame data"); |
| 732 | f->Destroy(); |
| 733 | return; |
| 734 | } |
| 735 | |
| 736 | // Copy the data. |
| 737 | // Here we concatenate into one big buffer |
| 738 | uint8_t* tmp = f->Buffer(); |
| 739 | for (int i = 0; i < encoded->iLayerNum; ++i) { |
| 740 | memcpy (tmp, encoded->sLayerInfo[i].pBsBuf, lengths[i]); |
| 741 | tmp += lengths[i]; |
| 742 | } |
| 743 | |
| 744 | f->SetEncodedWidth (frame->Width()); |
| 745 | f->SetEncodedHeight (frame->Height()); |
| 746 | f->SetTimeStamp (frame->Timestamp()); |
| 747 | f->SetFrameType (frame_type); |