Пример #1
0
static void dec_process(MSFilter *f){
	DecData *d=(DecData*)f->data;
	mblk_t *im;
	MSQueue nalus;
	AVFrame orig;
	ms_queue_init(&nalus);
	while((im=ms_queue_get(f->inputs[0]))!=NULL){
		/*push the sps/pps given in sprop-parameter-sets if any*/
		if (d->packet_num==0 && d->sps && d->pps){
			mblk_set_timestamp_info(d->sps,mblk_get_timestamp_info(im));
			mblk_set_timestamp_info(d->pps,mblk_get_timestamp_info(im));
			rfc3984_unpack(&d->unpacker,d->sps,&nalus);
			rfc3984_unpack(&d->unpacker,d->pps,&nalus);
			d->sps=NULL;
			d->pps=NULL;
		}
		rfc3984_unpack(&d->unpacker,im,&nalus);
		if (!ms_queue_empty(&nalus)){
			int size;
			uint8_t *p,*end;
			bool_t need_reinit=FALSE;

			size=nalusToFrame(d,&nalus,&need_reinit);
			if (need_reinit)
				dec_reinit(d);
			p=d->bitstream;
			end=d->bitstream+size;
			while (end-p>0) {
				int len;
				int got_picture=0;
				AVPacket pkt;
				avcodec_get_frame_defaults(&orig);
				av_init_packet(&pkt);
				pkt.data = p;
				pkt.size = end-p;
				len=avcodec_decode_video2(&d->av_context,&orig,&got_picture,&pkt);
				if (len<=0) {
					ms_warning("ms_AVdecoder_process: error %i.",len);
					if ((f->ticker->time - d->last_error_reported_time)>5000 || d->last_error_reported_time==0) {
						d->last_error_reported_time=f->ticker->time;
						ms_filter_notify_no_arg(f,MS_VIDEO_DECODER_DECODING_ERRORS);
					}
					break;
				}
				if (got_picture) {
					ms_queue_put(f->outputs[0],get_as_yuvmsg(f,d,&orig));
					if (!d->first_image_decoded) {
						ms_filter_notify_no_arg(f,MS_VIDEO_DECODER_FIRST_IMAGE_DECODED);
						d->first_image_decoded = TRUE;
					}
				}
				p+=len;
			}
		}
		d->packet_num++;
	}
}
Пример #2
0
/* remove payload header and aggregates fragmented packets */
static void dec_unpacketize(MSFilter *f, DecState *s, mblk_t *im, MSQueue *out){
	int xbit = (im->b_rptr[0] & 0x80) >> 7;
	im->b_rptr++;
	if (xbit) {
		/* Ignore extensions if some are present */
		int ibit = (im->b_rptr[0] & 0x80) >> 7;
		int lbit = (im->b_rptr[0] & 0x40) >> 6;
		int tbit = (im->b_rptr[0] & 0x20) >> 5;
		int kbit = (im->b_rptr[0] & 0x10) >> 4;
		int mbit = 0;
		if (ibit) {
			mbit = (im->b_rptr[1] & 0x80) >> 7;
		}
		im->b_rptr += (ibit + lbit + (tbit | kbit) + mbit);
	}

	/* end of frame bit ? */
	if (mblk_get_marker_info(im)) {
		/* should be aggregated with previous packet ? */
		if (s->curframe!=NULL){
			/* same timestamp ? */
			if (mblk_get_timestamp_info(im) == mblk_get_timestamp_info(s->curframe)) {
				concatb(s->curframe,im);
				msgpullup(s->curframe,-1);
				/* transmit complete frame */
				ms_queue_put(out, s->curframe);
				s->curframe=NULL;
			} else {
				/* transmit partial frame */
				ms_queue_put(out, s->curframe);
				s->curframe = NULL;
				/* transmit new one (be it complete or not) */
				ms_queue_put(out, im);
			}
		} else {
			/* transmit new one (be it complete or not) */
			ms_queue_put(out, im);
		}
	} else {
		if (s->curframe!=NULL) {
			/* append if same timestamp */
			if (mblk_get_timestamp_info(im) == mblk_get_timestamp_info(s->curframe)) {
				concatb(s->curframe,im);
			} else {
				/* transmit partial frame */
				ms_queue_put(out, s->curframe);
				s->curframe = im;
			}
		}
		else {
			s->curframe = im;
		}
	}
}
Пример #3
0
/* the goal of that function is to return a absolute timestamp closest to real time, with respect of given packet_ts, which is a relative to an undefined origin*/
static uint32_t get_cur_timestamp(MSFilter * f, mblk_t *im)
{
	SenderData *d = (SenderData *) f->data;
	uint32_t curts = (uint32_t)( (f->ticker->time*(uint64_t)d->rate)/(uint64_t)1000) ;
	int diffts;
	uint32_t netts;
	int difftime_ts;

	if (im && d->dtmf==0){ /*do not perform timestamp adjustment while a dtmf is being sent, otherwise durations are erroneous */
		uint32_t packet_ts=mblk_get_timestamp_info(im);
		if (d->last_sent_time==-1){
			d->tsoff = curts - packet_ts;
		}else{
			diffts=packet_ts-d->last_ts;
			difftime_ts=((f->ticker->time-d->last_sent_time)*d->rate)/1000;
			/* detect timestamp jump in the stream and adjust so that they become continuous on the network*/
			if (abs(diffts-difftime_ts)>(d->rate/5)){
				uint32_t tsoff=curts - packet_ts;
				ms_message("Adjusting output timestamp by %i",(tsoff-d->tsoff));
				d->tsoff = tsoff;
			}
		}
		netts = packet_ts + d->tsoff;
		d->last_sent_time=f->ticker->time;
		d->last_ts=packet_ts;
	}else netts=curts;
	return netts;
}
Пример #4
0
static void sender_process(MSFilter * f)
{
	SenderData *d = (SenderData *) f->data;
	RtpSession *s = d->session;

	mblk_t *im;
	uint32_t timestamp;

	if (s == NULL){
		ms_queue_flush(f->inputs[0]);
		return;
	}

	if (d->relay_session_id_size>0 && 
		( (f->ticker->time-d->last_rsi_time)>5000 || d->last_rsi_time==0) ) {
		ms_message("relay session id sent in RTCP APP");
		rtp_session_send_rtcp_APP(s,0,"RSID",(const uint8_t *)d->relay_session_id,d->relay_session_id_size);
		d->last_rsi_time=f->ticker->time;
	}

	while ((im = ms_queue_get(f->inputs[0])) != NULL) {
		mblk_t *header;

		timestamp = get_cur_timestamp(f, mblk_get_timestamp_info(im));
		ms_filter_lock(f);
		if (d->skip) {
			ms_debug("skipping..");
			send_dtmf(f, d->skip_until-d->dtmf_duration, timestamp);
			d->dtmf_start = FALSE;
			if (!RTP_TIMESTAMP_IS_NEWER_THAN(timestamp, d->skip_until)) {
				freemsg(im);
				ms_filter_unlock(f);
				continue;
			}
			d->skip = FALSE;
			d->dtmf = 0;
		}

		if (d->skip == FALSE && d->mute_mic==FALSE){
			int pt = mblk_get_payload_type(im);
			header = rtp_session_create_packet(s, 12, NULL, 0);
			if (pt>0)
				rtp_set_payload_type(header, pt);
			rtp_set_markbit(header, mblk_get_marker_info(im));
			header->b_cont = im;
			rtp_session_sendm_with_ts(s, header, timestamp);
		}
		else{
			freemsg(im);
		}

		if (d->dtmf != 0) {
			ms_debug("prepare to send RFC2833 dtmf.");
			d->skip_until = timestamp + d->dtmf_duration;
			d->skip = TRUE;
			d->dtmf_start = TRUE;
		}
		ms_filter_unlock(f);
	}
}
Пример #5
0
void SinkBase::cb_data(mblk_t *m)
{
	uint32_t st = mblk_get_timestamp_info(m);

	mblk_t *fm = dupmsg(m);
	mblk_meta_copy(m, fm);
	MSQueue *queue = post_handle(fm);	// 此处 dupmsg(m) 将不会导致 m 被释放
	bool first = true;

	unsigned char *obuf = 0;
	size_t olen = 0;
	int index = 0;
	size_t off = 0;
	bool key = false;

	while (mblk_t *om = ms_queue_get(queue)) {

		int dlen = size_for(index, om);
		obuf = (unsigned char*)realloc(obuf, off + dlen);
		save_for(index, om, obuf + off);

		if (index == 0)
			key = is_key(index, om);

		index++;
		off += dlen;

		// 处理时间戳回绕
		if (first_frame_) {
			first_frame_ = false;
		}
		else {
			uint32_t delta = st - last_stamp_;

			// 检查,是否乱序,乱序包直接扔掉!
			if (delta > 0x80000000) {
				fprintf(stderr, "??? maybe timestamp confusioned!, curr=%u, last=%u\n", st, last_stamp_);
				return;
			}

			next_stamp_ += delta / payload_freq();
		}

		last_stamp_ = st;

		freemsg(om);
	}

	if (cb_data_ && obuf) {
		cb_data_(opaque_, next_stamp_, obuf, off, key);
	}

	if (obuf) free(obuf);
}
Пример #6
0
/* remove payload header and aggregates fragmented packets */
static void dec_unpacketize(MSFilter *f, DecState *s, mblk_t *im, MSQueue *out){
	im->b_rptr++;

	/* end of frame bit ? */
	if (mblk_get_marker_info(im)) {
		/* should be aggregated with previous packet ? */
		if (s->curframe!=NULL){
			/* same timestamp ? */
			if (mblk_get_timestamp_info(im) == mblk_get_timestamp_info(s->curframe)) {
				concatb(s->curframe,im);
				msgpullup(s->curframe,-1);
				/* transmit complete frame */
				ms_queue_put(out, s->curframe);
				s->curframe=NULL;
			} else {
				/* transmit partial frame */
				ms_queue_put(out, s->curframe);
				s->curframe = NULL;
				/* transmit new one (be it complete or not) */
				ms_queue_put(out, im);
			}
		} else {
			/* transmit new one (be it complete or not) */
			ms_queue_put(out, im);
		}
	} else {
		if (s->curframe!=NULL) {
			/* append if same timestamp */
			if (mblk_get_timestamp_info(im) == mblk_get_timestamp_info(s->curframe)) {
				concatb(s->curframe,im);
			} else {
				/* transmit partial frame */
				ms_queue_put(out, s->curframe);
				s->curframe = im;
			}
		}
		else {
			s->curframe = im;
		}
	}
}
Пример #7
0
static void dec_process(MSFilter *f) {
	DecData *d = (DecData*)f->data;
	mblk_t *im = NULL;
	MSQueue nalus;
	mblk_t *decodeM = NULL;	
	int in_size = 0;
	jint out_size = 0;
	mblk_t *oneNalu = NULL;
	JNIEnv *jni_env = NULL;
	JavaVM *jvm = ms_get_jvm();
	static char start_code[4] = {0, 0, 0, 1};
	
	(*jvm)->AttachCurrentThread(jvm, &jni_env, NULL);	
	
	ms_queue_init(&nalus);	
	while((im = ms_queue_get(f->inputs[0])) != NULL) {
		/*push the sps/pps given in sprop-parameter-sets if any*/
		if (d->packet_num == 0 && d->sps && d->pps) {
			mblk_set_timestamp_info(d->sps,mblk_get_timestamp_info(im));
			mblk_set_timestamp_info(d->pps,mblk_get_timestamp_info(im));
			rfc3984_unpack(&d->unpacker,d->sps,&nalus);
			rfc3984_unpack(&d->unpacker,d->pps,&nalus);
			d->sps = NULL;
			d->pps = NULL;
		}
		rfc3984_unpack(&d->unpacker,im,&nalus);
		
		while((oneNalu = ms_queue_get(&nalus)) != NULL) {
			in_size = oneNalu->b_wptr - oneNalu->b_rptr;
			
			if (GET_TYPE(oneNalu->b_rptr[0]) == SPS_TYPE) {
				if (d->sps == NULL) {
					FMS_WARN("dec_process get sps\n");
					d->sps = allocb(in_size + START_CODE_LEN, 0);
					if (d->sps) {
						memcpy(d->sps->b_rptr, start_code, START_CODE_LEN);
						memcpy(d->sps->b_rptr + START_CODE_LEN, oneNalu->b_rptr, in_size);
						d->sps->b_wptr += in_size + START_CODE_LEN;
					}
				} else {
					freemsg(oneNalu);
					continue;						
				}
			} else if (GET_TYPE(oneNalu->b_rptr[0]) == PPS_TYPE) {
				if (d->pps == NULL && d->sps != NULL) {
					FMS_WARN("dec_process get pps\n");
					d->pps = allocb(in_size + START_CODE_LEN, 0);
					if (d->pps) {
						memcpy(d->pps->b_rptr, start_code, START_CODE_LEN);
						memcpy(d->pps->b_rptr + START_CODE_LEN, oneNalu->b_rptr, in_size);
						d->pps->b_wptr += in_size + START_CODE_LEN;
					}
				} else {
					freemsg(oneNalu);
					continue;	
				}
			}
			
			if (d->sps == NULL || (GET_TYPE(oneNalu->b_rptr[0]) != SPS_TYPE && d->pps == NULL)) {
				FMS_WARN("skip frame without no sps and pps\n");
				freemsg(oneNalu);
				continue;			
			}
			if (!d->IsRecivedFirstIframe && GET_TYPE(oneNalu->b_rptr[0]) != SPS_TYPE 
				&& GET_TYPE(oneNalu->b_rptr[0]) != PPS_TYPE) {
				if (GET_TYPE(oneNalu->b_rptr[0]) == IDR_TYPE) {
					d->IsRecivedFirstIframe = TRUE;
				} else {
					FMS_WARN("skip frame without the first IDR\n");
					freemsg(oneNalu);
					continue;
				}
			}

			(*jni_env)->SetByteArrayRegion(jni_env, d->input_data, 0, START_CODE_LEN, (jbyte*)start_code);
			(*jni_env)->SetByteArrayRegion(jni_env, d->input_data, START_CODE_LEN, in_size, (jbyte*)oneNalu->b_rptr);
	 
			out_size = (*jni_env)->CallIntMethod(jni_env, d->h264_decode_obj, d->h264_decode_id,
				                                     d->input_data, in_size + START_CODE_LEN, d->output_data);
			if (out_size <= 0) {
				freemsg(oneNalu);
				continue;
			}
				
			(*jni_env)->GetByteArrayRegion(jni_env, d->output_data, 0, out_size, 
				                              (jbyte*)d->bitstream);
		
			if (FALSE == d->IsFirstImageDec) {
				d->IsFirstImageDec = TRUE;
				//ms_filter_notify_no_arg(f, MS_VIDEO_DECODER_GET_FIRST_VIDEO_FRAME);
			}
			
			decodeM = get_as_yuvmsg(f, d, d->bitstream, out_size);
			if (decodeM) {
				ms_queue_put(f->outputs[0], decodeM);
			}
	
			freemsg(oneNalu);
		}
		d->packet_num++;
	}
	(*jvm)->DetachCurrentThread(jvm);
	
}
static void dec_process(MSFilter *f){
	DecData *d=(DecData*)f->data;
	MSPicture pic = {0};
	mblk_t *im,*om = NULL;
	ssize_t oBufidx = -1;
	size_t bufsize;
	bool_t need_reinit=FALSE;
	bool_t request_pli=FALSE;
	MSQueue nalus;
	AMediaCodecBufferInfo info;
	
	ms_queue_init(&nalus);

	while((im=ms_queue_get(f->inputs[0]))!=NULL){
		if (d->packet_num==0 && d->sps && d->pps){
			mblk_set_timestamp_info(d->sps,mblk_get_timestamp_info(im));
			mblk_set_timestamp_info(d->pps,mblk_get_timestamp_info(im));
			rfc3984_unpack(&d->unpacker, d->sps, &nalus);
            rfc3984_unpack(&d->unpacker, d->pps, &nalus);
			d->sps=NULL;
			d->pps=NULL;
		}

		if(rfc3984_unpack(&d->unpacker,im,&nalus) <0){
			request_pli=TRUE;
		}
		if (!ms_queue_empty(&nalus)){
			int size;
			uint8_t *buf=NULL;
			ssize_t iBufidx;

			size=nalusToFrame(d,&nalus,&need_reinit);

			if (need_reinit) {
				//In case of rotation, the decoder needs to flushed in order to restart with the new video size
				AMediaCodec_flush(d->codec);
				d->first_buffer_queued = FALSE;
			}

			/*First put our H264 bitstream into the decoder*/
			iBufidx = AMediaCodec_dequeueInputBuffer(d->codec, TIMEOUT_US);
			if (iBufidx >= 0) {
				buf = AMediaCodec_getInputBuffer(d->codec, iBufidx, &bufsize);
				if(buf == NULL) {
					ms_error("MSMediaCodecH264Dec: AMediaCodec_getInputBuffer() returned NULL");
					break;
				}
				if((size_t)size > bufsize) {
					ms_error("Cannot copy the bitstream into the input buffer size : %i and bufsize %i",size,(int) bufsize);
					break;
				} else {
					struct timespec ts;
					clock_gettime(CLOCK_MONOTONIC, &ts);
					memcpy(buf,d->bitstream,(size_t)size);
					AMediaCodec_queueInputBuffer(d->codec, iBufidx, 0, (size_t)size, (ts.tv_nsec/1000) + 10000LL, 0);
					d->first_buffer_queued = TRUE;
				}
			}else if (iBufidx == AMEDIA_ERROR_UNKNOWN){
				ms_error("MSMediaCodecH264Dec: AMediaCodec_dequeueInputBuffer() had an exception");
			}
		}
		d->packet_num++;
		if (d->sps && d->pps) request_pli = FALSE;
		else request_pli = TRUE;
	}
	
	/*secondly try to get decoded frames from the decoder, this is performed every tick*/
	while (d->first_buffer_queued && (oBufidx = AMediaCodec_dequeueOutputBuffer(d->codec, &info, TIMEOUT_US)) >= 0){
		AMediaFormat *format;
		int width = 0, height = 0, color = 0;
		uint8_t *buf = AMediaCodec_getOutputBuffer(d->codec, oBufidx, &bufsize);
		
		if(buf == NULL){
			ms_filter_notify_no_arg(f,MS_VIDEO_DECODER_DECODING_ERRORS);
			ms_error("MSMediaCodecH264Dec: AMediaCodec_getOutputBuffer() returned NULL");
		}

		format = AMediaCodec_getOutputFormat(d->codec);
		if(format != NULL){
			AMediaFormat_getInt32(format, "width", &width);
			AMediaFormat_getInt32(format, "height", &height);
			AMediaFormat_getInt32(format, "color-format", &color);

			d->vsize.width=width;
			d->vsize.height=height;
			AMediaFormat_delete(format);
		}

		if(buf != NULL && d->sps && d->pps){ /*some decoders output garbage while no sps or pps have been received yet !*/
			if(width != 0 && height != 0 ){
				if(color == 19) {
					//YUV
					int ysize = width*height;
					int usize = ysize/4;
					om = ms_yuv_buf_allocator_get(d->buf_allocator,&pic,width,height);
					memcpy(pic.planes[0],buf,ysize);
					memcpy(pic.planes[1],buf+ysize,usize);
					memcpy(pic.planes[2],buf+ysize+usize,usize);
				} else {
					uint8_t* cbcr_src = (uint8_t*) (buf + width * height);
					om = copy_ycbcrbiplanar_to_true_yuv_with_rotation_and_down_scale_by_2(d->buf_allocator, buf, cbcr_src, 0, width, height, width, width, TRUE, FALSE);
				}

				if (!d->first_image_decoded) {
					ms_message("First frame decoded %ix%i",width,height);
					d->first_image_decoded = true;
					ms_filter_notify_no_arg(f, MS_VIDEO_DECODER_FIRST_IMAGE_DECODED);
				}
				ms_queue_put(f->outputs[0], om);
			}else{
				ms_error("MSMediaCodecH264Dec: width and height are not known !");
			}
		}
		AMediaCodec_releaseOutputBuffer(d->codec, oBufidx, FALSE);
	}
	if (oBufidx == AMEDIA_ERROR_UNKNOWN){
		ms_error("MSMediaCodecH264Dec: AMediaCodec_dequeueOutputBuffer() had an exception");
	}

	if (d->avpf_enabled && request_pli) {
    	ms_filter_notify_no_arg(f, MS_VIDEO_DECODER_SEND_PLI);
    }
    ms_queue_flush(f->inputs[0]);
}
Пример #9
0
void MSOpenH264Decoder::feed()
{
    if (!isInitialized()) {
        ms_error("MSOpenH264Decoder::feed(): not initialized");
        ms_queue_flush(mFilter->inputs[0]);
        return;
    }

    MSQueue nalus;
    ms_queue_init(&nalus);

    mblk_t *im;
    while ((im = ms_queue_get(mFilter->inputs[0])) != NULL) {
        if ((getIDRPicId() == 0) && (mSPS != 0) && (mPPS != 0)) {
            // Push the sps/pps given in sprop-parameter-sets if any
            mblk_set_timestamp_info(mSPS, mblk_get_timestamp_info(im));
            mblk_set_timestamp_info(mPPS, mblk_get_timestamp_info(im));
            rfc3984_unpack(mUnpacker, mSPS, &nalus);
            rfc3984_unpack(mUnpacker, mPPS, &nalus);
            mSPS = 0;
            mPPS = 0;
        }
        rfc3984_unpack(mUnpacker, im, &nalus);
        if (!ms_queue_empty(&nalus)) {
            void * pData[3] = { 0 };
            SBufferInfo sDstBufInfo = { 0 };
            int len = nalusToFrame(&nalus);

            DECODING_STATE state = mDecoder->DecodeFrame2(mBitstream, len, (uint8_t**)pData, &sDstBufInfo);
            if (state != dsErrorFree) {
                ms_error("OpenH264 decoder: DecodeFrame2 failed: 0x%x", state);
                if (((mFilter->ticker->time - mLastErrorReportTime) > 5000) || (mLastErrorReportTime == 0)) {
                    mLastErrorReportTime = mFilter->ticker->time;
                    ms_filter_notify_no_arg(mFilter, MS_VIDEO_DECODER_DECODING_ERRORS);
                }
            }
            if (sDstBufInfo.iBufferStatus == 1) {
                uint8_t * pDst[3] = { 0 };
                pDst[0] = (uint8_t *)pData[0];
                pDst[1] = (uint8_t *)pData[1];
                pDst[2] = (uint8_t *)pData[2];

                // Update video size and (re)allocate YUV buffer if needed
                if ((mWidth != sDstBufInfo.UsrData.sSystemBuffer.iWidth)
                        || (mHeight != sDstBufInfo.UsrData.sSystemBuffer.iHeight)) {
                    if (mYUVMsg) {
                        freemsg(mYUVMsg);
                    }
                    mWidth = sDstBufInfo.UsrData.sSystemBuffer.iWidth;
                    mHeight = sDstBufInfo.UsrData.sSystemBuffer.iHeight;
                    mYUVMsg = ms_yuv_buf_alloc(&mOutbuf, mWidth, mHeight);
                    ms_filter_notify_no_arg(mFilter,MS_FILTER_OUTPUT_FMT_CHANGED);
                }

                // Scale/copy frame to destination mblk_t
                for (int i = 0; i < 3; i++) {
                    uint8_t *dst = mOutbuf.planes[i];
                    uint8_t *src = pDst[i];
                    int h = mHeight >> (( i > 0) ? 1 : 0);

                    for(int j = 0; j < h; j++) {
                        memcpy(dst, src, mOutbuf.strides[i]);
                        dst += mOutbuf.strides[i];
                        src += sDstBufInfo.UsrData.sSystemBuffer.iStride[(i == 0) ? 0 : 1];
                    }
                }
                ms_queue_put(mFilter->outputs[0], dupmsg(mYUVMsg));

                // Update average FPS
                if (ms_average_fps_update(&mFPS, mFilter->ticker->time)) {
                    ms_message("OpenH264 decoder: Frame size: %dx%d", mWidth, mHeight);
                }

                // Notify first decoded image
                if (!mFirstImageDecoded) {
                    mFirstImageDecoded = true;
                    ms_filter_notify_no_arg(mFilter, MS_VIDEO_DECODER_FIRST_IMAGE_DECODED);
                }

#if MSOPENH264_DEBUG
                ms_message("OpenH264 decoder: IDR pic id: %d, Frame num: %d, Temporal id: %d, VCL NAL: %d", getIDRPicId(), getFrameNum(), getTemporalId(), getVCLNal());
#endif
            }
        }
Пример #10
0
static void dec_process(MSFilter *f){
	DecData *d=(DecData*)f->data;
	MSPicture pic = {0};
	mblk_t *im,*om = NULL;
	bool_t need_reinit=FALSE;
	bool_t request_pli=FALSE;
	MSQueue nalus;
	ms_queue_init(&nalus);

	while((im=ms_queue_get(f->inputs[0]))!=NULL){
		if (d->packet_num==0 && d->sps && d->pps){
			mblk_set_timestamp_info(d->sps,mblk_get_timestamp_info(im));
			mblk_set_timestamp_info(d->pps,mblk_get_timestamp_info(im));
			rfc3984_unpack(&d->unpacker, d->sps, &nalus);
            rfc3984_unpack(&d->unpacker, d->pps, &nalus);
			d->sps=NULL;
			d->pps=NULL;
		}

		if(rfc3984_unpack(&d->unpacker,im,&nalus) <0){
			request_pli=TRUE;
		}
		if (!ms_queue_empty(&nalus)){
			AMediaCodecBufferInfo info;
			int size;
			int width = 0, height = 0, color = 0;
			uint8_t *buf=NULL;
			size_t bufsize;
			ssize_t iBufidx, oBufidx;

			size=nalusToFrame(d,&nalus,&need_reinit);

			if (need_reinit) {
				//In case of rotation, the decoder needs to flushed in order to restart with the new video size
				AMediaCodec_flush(d->codec);
			}

			iBufidx = AMediaCodec_dequeueInputBuffer(d->codec, TIMEOUT_US);
			if (iBufidx >= 0) {
				buf = AMediaCodec_getInputBuffer(d->codec, iBufidx, &bufsize);
				if(buf == NULL) {
					break;
				}
				if((size_t)size > bufsize) {
					ms_error("Cannot copy the bitstream into the input buffer size : %i and bufsize %i",size,(int) bufsize);
				} else {
					memcpy(buf,d->bitstream,(size_t)size);
					AMediaCodec_queueInputBuffer(d->codec, iBufidx, 0, (size_t)size, TIMEOUT_US, 0);
				}
			}

            oBufidx = AMediaCodec_dequeueOutputBuffer(d->codec, &info, TIMEOUT_US);
			if(oBufidx >= 0){
				AMediaFormat *format;
				buf = AMediaCodec_getOutputBuffer(d->codec, oBufidx, &bufsize);
				if(buf == NULL){
					ms_filter_notify_no_arg(f,MS_VIDEO_DECODER_DECODING_ERRORS);
					break;
				}

				format = AMediaCodec_getOutputFormat(d->codec);
				if(format != NULL){
					AMediaFormat_getInt32(format, "width", &width);
					AMediaFormat_getInt32(format, "height", &height);
					AMediaFormat_getInt32(format, "color-format", &color);

					d->vsize.width=width;
					d->vsize.height=height;
					AMediaFormat_delete(format);
				}
			}

			if(buf != NULL){
				//YUV
				if(width != 0 && height != 0 ){
					if(color == 19) {
						int ysize = width*height;
						int usize = ysize/4;
						om=ms_yuv_buf_alloc(&pic,width,height);
						memcpy(pic.planes[0],buf,ysize);
						memcpy(pic.planes[1],buf+ysize,usize);
						memcpy(pic.planes[2],buf+ysize+usize,usize);
					} else {
						uint8_t* cbcr_src = (uint8_t*) (buf + width * height);
						om = copy_ycbcrbiplanar_to_true_yuv_with_rotation_and_down_scale_by_2(d->buf_allocator, buf, cbcr_src, 0, width, height, width, width, TRUE, FALSE);
					}

					if (!d->first_image_decoded) {
						ms_message("First frame decoded %ix%i",width,height);
						d->first_image_decoded = true;
						ms_filter_notify_no_arg(f, MS_VIDEO_DECODER_FIRST_IMAGE_DECODED);
					}

					ms_queue_put(f->outputs[0], om);
				}

				if(oBufidx > 0) {
                	AMediaCodec_releaseOutputBuffer(d->codec, oBufidx, FALSE);
				}


			}
		}
		d->packet_num++;
	}

	if (d->avpf_enabled && request_pli) {
    	ms_filter_notify_no_arg(f, MS_VIDEO_DECODER_SEND_PLI);
    }
}