Пример #1
0
static codec_data_t *ffmpeg_create (const char *stream_type,
                                    const char *compressor,
                                    int type,
                                    int profile,
                                    format_list_t *media_fmt,
                                    video_info_t *vinfo,
                                    const uint8_t *userdata,
                                    uint32_t ud_size,
                                    video_vft_t *vft,
                                    void *ifptr)
{
    ffmpeg_codec_t *ffmpeg;

    ffmpeg = MALLOC_STRUCTURE(ffmpeg_codec_t);
    memset(ffmpeg, 0, sizeof(*ffmpeg));

    ffmpeg->m_vft = vft;
    ffmpeg->m_ifptr = ifptr;
    avcodec_init();
    avcodec_register_all();
    av_log_set_level(AV_LOG_QUIET);

    ffmpeg->m_codecId = ffmpeg_find_codec(stream_type, compressor, type,
                                          profile, media_fmt, userdata, ud_size);

    // must have a codecID - we checked it earlier
    ffmpeg->m_codec = avcodec_find_decoder(ffmpeg->m_codecId);
    ffmpeg->m_c = avcodec_alloc_context();
    ffmpeg->m_picture = avcodec_alloc_frame();
    bool open_codec = true;
    bool run_userdata = false;
    bool free_userdata = false;

    switch (ffmpeg->m_codecId) {
    case CODEC_ID_MJPEG:
        break;
    case CODEC_ID_H264:
        // need to find height and width
        if (media_fmt != NULL && media_fmt->fmt_param != NULL) {
            userdata = h264_sdp_parse_sprop_param_sets(media_fmt->fmt_param,
                       &ud_size,
                       ffmpeg->m_vft->log_msg);
            if (userdata != NULL) free_userdata = true;
            ffmpeg_message(LOG_DEBUG, "ffmpeg", "sprop len %d", ud_size);
        }
        if (ud_size > 0) {
            ffmpeg_message(LOG_DEBUG, "ffmpeg", "userdata len %d", ud_size);
            open_codec = ffmpeg_find_h264_size(ffmpeg, userdata, ud_size);
            ffmpeg_message(LOG_DEBUG, "ffmpeg", "open codec is %d", open_codec);
            run_userdata = true;
        } else {
            open_codec = false;
        }
        break;
    case CODEC_ID_MPEG4: {
        fmtp_parse_t *fmtp = NULL;
        open_codec = false;
        if (media_fmt != NULL) {
            fmtp = parse_fmtp_for_mpeg4(media_fmt->fmt_param,
                                        ffmpeg->m_vft->log_msg);
            if (fmtp->config_binary != NULL) {
                userdata = fmtp->config_binary;
                ud_size = fmtp->config_binary_len;
                fmtp->config_binary = NULL;
                free_userdata = true;
            }
        }

        if (ud_size > 0) {
            uint8_t *vol = MP4AV_Mpeg4FindVol((uint8_t *)userdata, ud_size);
            u_int8_t TimeBits;
            u_int16_t TimeTicks;
            u_int16_t FrameDuration;
            u_int16_t FrameWidth;
            u_int16_t FrameHeight;
            u_int8_t  aspectRatioDefine;
            u_int8_t  aspectRatioWidth;
            u_int8_t  aspectRatioHeight;
            if (vol) {
                if (MP4AV_Mpeg4ParseVol(vol,
                                        ud_size - (vol - userdata),
                                        &TimeBits,
                                        &TimeTicks,
                                        &FrameDuration,
                                        &FrameWidth,
                                        &FrameHeight,
                                        &aspectRatioDefine,
                                        &aspectRatioWidth,
                                        &aspectRatioHeight)) {
                    ffmpeg->m_c->width = FrameWidth;
                    ffmpeg->m_c->height = FrameHeight;
                    open_codec = true;
                    run_userdata = true;
                }
            }
        }
        if (fmtp != NULL) {
            free_fmtp_parse(fmtp);
        }
    }
    break;
    case CODEC_ID_SVQ3:
        ffmpeg->m_c->extradata = (void *)userdata;
        ffmpeg->m_c->extradata_size = ud_size;
        if (vinfo != NULL) {
            ffmpeg->m_c->width = vinfo->width;
            ffmpeg->m_c->height = vinfo->height;
        }
        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 NULL;
        }
        ffmpeg_message(LOG_DEBUG, "ffmpeg", "pixel format is %d",
                       ffmpeg->m_c->pix_fmt);
        ffmpeg->m_codec_opened = true;
        if (run_userdata) {
            uint32_t offset = 0;
            do {
                int got_picture;
                offset += avcodec_decode_video(ffmpeg->m_c,
                                               ffmpeg->m_picture,
                                               &got_picture,
                                               (uint8_t *)userdata + offset,
                                               ud_size - offset);
            } while (offset < ud_size);
        }

    }

    if (free_userdata) {
        CHECK_AND_FREE(userdata);
    }
    ffmpeg->m_did_pause = 1;
    return ((codec_data_t *)ffmpeg);
}
Пример #2
0
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);
}
Пример #3
0
static int xvid_codec_check (lib_message_func_t message,
			     const char *compressor,
			     int type,
			     int profile,
			     format_list_t *fptr,
			     const uint8_t *userdata,
			     uint32_t userdata_size,
			     CConfigSet *pConfig)
{
  int retval;
  retval = 3;
  if (compressor != NULL && 
      (strcasecmp(compressor, "MP4 FILE") == 0)) {
    if ((type == MP4_MPEG4_VIDEO_TYPE) &&
	((profile >= MPEG4_SP_L1 && profile <= MPEG4_SP_L3) ||
	 (profile == MPEG4_SP_L0))) {
      return retval;
    }
    return -1;
  }
  if (fptr != NULL) {
    // find format. If matches, call parse_fmtp_for_mpeg4, look at
    // profile level.
    if (fptr->rtpmap != NULL && fptr->rtpmap->encode_name != NULL) {
      if (strcasecmp(fptr->rtpmap->encode_name, "MP4V-ES") == 0) {
	fmtp_parse_t *fmtp;
	media_desc_t *mptr = fptr->media;
	if (find_unparsed_a_value(mptr->unparsed_a_lines, "a=x-mpeg4-simple-profile-decoder") != NULL) {
	  // our own special code for simple profile decoder
	  return retval;
	}
	fmtp = parse_fmtp_for_mpeg4(fptr->fmt_param, message);
	int retvl = -1;
	if (fmtp != NULL) {
	  int profile = fmtp->profile_level_id;
	  if ((profile >= MPEG4_SP_L1 && profile <= MPEG4_SP_L3) || 
	      (profile == MPEG4_SP_L0)) {
	    retvl = retval;
	  } else if (fmtp->config_binary != NULL) {
	    // see if they indicate simple tools in VOL
#if 0
	    uint8_t *volptr;
	    volptr = MP4AV_Mpeg4FindVol(fmtp->config_binary, 
					fmtp->config_binary_len);
	    if (volptr != NULL && 
		((volptr[4] & 0x7f) == 0) &&
		((volptr[5] & 0x80) == 0x80)) {
message(LOG_ERR, "xvid", "indicated simple tools in xvid");
	      retvl = retval;
	    }
#endif
	  }
	  free_fmtp_parse(fmtp);
	}
	return retvl;
      }
    }
    return -1;
  }

  if (compressor != NULL) {
    const char **lptr = xvid_compressors;
    while (*lptr != NULL) {
      if (strcasecmp(*lptr, compressor) == 0) {
	return retval;
      }
      lptr++;
    }
  }
  return -1;
}
Пример #4
0
static int look_and_parse_vol (xvid_codec_t *xvid,
			       uint8_t *bufptr,
			       uint32_t len)
{
  uint8_t *volptr;
  uint32_t vollen;
  int ret;
  volptr = MP4AV_Mpeg4FindVol(bufptr, len);
  if (volptr == NULL) {
    return -1;
  }
  vollen = len - (volptr - bufptr);

  uint8_t timeBits;
  uint16_t timeTicks, dur, width, height;
  uint8_t aspect_ratio, aspect_ratio_w, aspect_ratio_h;
  if (MP4AV_Mpeg4ParseVol(volptr, 
			  vollen, 
			  &timeBits, 
			  &timeTicks,
			  &dur,
			  &width,
			  &height,
			  &aspect_ratio,
			  &aspect_ratio_w,
			  &aspect_ratio_h) == false) {
    return -1;
  }

  xvid_message(LOG_DEBUG, "xvid", "aspect ratio %x %d %d", 
	       aspect_ratio, aspect_ratio_w, aspect_ratio_h);
  // Get the VO/VOL header.  If we fail, set the bytestream back
  ret = 0;
  XVID_DEC_PARAM param;
  param.width = width;
  param.height = height;

  ret = xvid_decore(NULL, XVID_DEC_CREATE,
		    &param, NULL);
  if (ret != XVID_ERR_OK) {
    return -1;
  }
  double ar = 0.0;
  switch (aspect_ratio) {
  default:
    aspect_ratio_h = 0;
    break; 
  case 2:
    aspect_ratio_w = 12;
    aspect_ratio_h = 11;
    break;
  case 3:
    aspect_ratio_w = 10;
    aspect_ratio_h = 11;
    break;
  case 4:
    aspect_ratio_w = 16;
    aspect_ratio_h = 11;
    break;
  case 5:
    aspect_ratio_w = 40;
    aspect_ratio_h = 33;
    break;
  case 0xf:
    break;
  }
  if (aspect_ratio_h != 0) {
    ar = (double)aspect_ratio_w;
    ar *= (double) param.width;
    ar /= (double)aspect_ratio_h;
    ar /= (double)param.height;
  }
  xvid->m_xvid_handle = param.handle;
  xvid->m_vft->video_configure(xvid->m_ifptr, 
			       param.width,
			       param.height,
			       VIDEO_FORMAT_YUV,
			       ar);
  // we need to then run the VOL through the decoder.
  XVID_DEC_FRAME frame;
  XVID_DEC_PICTURE decpict;

  frame.bitstream = (void *)volptr;
  frame.length = vollen;
  frame.colorspace = XVID_CSP_USER;
  frame.image = &decpict;
  ret = xvid_decore(xvid->m_xvid_handle, XVID_DEC_DECODE, &frame, NULL);
  xvid_message(LOG_NOTICE, "xvidif", "decoded vol ret %d", ret);
  
  return ret == XVID_ERR_OK ? 0 : -1;
}
Пример #5
0
static int look_for_vol (xvid_codec_t *xvid, 
			 uint8_t *bufptr, 
			 uint32_t len)
{
  uint8_t *volptr;
  int vollen;
  int ret;
  volptr = MP4AV_Mpeg4FindVol(bufptr, len);
  if (volptr == NULL) {
    return -1 ;
  }
  vollen = len - (volptr - bufptr);

  uint8_t timeBits;
  uint16_t timeTicks, dur, width, height;
  uint8_t aspect_ratio, aspect_ratio_w, aspect_ratio_h;
  if (MP4AV_Mpeg4ParseVol(volptr, 
			  vollen, 
			  &timeBits, 
			  &timeTicks,
			  &dur,
			  &width,
			  &height,
			  &aspect_ratio,
			  &aspect_ratio_w,
			  &aspect_ratio_h) == false) {
    return -1;
  }

  xvid_message(LOG_DEBUG, "xvid", "aspect ratio %x %d %d", 
	       aspect_ratio, aspect_ratio_w, aspect_ratio_h);
  // Get the VO/VOL header.  If we fail, set the bytestream back

  xvid_dec_create_t create;
  create.version = XVID_VERSION;
  create.width = width;
  create.height = height;

  ret = xvid_decore(NULL, XVID_DEC_CREATE,
		    &create, NULL);
    double ar = 0.0;
    switch (aspect_ratio) {
    default:
      aspect_ratio_h = 0;
      break; 
    case 2:
      aspect_ratio_w = 12;
      aspect_ratio_h = 11;
      break;
    case 3:
      aspect_ratio_w = 10;
      aspect_ratio_h = 11;
      break;
    case 4:
      aspect_ratio_w = 16;
      aspect_ratio_h = 11;
      break;
    case 5:
      aspect_ratio_w = 40;
      aspect_ratio_h = 33;
      break;
    case 0xf:
      break;
    }
    if (aspect_ratio_h != 0) {
      ar = (double)aspect_ratio_w;
      ar *= (double) create.width;
      ar /= (double)aspect_ratio_h;
      ar /= (double)create.height;
    }
    xvid->m_xvid_handle = create.handle;
    xvid->m_vft->video_configure(xvid->m_ifptr, 
				 create.width,
				 create.height,
				 VIDEO_FORMAT_YUV,
				 ar);
   // we need to then run the VOL through the decoder.
  xvid_dec_frame_t dec;
  xvid_dec_stats_t stats;
  do {
    dec.version = XVID_VERSION;
    dec.bitstream = volptr;
    dec.length = vollen;
    dec.output.csp = XVID_CSP_INTERNAL;

    stats.version = XVID_VERSION;

    ret = xvid_decore(xvid->m_xvid_handle, 
		      XVID_DEC_DECODE, 
		      &dec, 
		      &stats);
    if (ret < 0) {
      xvid_message(LOG_NOTICE, "xvidif", "decoded vol ret %d", ret);
    }
      
    if (ret < 0 || ret > vollen) {
      vollen = 0;
    } else {
      vollen -= ret;
      volptr += ret;
    }
    // we could check for vol changes, etc here, if we wanted.
  } while (vollen > 4 && stats.type == 0);
  return 0;
}