int MediaBridgeSession::SendVideo() { VideoDecoder *decoder = VideoCodecFactory::CreateDecoder(VideoCodec::SORENSON); VideoEncoder *encoder = VideoCodecFactory::CreateEncoder(rtpVideoCodec); DWORD width = 0; DWORD height = 0; DWORD numpixels = 0; QWORD lastVideoTs = 0; Log(">SendVideo\n"); //Set video format if (!rtpVideo.SetSendingCodec(rtpVideoCodec)) //Error return Error("Peer do not support [%d,%s]\n",rtpVideoCodec,VideoCodec::GetNameFor(rtpVideoCodec)); //While sending video while (sendingVideo) { //Wait for next video if (!videoFrames.Wait(0)) //Check again continue; //Get audio grame RTMPVideoFrame* video = videoFrames.Pop(); //check if (!video) //Again continue; //Get time difference DWORD diff = 0; //Get timestam QWORD ts = video->GetTimestamp(); //If it is not the first frame if (lastVideoTs) //Calculate it diff = ts - lastVideoTs; //Set the last audio timestamp lastVideoTs = ts; //Check if (video->GetVideoCodec()!=RTMPVideoFrame::FLV1) //Error continue; //Decode frame if (!decoder->Decode(video->GetMediaData(),video->GetMediaSize())) { Error("decode packet error"); //Next continue; } //Check size if (decoder->GetWidth()!=width || decoder->GetHeight()!=height) { //Get dimension width = decoder->GetWidth(); height = decoder->GetHeight(); //Set size numpixels = width*height*3/2; //Set also frame rate and bps encoder->SetFrameRate(25,300,500); //Set them in the encoder encoder->SetSize(width,height); } //Check size if (!numpixels) { Error("numpixels equals 0"); //Next continue; } //Check fpu if (sendFPU) { //Send it encoder->FastPictureUpdate(); //Reset sendFPU = false; } //Encode it VideoFrame *videoFrame = encoder->EncodeFrame(decoder->GetFrame(),numpixels); //If was failed if (!videoFrame) { Log("No video frame\n"); //Next continue; } //Set frame time videoFrame->SetTimestamp(diff); //Send it smoothly smoother.SendFrame(videoFrame,diff); //Delete video frame delete(video); } Log("<SendVideo\n"); return 1; }
Vdec_ReturnType vdec_post_input_buffer(struct VDecoder *dec, video_input_frame_info *frame, void *cookie) { QTV_MSG_PRIO3(QTVDIAG_GENERAL,QTVDIAG_PRIO_LOW,"vdec: post_input data=%p len=%d cookie=%p\n", frame->data, frame->len, cookie); #ifdef LOG_INPUT_BUFFERS static int take_input = 1; #endif int fatal_err = 0; /*checkBufAvail flag is needed since we do not need to checkout * YUV/Slice buffer incase the NAL corresponds to same frame. * This is required for multiple NALs in one input buffer */ bool checkBufAvail = true; VDEC_INPUT_BUFFER input; VideoDecoder *pDec = (VideoDecoder*)(dec->core); VDEC_ERROR err = VDEC_ERR_EVERYTHING_FINE; if (NULL == dec || NULL == frame || NULL == frame->data ) { QTV_MSG_PRIO3(QTVDIAG_GENERAL,QTVDIAG_PRIO_ERROR,"vdec: error: encountered NULL parameter dec: 0x%x frame: 0x%x data: 0x%x\n", (unsigned int)dec, (unsigned int)frame, (unsigned int)frame->data); return VDEC_EFAILED; } input.buffer[0] = (unsigned char*)frame->data; input.timestamp[0] = (long long)frame->timestamp; input.buffer_size[0] = (unsigned long int)frame->len; input.buffer_pos[0] = 0; input.layers = 1; input.eOSIndicator[0]= false; QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"vdec: received ts: %lld", frame->timestamp); if (frame->timestamp < timestamp ) { QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"vdec: error: out of order stamp! %d < %d\n", (int)(frame->timestamp&0xFFFFFFFF), timestamp); } timestamp = (int)frame->timestamp; QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"vdec: vdec_core_post_input. buffer_size[0]: %ld frame->flags: 0x%x\n", input.buffer_size[0], frame->flags); if (input.buffer_size[0] == 0 && frame->flags & FRAME_FLAG_EOS) { QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_LOW,"vdec: Zero-length buffer with EOS bit set\n"); input.eOSIndicator[0] = true; if(pDec) err = pDec->EOS( ); else err = VDEC_ERR_NULL_STREAM_ID; if(VDEC_ERR_OUT_OF_BUFFERS == err) return VDEC_EOUTOFBUFFERS; vdec_decoder_info->ctxt->buffer_done(vdec_decoder_info->ctxt, cookie); if (VDEC_ERR_EVERYTHING_FINE == err) return VDEC_SUCCESS; return VDEC_EFAILED; } QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_LOW,"vdec: vdec_core_post_input\n"); #ifdef LOG_INPUT_BUFFERS if (take_input) { fwritex((unsigned char*)frame->data, frame->len, pInputFile); QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_HIGH,"vdec: frame %d frame->len %d\n", counter++, frame->len); } #endif do { QPERF_TIME(arm_decode, err = pDec->Decode( &input, checkBufAvail )); if (VDEC_ERR_EVERYTHING_FINE != err) { QTV_MSG_PRIO1(QTVDIAG_GENERAL,QTVDIAG_PRIO_HIGH,"vdec: vdec_decoder error: %d\n", (int)err); if(VDEC_ERR_UNSUPPORTED_DIMENSIONS == err) { fatal_err = 1; break; } } checkBufAvail = false; } while( ( VDEC_ERR_EVERYTHING_FINE == err ) && ( 0 != input.buffer_size[0] ) ); #ifdef LOG_INPUT_BUFFERS take_input = (err==14?0:1); #endif if(VDEC_ERR_OUT_OF_BUFFERS == err) return VDEC_EOUTOFBUFFERS; vdec_input_buffer_release_cb_handler(pDec,&input,cookie); if(VDEC_ERR_EVERYTHING_FINE == err) return VDEC_SUCCESS; if(fatal_err) { static struct vdec_frame frame; memset(&frame, 0, sizeof(frame)); frame.flags |= FRAME_FLAG_FATAL_ERROR; QPERF_END(frame_data); vdec_decoder_info->ctxt->frame_done(vdec_decoder_info->ctxt, &frame); } return VDEC_EFAILED; }