コード例 #1
0
ファイル: ffmpeg.cpp プロジェクト: qmwd2006/mpeg4ip
static int ffmpeg_frame_is_sync (codec_data_t *ifptr,
                                 uint8_t *buffer,
                                 uint32_t buflen,
                                 void *userdata)
{
    int ret;
    int ftype;
    uint32_t offset;
    ffmpeg_codec_t *ffmpeg = (ffmpeg_codec_t *)ifptr;
    switch (ffmpeg->m_codecId) {
    case CODEC_ID_H264:
        // look for idr nal
        do {
            uint8_t nal_type = h264_nal_unit_type(buffer);
            if (nal_type == H264_NAL_TYPE_SEQ_PARAM) return 1;
            //ffmpeg_message(LOG_DEBUG, "ffmpeg", "nal type %u", nal_type);
            if (h264_nal_unit_type_is_slice(nal_type)) {
                if (nal_type == H264_NAL_TYPE_IDR_SLICE) return 1;
#if 0
                uint8_t slice_type;
                if (h264_find_slice_type(buffer, buflen, &slice_type) >= 0) {
                    return H264_TYPE_IS_I(slice_type) ? 1 : 0;
                }
                return 0;
#else
                return 0;
#endif
            }
            offset = h264_find_next_start_code(buffer, buflen);
            buffer += offset;
            buflen -= offset;
        } while (offset != 0);
        break;
    case CODEC_ID_MPEG2VIDEO:
        // this would be for mpeg2
        ret = MP4AV_Mpeg3FindPictHdr(buffer, buflen, &ftype);
        ffmpeg_message(LOG_ERR, "ffmpeg", "ret %u type %u", ret, ftype);
        if (ret >= 0 && ftype == 1) {
            return 1;
        }
        break;
    case CODEC_ID_MPEG4: {
        uint8_t *vop = MP4AV_Mpeg4FindVop(buffer, buflen);
        if (vop == NULL) return 0;
        if (MP4AV_Mpeg4GetVopType(vop, buflen - (vop - buffer)) == VOP_TYPE_I)
            return 1;
    }
    break;
    default:
        // for every other, return that it is sync
        return 1;
    }
    return 0;
}
コード例 #2
0
ファイル: ffmpeg.cpp プロジェクト: qmwd2006/mpeg4ip
static int ffmpeg_decode (codec_data_t *ptr,
                          frame_timestamp_t *pts,
                          int from_rtp,
                          int *sync_frame,
                          uint8_t *buffer,
                          uint32_t buflen,
                          void *ud)
{
    ffmpeg_codec_t *ffmpeg = (ffmpeg_codec_t *)ptr;
    uint32_t bytes_used = 0;
    int got_picture = 0;
    uint64_t ts = pts->msec_timestamp;

    //ffmpeg_message(LOG_ERR, "ffmpeg", "%u timestamp "U64, buflen, ts);
    if (ffmpeg->m_codec_opened == false) {
        // look for header, like above, and open it
        bool open_codec = true;
        switch (ffmpeg->m_codecId) {
        case CODEC_ID_H264:
            open_codec = ffmpeg_find_h264_size(ffmpeg, buffer, buflen);
            break;
        default:
            break;
        }
        if (open_codec) {
            if (avcodec_open(ffmpeg->m_c, ffmpeg->m_codec) < 0) {
                ffmpeg_message(LOG_CRIT, "ffmpeg", "failed to open codec");
                return buflen;
            }
            ffmpeg->m_codec_opened = true;
            ffmpeg_message(LOG_ERR, "ffmpeg", "opened codec");
        } else {
            ffmpeg_message(LOG_ERR, "ffmpeg", "no open %u "U64, buflen, ts);
            return buflen;
        }
    }

    // look and see if we have read the I frame.
    if (ffmpeg->m_got_i == false) {
        if (ffmpeg_frame_is_sync(ptr, buffer, buflen, NULL) == 0) {
            return buflen;
        }
        ffmpeg->m_got_i = true;
    }

    int ret;
    do {
        int local_got_picture;
        ret = avcodec_decode_video(ffmpeg->m_c,
                                   ffmpeg->m_picture,
                                   &local_got_picture,
                                   buffer + bytes_used,
                                   buflen - bytes_used);
        bytes_used += ret;
        //ffmpeg_message(LOG_CRIT, "ffmpeg", "used %d %d", ret, local_got_picture);
        got_picture |= local_got_picture;
    } while (ret != -1 && bytes_used < buflen);

    if (pts->timestamp_is_pts) {
        //ffmpeg_message(LOG_ERR, "ffmpeg", "pts timestamp "U64, ts);
        if (ffmpeg->m_codecId == CODEC_ID_MPEG2VIDEO) {
            if (ffmpeg->pts_convert.frame_rate == 0.0) {
                int have_mpeg2;
                uint32_t h, w;
                double bitrate, aspect_ratio;
                uint8_t profile;
                MP4AV_Mpeg3ParseSeqHdr(buffer, buflen,
                                       &have_mpeg2,
                                       &h, &w,
                                       &ffmpeg->pts_convert.frame_rate,
                                       &bitrate, &aspect_ratio,
                                       &profile);
            }

            int ftype;
            int header = MP4AV_Mpeg3FindPictHdr(buffer, buflen, &ftype);
            if (header >= 0) {
                uint16_t temp_ref = MP4AV_Mpeg3PictHdrTempRef(buffer + header);
                uint64_t ret;
                if (got_picture == 0 ||
                        mpeg3_find_dts_from_pts(&ffmpeg->pts_convert,
                                                ts,
                                                ftype,
                                                temp_ref,
                                                &ret) < 0) {
                    ffmpeg->have_cached_ts = false;
                    return buflen;
                }
#if 0
                ffmpeg->m_vft->log_msg(LOG_DEBUG, "ffmpeg", "pts "U64" dts "U64" temp %u type %u %u",
                                       ts, ret,
                                       temp_ref, ftype, got_picture);
#endif
                ts = ret;
                //	ffmpeg_message(LOG_ERR, "ffmpeg", "type %d ref %u "U64, ftype, temp_ref, ret);
            }
        } else if (ffmpeg->m_codecId == CODEC_ID_MPEG4) {
            uint8_t *vopstart = MP4AV_Mpeg4FindVop(buffer, buflen);
            if (vopstart) {
                int ftype = MP4AV_Mpeg4GetVopType(vopstart, buflen);
                uint64_t dts;
                if (MP4AV_calculate_dts_from_pts(&ffmpeg->pts_to_dts,
                                                 ts,
                                                 ftype,
                                                 &dts) < 0) {
                    ffmpeg->have_cached_ts = false;
#ifdef DEBUG_FFMPEG_PTS
                    ffmpeg_message(LOG_DEBUG, "ffmpeg", "type %d %d pts "U64" failed to calc",
                                   ftype, got_picture, ts);
#endif
                    return buflen;
                }
#ifdef DEBUG_FFMPEG_PTS
                ffmpeg_message(LOG_DEBUG, "ffmpeg", "type %d %d pts "U64" dts "U64,
                               ftype, got_picture, ts, dts);
#endif
                ts = dts;
            }
        } else if (ffmpeg->m_codecId == CODEC_ID_H264) {
            uint8_t *nal_ptr = buffer;
            uint32_t len = buflen;
            bool have_b_nal = false;
            do {
                if (h264_nal_unit_type_is_slice(h264_nal_unit_type(nal_ptr))) {
                    uint8_t slice_type;
                    if (h264_find_slice_type(nal_ptr, len, &slice_type, false) >= 0) {
                        have_b_nal = H264_TYPE_IS_B(slice_type);
                    }
                }
                uint32_t offset = h264_find_next_start_code(nal_ptr, len);
                if (offset == 0) {
                    len = 0;
                } else {
                    nal_ptr += offset;
                    len -= offset;
                }
            } while (len > 0 && have_b_nal == false);
            uint64_t dts;
            if (MP4AV_calculate_dts_from_pts(&ffmpeg->pts_to_dts,
                                             ts,
                                             have_b_nal ? VOP_TYPE_B : VOP_TYPE_P,
                                             &dts) < 0) {
                ffmpeg->have_cached_ts = false;
#ifdef DEBUG_FFMPEG_PTS
                ffmpeg_message(LOG_DEBUG, "ffmpeg", "pts "U64" failed to calc",
                               ts);
#endif
                return buflen;
            }
            ts = dts;
        }
    }
    if (got_picture != 0) {
        if (ffmpeg->m_video_initialized == false) {
            double aspect;
            if (ffmpeg->m_c->sample_aspect_ratio.den == 0) {
                aspect = 0.0; // don't have one
            } else {
                aspect = av_q2d(ffmpeg->m_c->sample_aspect_ratio);
            }
            if (ffmpeg->m_c->width == 0) {
                return buflen;
            }
            ffmpeg->m_vft->video_configure(ffmpeg->m_ifptr,
                                           ffmpeg->m_c->width,
                                           ffmpeg->m_c->height,
                                           VIDEO_FORMAT_YUV,
                                           aspect);
            ffmpeg->m_video_initialized = true;
        }

        if (ffmpeg->m_c->pix_fmt != PIX_FMT_YUV420P) {
            // convert the image from whatever it is to YUV 4:2:0
            AVPicture from, to;
            int ret;
            // get the buffer to copy into (put it right into the ring buffer)
            ret = ffmpeg->m_vft->video_get_buffer(ffmpeg->m_ifptr,
                                                  &to.data[0],
                                                  &to.data[1],
                                                  &to.data[2]);
            if (ret == 0) {
                return buflen;
            }
            // set up the AVPicture structures
            to.linesize[0] = ffmpeg->m_c->width;
            to.linesize[1] = ffmpeg->m_c->width / 2;
            to.linesize[2] = ffmpeg->m_c->width / 2;
            for (int ix = 0; ix < 4; ix++) {
                from.data[ix] = ffmpeg->m_picture->data[ix];
                from.linesize[ix] = ffmpeg->m_picture->linesize[ix];
            }

            img_convert(&to, PIX_FMT_YUV420P,
                        &from, ffmpeg->m_c->pix_fmt,
                        ffmpeg->m_c->width, ffmpeg->m_c->height);
            ffmpeg->m_vft->video_filled_buffer(ffmpeg->m_ifptr,
                                               ffmpeg->have_cached_ts ?
                                               ffmpeg->cached_ts : ts);
        } else {
            ffmpeg->m_vft->video_have_frame(ffmpeg->m_ifptr,
                                            ffmpeg->m_picture->data[0],
                                            ffmpeg->m_picture->data[1],
                                            ffmpeg->m_picture->data[2],
                                            ffmpeg->m_picture->linesize[0],
                                            ffmpeg->m_picture->linesize[1],
                                            ffmpeg->have_cached_ts ?
                                            ffmpeg->cached_ts : ts);
        }
        ffmpeg->cached_ts = ts;
    } else {
        ffmpeg->cached_ts = ts;
        ffmpeg->have_cached_ts = true;
    }
#ifdef DEBUG_FFMPEG_FRAME
    ffmpeg_message(LOG_DEBUG, "ffmpeg", "used %u of %u", bytes_used, buflen);
#endif
    return (buflen);
}
コード例 #3
0
ファイル: mpeg4.cpp プロジェクト: dazzle-multimedia/mpeg4ip
static int iso_decode (codec_data_t *ptr, 
		       frame_timestamp_t *ts, 
		       int from_rtp, 
		       int *sync_frame,
		       uint8_t *buffer,
		       uint32_t buflen,
		       void *userdata)
{
  Int iEof = 1;
  iso_decode_t *iso = (iso_decode_t *)ptr;
  uint32_t used = 0;

  if (buflen <= 4) return -1;

  //  iso_message(LOG_DEBUG, "iso", "frame %d", iso->m_total_frames);
  iso->m_total_frames++;
  buffer[buflen] = 0;
  buffer[buflen + 1] = 0;
  buffer[buflen + 2] = 1;

  switch (iso->m_decodeState) {
  case DECODE_STATE_VOL_SEARCH: {
    if (buffer[0] == 0 &&
	buffer[1] == 0 &&
	(buffer[2] & 0xfc) == 0x80 &&
	(buffer[3] & 0x03) == 0x02) {
      // we have the short header
      iso->m_short_header = 1;
      iso->m_pvodec->SetUpBitstreamBuffer((unsigned char *)buffer, buflen);
      iso->m_pvodec->video_plane_with_short_header();
      iso->m_pvodec->postVO_VOLHeadInit(iso->m_pvodec->getWidth(),
					iso->m_pvodec->getHeight(),
					&iso->m_bSpatialScalability);
      iso_message(LOG_INFO, mp4iso, "Decoding using short headers");
      iso->m_vft->video_configure(iso->m_ifptr, 
				  iso->m_pvodec->getWidth(),
				  iso->m_pvodec->getHeight(),
				  VIDEO_FORMAT_YUV,
				  calculate_aspect_ratio(iso));
      iso->m_decodeState = DECODE_STATE_NORMAL;
      try {
	iEof = iso->m_pvodec->h263_decode(FALSE);
      } catch (...) {
	iso_message(LOG_ERR, mp4iso, "Couldn't decode h263 in vol search");
      }
      break; 
    } else {
      uint8_t *volhdr = MP4AV_Mpeg4FindVol(buffer, buflen);
      if (volhdr != NULL) {
	used = volhdr - buffer;
	try {
	  iso->m_pvodec->SetUpBitstreamBuffer((unsigned char *)volhdr, buflen - used);
	  iso->m_pvodec->decodeVOLHead();
	  iso->m_pvodec->postVO_VOLHeadInit(iso->m_pvodec->getWidth(),
					    iso->m_pvodec->getHeight(),
					  &iso->m_bSpatialScalability);
	  iso_message(LOG_INFO, mp4iso, "Found VOL");
	
	  iso->m_vft->video_configure(iso->m_ifptr, 
				      iso->m_pvodec->getWidth(),
				      iso->m_pvodec->getHeight(),
				      VIDEO_FORMAT_YUV,
				      calculate_aspect_ratio(iso));
	
	  iso->m_decodeState = DECODE_STATE_WAIT_I;
	  used += iso->m_pvodec->get_used_bytes();
	} catch (int err) {
	  iso_message(LOG_DEBUG, mp4iso, "Caught exception in VOL search %d", err);
	  if (err == 1) used = buflen;
	  else used += iso->m_pvodec->get_used_bytes();
	}
      }
    }
    if (iso->m_decodeState != DECODE_STATE_WAIT_I) {
      if (iso->m_vinfo != NULL) {
	iso->m_pvodec->FakeOutVOVOLHead(iso->m_vinfo->height,
					iso->m_vinfo->width,
					30,
					&iso->m_bSpatialScalability);
	iso->m_vft->video_configure(iso->m_ifptr, 
				    iso->m_vinfo->width,
				    iso->m_vinfo->height,
				    VIDEO_FORMAT_YUV,
				    calculate_aspect_ratio(iso));

	iso->m_decodeState = DECODE_STATE_NORMAL;
      } 

      return used;
    }
    // else fall through
  }
  case DECODE_STATE_WAIT_I: {
    uint8_t *vophdr = MP4AV_Mpeg4FindVop(buffer, buflen);
    if (vophdr != NULL) {
      used = vophdr - buffer;
    }
    iso->m_pvodec->SetUpBitstreamBuffer((unsigned char *)buffer + used, buflen + 3 - used);
    try {
      iEof = iso->m_pvodec->decode(NULL, TRUE);
      if (iEof == -1) {
	iso->m_num_wait_i_frames++;
	return(iso->m_pvodec->get_used_bytes());
      }
      iso_message(LOG_DEBUG, mp4iso, "Back to normal decode");
      iso->m_decodeState = DECODE_STATE_NORMAL;
      iso->m_bCachedRefFrame = FALSE;
      iso->m_bCachedRefFrameCoded = FALSE;
      iso->m_cached_valid = FALSE;
      iso->m_cached_time = 0;
    } catch (int err) {
      if (err != 1)
	iso_message(LOG_DEBUG, mp4iso, 
		    "ts "U64",Caught exception in wait_i %d", 
		    ts->msec_timestamp, err);
      return (iso->m_pvodec->get_used_bytes());
      //return (-1);
    }
    break;
  }
  case DECODE_STATE_NORMAL:
    try {
      if (iso->m_short_header != 0) {
	iso->m_pvodec->SetUpBitstreamBuffer((unsigned char *)buffer, buflen + 3);
	iEof = iso->m_pvodec->h263_decode(TRUE);
      } else {
	uint8_t *vophdr = MP4AV_Mpeg4FindVop(buffer, buflen);
	if (vophdr != NULL && vophdr != buffer) {
	  iso_message(LOG_DEBUG, mp4iso, "Illegal code before VOP header");
	  used = vophdr - buffer;
	  buflen -= used;
	  buffer = vophdr;
	}
	iso->m_pvodec->SetUpBitstreamBuffer((unsigned char *)buffer, buflen + 3);
	iEof = iso->m_pvodec->decode(NULL, FALSE, FALSE);
      }
    } catch (int err) {
      // This is because sometimes, the encoder doesn't read all the bytes
      // it should out of the rtp packet.  The rtp bytestream does a read
      // and determines that we're trying to read across bytestreams.
      // If we get this, we don't want to change anything - just fall up
      // to the decoder thread so it gives us a new timestamp.
      if (err == 1) {
	// throw from running past end of frame
	return -1;
      }
      iso_message(LOG_DEBUG, mp4iso, 
		  "Mpeg4 ncaught %d -> waiting for I", err);
      iso->m_decodeState = DECODE_STATE_WAIT_I;
      return (iso->m_pvodec->get_used_bytes());
    } catch (...) {
      iso_message(LOG_DEBUG, mp4iso, 
		  "Mpeg4 ncaught -> waiting for I");
      iso->m_decodeState = DECODE_STATE_WAIT_I;
      //return (-1);
      return (iso->m_pvodec->get_used_bytes());
    }
    break;
  }

  /*
   * We've got a good frame.  See if we need to display it
   */
  const CVOPU8YUVBA *pvopcQuant = NULL;
  if (iso->m_pvodec->fSptUsage() == 1) {
    //player_debug_message("Sprite");
  }
  uint64_t displaytime = 0;
  int cached_ts = 0;
  if (iEof == EOF) {
    if (iso->m_bCachedRefFrame) {
      iso->m_bCachedRefFrame = FALSE;
      if (iso->m_bCachedRefFrameCoded) {
	pvopcQuant = iso->m_pvodec->pvopcRefQLater();
	displaytime = ts->msec_timestamp;
      }
    }
  } else {
#if 0
    iso_message(LOG_DEBUG, mp4iso, "frame "U64" type %d", 
		ts->msec_timestamp, iso->m_pvodec->vopmd().vopPredType);
#endif
    if (iso->m_pvodec->vopmd().vopPredType == BVOP) {
      if (iEof != FALSE) {
	pvopcQuant = iso->m_pvodec->pvopcReconCurr();
	displaytime = ts->msec_timestamp;
      } 
    } else {
      if (iso->m_bCachedRefFrame) {
	iso->m_bCachedRefFrame = FALSE;
	if (iso->m_bCachedRefFrameCoded) {
	  pvopcQuant = iso->m_pvodec->pvopcRefQPrev();
	  if (ts->timestamp_is_pts) {
	    int old_was_valid = iso->m_cached_valid;
	    displaytime = iso->m_cached_time;
	    cached_ts = 1;
	    // old time stamp wasn't valid - instead of calculating it
	    // ourselves, just punt on it.
	    if (old_was_valid == 0) {
	      return (iEof == EOF ? -1 : 0);
	    }
	  } else {
	    displaytime = ts->msec_timestamp;
	  }
	}
      }

      iso->m_cached_time = ts->msec_timestamp;
      iso->m_cached_valid = TRUE;
      iso->m_bCachedRefFrame = TRUE;
      iso->m_bCachedRefFrameCoded = (iEof != FALSE);
    }
  }

  if (pvopcQuant != NULL) {
#if 0
    player_debug_message("frame rtp_ts "U64" disp "U64" cached %d", 
			 ts->msec_timestamp, displaytime, cached_ts);
#endif
    /*
     * Get the information to the video sync structure
     */
    const uint8_t *y, *u, *v;
    int pixelw_y, pixelw_uv;
    pixelw_y =  pvopcQuant->getPlane(Y_PLANE)->where().width;
    pixelw_uv = pvopcQuant->getPlane(U_PLANE)->where().width;

    y = (const uint8_t *)pvopcQuant->getPlane(Y_PLANE)->pixels(0,0);
    u = (const uint8_t *)pvopcQuant->getPlane(U_PLANE)->pixels(0,0);
    v = (const uint8_t *)pvopcQuant->getPlane(V_PLANE)->pixels(0,0);
    iso->m_last_time = displaytime;
#if 0
    player_debug_message("Adding video at "U64" %d", displaytime,
			 iso->m_pvodec->vopmd().vopPredType);
#endif

    iso->m_vft->video_have_frame(iso->m_ifptr, 
				y, 
				u, 
				v, 
				pixelw_y, 
				pixelw_uv, 
				displaytime);
  } else {
    iso_message(LOG_DEBUG, mp4iso, "decode but no frame "U64, ts->msec_timestamp);
  }
  return (iso->m_pvodec->get_used_bytes() + used);
}
コード例 #4
0
ファイル: xvid1_0.cpp プロジェクト: acassis/emlinux-ssd1935
static int xvid_decode (codec_data_t *ptr,
			frame_timestamp_t *pts, 
			int from_rtp,
			int *sync_frame,
			uint8_t *buffer, 
			uint32_t blen,
			void *ud)
{
  int ret;
  xvid_codec_t *xvid = (xvid_codec_t *)ptr;
  uint64_t ts = pts->msec_timestamp;
  int buflen = blen, used = 0;

  uint8_t *vop = MP4AV_Mpeg4FindVop(buffer, blen);
  int type = 0;
  if (vop != NULL) {
    type = MP4AV_Mpeg4GetVopType(vop, blen);
    uint64_t dts;
    if (MP4AV_calculate_dts_from_pts(&xvid->pts_to_dts,
				     ts,
				     type,
				     &dts) < 0) {
      return buflen;
    }
    ts = dts;
  }
#if 0
  xvid_message(LOG_DEBUG, "xvidif", "%u at %llu %d", 
	       blen, ts, type);
#endif

  if (xvid->m_decodeState == XVID_STATE_VO_SEARCH) {
    ret = look_for_vol(xvid, buffer, buflen);
    if (ret < 0) {
      return buflen;
    }
    xvid->m_decodeState = XVID_STATE_NORMAL;
  }
  xvid_dec_frame_t dec;
  xvid_dec_stats_t stats;
  do {
    memset(&dec, 0, sizeof(dec));
    memset(&stats, 0, sizeof(dec));
	   
    dec.version = XVID_VERSION;
    dec.bitstream = buffer;
    dec.length = buflen;
    dec.general = 0;
    dec.output.csp = XVID_CSP_INTERNAL;

    stats.version = XVID_VERSION;

    ret = xvid_decore(xvid->m_xvid_handle, 
		      XVID_DEC_DECODE, 
		      &dec, 
		      &stats);
#if 0
    xvid_message(LOG_DEBUG, "xvidif", "ret %d type %d blen %d of %u",
		 ret, stats.type, buflen, blen);
#endif
    if (ret < 0 || ret > buflen) {
      buflen = 0;
      used = blen;
    } else {
      buflen -= ret;
      buffer += ret;
      used += ret;
    }
    // we could check for vol changes, etc here, if we wanted.
  } while (buflen > 4 && stats.type <= 0);

  if (stats.type > 0) {
    xvid->m_vft->video_have_frame(xvid->m_ifptr,
				  (const uint8_t *)dec.output.plane[0],
				  (const uint8_t *)dec.output.plane[1],
				  (const uint8_t *)dec.output.plane[2],
				  dec.output.stride[0],
				  dec.output.stride[1],
				  ts);
  } 
#if 0
    xvid->m_vft->log_msg(LOG_DEBUG, "xvid", "error returned %d", ret);
#endif
    xvid->m_total_frames++;
  return (used);
}