static demuxer_t* demux_ppbox_open(demuxer_t* demuxer) { ppbox_demux_priv_t * priv = (ppbox_demux_priv_t *)calloc(sizeof(ppbox_demux_priv_t), 1); priv->duration = PPBOX_GetDuration()(); priv->stream_count = PPBOX_GetStreamCount()(); mp_msg(MSGT_DEMUX, MSGL_ERR, "demux_ppbox_open duration %u\n", priv->duration); mp_msg(MSGT_DEMUX, MSGL_ERR, "demux_ppbox_open stream count %u\n", priv->stream_count); for (uint32_t idx = 0; idx < priv->stream_count; ++idx) { PPBOX_StreamInfoEx info; PPBOX_GetStreamInfoEx()(idx, &info); if (info.type == ppbox_video) { mp_msg(MSGT_DEMUX, MSGL_ERR, "video stream\n"); sh_video_t* sh_video = new_sh_video(demuxer, idx);; BITMAPINFOHEADER *bih = calloc(sizeof(*bih) + info.format_size, 1); bih->biSize = sizeof(*bih) + info.format_size; bih->biCompression = mmioFOURCC('H', '2', '6', '4'); bih->biWidth = info.video_format.width; bih->biHeight = info.video_format.height; memcpy(bih + 1, info.format_buffer, info.format_size); sh_video->format = bih->biCompression; sh_video->disp_w = info.video_format.width; sh_video->disp_h = info.video_format.height; sh_video->fps = info.video_format.frame_rate; sh_video->frametime = 1.0 / info.video_format.frame_rate; sh_video->bih = bih; demuxer->video->sh = sh_video; priv->streams[idx] = demuxer->video; } else if (info.type == ppbox_audio) { mp_msg(MSGT_DEMUX, MSGL_ERR, "audio stream\n"); #if STREAMTYPE_PPBOX == 21 sh_audio_t* sh_audio = new_sh_audio(demuxer, idx); #else sh_audio_t* sh_audio = new_sh_audio(demuxer, idx, NULL); #endif WAVEFORMATEX *wf = calloc(sizeof(*wf) + info.format_size, 1);; wf->wFormatTag = 255; wf->nChannels = info.audio_format.channel_count; wf->nSamplesPerSec = info.audio_format.sample_rate; wf->wBitsPerSample = info.audio_format.sample_size; wf->cbSize = info.format_size; memcpy(wf + 1, info.format_buffer, info.format_size); sh_audio->wf = wf; sh_audio->format = mmioFOURCC('M', 'P', '4', 'A'); sh_audio->samplerate = info.audio_format.sample_rate; sh_audio->samplesize = info.audio_format.sample_size; sh_audio->channels = info.audio_format.channel_count; demuxer->audio->sh = sh_audio; demuxer->audio->id = idx; priv->streams[idx] = demuxer->audio; } } demuxer->seekable = priv->duration > 0; demuxer->priv = priv; return demuxer; }
static demuxer_t* demux_open_y4m(demuxer_t* demuxer){ y4m_priv_t* priv = demuxer->priv; sh_video_t* sh=new_sh_video(demuxer,0); priv->framenum = 0; priv->si = malloc(sizeof(y4m_stream_info_t)); sh->bih=calloc(1, sizeof(*sh->bih)); demuxer->video->sh=sh; sh->ds=demuxer->video; demuxer->video->id=0; read_streaminfo(demuxer); return demuxer; }
static demuxer_t* demux_open_rawdv(demuxer_t* demuxer) { unsigned char dv_frame[DV_PAL_FRAME_SIZE]; sh_video_t *sh_video = NULL; rawdv_frames_t *frames = malloc(sizeof(rawdv_frames_t)); dv_decoder_t *dv_decoder=NULL; mp_msg(MSGT_DEMUXER,MSGL_V,"demux_open_rawdv() end_pos %"PRId64"\n",(int64_t)demuxer->stream->end_pos); // go back to the beginning stream_reset(demuxer->stream); stream_seek(demuxer->stream, 0); //get the first frame stream_read(demuxer->stream, dv_frame, DV_PAL_FRAME_SIZE); //read params from this frame dv_decoder=dv_decoder_new(TRUE,TRUE,FALSE); dv_decoder->quality=DV_QUALITY_BEST; if (dv_parse_header(dv_decoder, dv_frame) == -1) return NULL; // create a new video stream header sh_video = new_sh_video(demuxer, 0); if (!sh_video) return NULL; // make sure the demuxer knows about the new video stream header // (even though new_sh_video() ought to take care of it) demuxer->seekable = 1; demuxer->video->sh = sh_video; // make sure that the video demuxer stream header knows about its // parent video demuxer stream (this is getting wacky), or else // video_read_properties() will choke sh_video->ds = demuxer->video; // custom fourcc for internal MPlayer use // sh_video->format = mmioFOURCC('R', 'A', 'D', 'V'); sh_video->format = mmioFOURCC('D', 'V', 'S', 'D'); sh_video->disp_w = dv_decoder->width; sh_video->disp_h = dv_decoder->height; mp_msg(MSGT_DEMUXER,MSGL_V,"demux_open_rawdv() frame_size: %d w: %d h: %d dif_seq: %d system: %d\n",dv_decoder->frame_size,dv_decoder->width, dv_decoder->height,dv_decoder->num_dif_seqs,dv_decoder->system); sh_video->fps= (dv_decoder->system==e_dv_system_525_60?29.97:25); sh_video->frametime = 1.0/sh_video->fps; // emulate BITMAPINFOHEADER for win32 decoders: sh_video->bih=malloc(sizeof(BITMAPINFOHEADER)); memset(sh_video->bih,0,sizeof(BITMAPINFOHEADER)); sh_video->bih->biSize=40; sh_video->bih->biWidth = dv_decoder->width; sh_video->bih->biHeight = dv_decoder->height; sh_video->bih->biPlanes=1; sh_video->bih->biBitCount=24; sh_video->bih->biCompression=sh_video->format; // "DVSD" sh_video->bih->biSizeImage=sh_video->bih->biWidth*sh_video->bih->biHeight*3; frames->current_filepos=0; frames->current_frame=0; frames->frame_size=dv_decoder->frame_size; frames->frame_number=demuxer->stream->end_pos/frames->frame_size; mp_msg(MSGT_DEMUXER,MSGL_V,"demux_open_rawdv() seek to %qu, size: %d, dv_dec->frame_size: %d\n",frames->current_filepos,frames->frame_size, dv_decoder->frame_size); if (dv_decoder->audio != NULL && demuxer->audio->id>=-1){ sh_audio_t *sh_audio = new_sh_audio(demuxer, 0); demuxer->audio->sh = sh_audio; sh_audio->ds = demuxer->audio; mp_msg(MSGT_DEMUXER,MSGL_V,"demux_open_rawdv() chan: %d samplerate: %d\n",dv_decoder->audio->num_channels,dv_decoder->audio->frequency ); // custom fourcc for internal MPlayer use sh_audio->format = mmioFOURCC('R', 'A', 'D', 'V'); sh_audio->wf = malloc(sizeof(WAVEFORMATEX)); memset(sh_audio->wf, 0, sizeof(WAVEFORMATEX)); sh_audio->wf->wFormatTag = sh_audio->format; sh_audio->wf->nChannels = dv_decoder->audio->num_channels; sh_audio->wf->wBitsPerSample = 16; sh_audio->wf->nSamplesPerSec = dv_decoder->audio->frequency; // info about the input stream: sh_audio->wf->nAvgBytesPerSec = sh_video->fps*dv_decoder->frame_size; sh_audio->wf->nBlockAlign = dv_decoder->frame_size; // sh_audio->context=(void*)dv_decoder; } stream_reset(demuxer->stream); stream_seek(demuxer->stream, 0); dv_decoder_free(dv_decoder); //we keep this in the context of both stream headers demuxer->priv=frames; return demuxer; }
static demuxer_t* demux_open_tv(demuxer_t *demuxer) { tvi_handle_t *tvh; sh_video_t *sh_video; sh_audio_t *sh_audio = NULL; const tvi_functions_t *funcs; demuxer->priv=NULL; if(!(tvh=tv_begin(demuxer->stream->priv))) return NULL; if (!tvh->functions->init(tvh->priv)) return NULL; tvh->demuxer = demuxer; tvh->functions->control(tvh->priv,TVI_CONTROL_VBI_INIT, &(tvh->tv_param->teletext.device)); tvh->functions->control(tvh->priv,TVI_CONTROL_GET_VBI_PTR, &demuxer->teletext); if (!open_tv(tvh)) { tv_uninit(tvh); return NULL; } funcs = tvh->functions; demuxer->priv=tvh; sh_video = new_sh_video(demuxer, 0); /* get IMAGE FORMAT */ funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FORMAT, &sh_video->format); // if (IMGFMT_IS_RGB(sh_video->format) || IMGFMT_IS_BGR(sh_video->format)) // sh_video->format = 0x0; /* set FPS and FRAMETIME */ if(!sh_video->fps) { float tmp; if (funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FPS, &tmp) != TVI_CONTROL_TRUE) sh_video->fps = 25.0f; /* on PAL */ else sh_video->fps = tmp; } if (tvh->tv_param->fps != -1.0f) sh_video->fps = tvh->tv_param->fps; sh_video->frametime = 1.0f/sh_video->fps; /* If playback only mode, go to immediate mode, fail silently */ if(tvh->tv_param->immediate == 1) { funcs->control(tvh->priv, TVI_CONTROL_IMMEDIATE, 0); tvh->tv_param->noaudio = 1; } /* disable TV audio if -nosound is present */ if (!demuxer->audio || demuxer->audio->id == -2) { tvh->tv_param->noaudio = 1; } /* set width */ funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &sh_video->disp_w); /* set height */ funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &sh_video->disp_h); demuxer->video->sh = sh_video; sh_video->ds = demuxer->video; demuxer->video->id = 0; demuxer->seekable = 0; /* here comes audio init */ if (tvh->tv_param->noaudio == 0 && funcs->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE) { int audio_format; int sh_audio_format; char buf[128]; /* yeah, audio is present */ funcs->control(tvh->priv, TVI_CONTROL_AUD_SET_SAMPLERATE, &tvh->tv_param->audiorate); if (funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_FORMAT, &audio_format) != TVI_CONTROL_TRUE) goto no_audio; switch(audio_format) { case AF_FORMAT_U8: case AF_FORMAT_S8: case AF_FORMAT_U16_LE: case AF_FORMAT_U16_BE: case AF_FORMAT_S16_LE: case AF_FORMAT_S16_BE: case AF_FORMAT_S32_LE: case AF_FORMAT_S32_BE: sh_audio_format = 0x1; /* PCM */ break; case AF_FORMAT_IMA_ADPCM: case AF_FORMAT_MU_LAW: case AF_FORMAT_A_LAW: case AF_FORMAT_MPEG2: default: mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_UnsupportedAudioType, af_fmt2str(audio_format, buf, 128), audio_format); goto no_audio; } sh_audio = new_sh_audio(demuxer, 0, NULL); funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLERATE, &sh_audio->samplerate); funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLESIZE, &sh_audio->samplesize); funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_CHANNELS, &sh_audio->channels); sh_audio->format = sh_audio_format; sh_audio->sample_format = audio_format; sh_audio->i_bps = sh_audio->o_bps = sh_audio->samplerate * sh_audio->samplesize * sh_audio->channels; // emulate WF for win32 codecs: sh_audio->wf = malloc(sizeof(*sh_audio->wf)); sh_audio->wf->wFormatTag = sh_audio->format; sh_audio->wf->nChannels = sh_audio->channels; sh_audio->wf->wBitsPerSample = sh_audio->samplesize * 8; sh_audio->wf->nSamplesPerSec = sh_audio->samplerate; sh_audio->wf->nBlockAlign = sh_audio->samplesize * sh_audio->channels; sh_audio->wf->nAvgBytesPerSec = sh_audio->i_bps; mp_msg(MSGT_DECVIDEO, MSGL_V, " TV audio: %d channels, %d bits, %d Hz\n", sh_audio->wf->nChannels, sh_audio->wf->wBitsPerSample, sh_audio->wf->nSamplesPerSec); demuxer->audio->sh = sh_audio; sh_audio->ds = demuxer->audio; demuxer->audio->id = 0; } no_audio: if(!(funcs->start(tvh->priv))) { // start failed :( tv_uninit(tvh); return NULL; } /* set color eq */ tv_set_color_options(tvh, TV_COLOR_BRIGHTNESS, tvh->tv_param->brightness); tv_set_color_options(tvh, TV_COLOR_HUE, tvh->tv_param->hue); tv_set_color_options(tvh, TV_COLOR_SATURATION, tvh->tv_param->saturation); tv_set_color_options(tvh, TV_COLOR_CONTRAST, tvh->tv_param->contrast); if(tvh->tv_param->gain!=-1) if(funcs->control(tvh->priv,TVI_CONTROL_VID_SET_GAIN,&tvh->tv_param->gain)!=TVI_CONTROL_TRUE) mp_msg(MSGT_TV,MSGL_WARN,"Unable to set gain control!\n"); teletext_control(demuxer->teletext,TV_VBI_CONTROL_RESET, &tvh->tv_param->teletext); return demuxer; }
void rtpCodecInitialize_video(demuxer_t* demuxer, MediaSubsession* subsession, unsigned& flags) { flags = 0; // Create a dummy video stream header // to make the main MPlayer code happy: sh_video_t* sh_video = new_sh_video(demuxer,0); BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)calloc(1,sizeof(BITMAPINFOHEADER)); bih->biSize = sizeof(BITMAPINFOHEADER); sh_video->bih = bih; demux_stream_t* d_video = demuxer->video; d_video->sh = sh_video; sh_video->ds = d_video; // Map known video MIME types to the BITMAPINFOHEADER parameters // that this program uses. (Note that not all types need all // of the parameters to be set.) if (strcmp(subsession->codecName(), "MPV") == 0) { flags |= RTPSTATE_IS_MPEG12_VIDEO; } else if (strcmp(subsession->codecName(), "MP1S") == 0 || strcmp(subsession->codecName(), "MP2T") == 0) { flags |= RTPSTATE_IS_MPEG12_VIDEO|RTPSTATE_IS_MULTIPLEXED; } else if (strcmp(subsession->codecName(), "H263") == 0 || strcmp(subsession->codecName(), "H263-2000") == 0 || strcmp(subsession->codecName(), "H263-1998") == 0) { bih->biCompression = sh_video->format = mmioFOURCC('H','2','6','3'); needVideoFrameRate(demuxer, subsession); } else if (strcmp(subsession->codecName(), "H264") == 0) { bih->biCompression = sh_video->format = mmioFOURCC('H','2','6','4'); unsigned int configLen = 0; unsigned char* configData = parseH264ConfigStr(subsession->fmtp_spropparametersets(), configLen); sh_video->bih = bih = insertVideoExtradata(bih, configData, configLen); delete[] configData; #ifdef USE_LIBAVCODEC av_register_codec_parser(&h264_parser); h264parserctx = av_parser_init(CODEC_ID_H264); #endif needVideoFrameRate(demuxer, subsession); } else if (strcmp(subsession->codecName(), "H261") == 0) { bih->biCompression = sh_video->format = mmioFOURCC('H','2','6','1'); needVideoFrameRate(demuxer, subsession); } else if (strcmp(subsession->codecName(), "JPEG") == 0) { bih->biCompression = sh_video->format = mmioFOURCC('M','J','P','G'); needVideoFrameRate(demuxer, subsession); } else if (strcmp(subsession->codecName(), "MP4V-ES") == 0) { bih->biCompression = sh_video->format = mmioFOURCC('m','p','4','v'); // For the codec to work correctly, it may need a 'VOL Header' to be // inserted at the front of the data stream. Construct this from the // "config" MIME parameter, which was present (hopefully) in the // session's SDP description: unsigned configLen; unsigned char* configData = parseGeneralConfigStr(subsession->fmtp_config(), configLen); sh_video->bih = bih = insertVideoExtradata(bih, configData, configLen); needVideoFrameRate(demuxer, subsession); } else if (strcmp(subsession->codecName(), "X-QT") == 0 || strcmp(subsession->codecName(), "X-QUICKTIME") == 0) { // QuickTime generic RTP format, as described in // http://developer.apple.com/quicktime/icefloe/dispatch026.html // We can't initialize this stream until we've received the first packet // that has QuickTime "sdAtom" information in the header. So, keep // reading packets until we get one: unsigned char* packetData; unsigned packetDataLen; float pts; QuickTimeGenericRTPSource* qtRTPSource = (QuickTimeGenericRTPSource*)(subsession->rtpSource()); unsigned fourcc; do { if (!awaitRTPPacket(demuxer, demuxer->video, packetData, packetDataLen, pts)) { return; } } while (!parseQTState_video(qtRTPSource->qtState, fourcc)); bih->biCompression = sh_video->format = fourcc; bih->biWidth = qtRTPSource->qtState.width; bih->biHeight = qtRTPSource->qtState.height; uint8_t *pos = (uint8_t*)qtRTPSource->qtState.sdAtom + 86; uint8_t *endpos = (uint8_t*)qtRTPSource->qtState.sdAtom + qtRTPSource->qtState.sdAtomSize; while (pos+8 < endpos) { unsigned atomLength = pos[0]<<24 | pos[1]<<16 | pos[2]<<8 | pos[3]; if (atomLength == 0 || atomLength > endpos-pos) break; if ((!memcmp(pos+4, "avcC", 4) && fourcc==mmioFOURCC('a','v','c','1') || !memcmp(pos+4, "esds", 4) || !memcmp(pos+4, "SMI ", 4) && fourcc==mmioFOURCC('S','V','Q','3')) && atomLength > 8) { sh_video->bih = bih = insertVideoExtradata(bih, pos+8, atomLength-8); break; } pos += atomLength; } needVideoFrameRate(demuxer, subsession); } else { fprintf(stderr, "Unknown MPlayer format code for MIME type \"video/%s\"\n", subsession->codecName()); } }
/** * \brief MPlayer callback: Open MNG stream. * \param[in] demuxer demuxer structure * \return demuxer structure on success, \p NULL on error */ static demuxer_t * demux_mng_open(demuxer_t * demuxer) { mng_priv_t * mng_priv; mng_handle h_mng; mng_retcode mng_ret; sh_video_t * sh_video; // create private data structure mng_priv = calloc(1, sizeof(mng_priv_t)); //stream pointer into private data mng_priv->stream = demuxer->stream; // initialize MNG image instance h_mng = mng_initialize((mng_ptr)mng_priv, demux_mng_alloc, demux_mng_free, MNG_NULL); if (!h_mng) { mp_msg(MSGT_DEMUX, MSGL_ERR, "demux_mng: could not initialize MNG image instance\n"); free(mng_priv); return NULL; } // MNG image handle into private data mng_priv->h_mng = h_mng; // set required MNG callbacks if (mng_setcb_openstream(h_mng, demux_mng_openstream) || mng_setcb_closestream(h_mng, demux_mng_closestream) || mng_setcb_readdata(h_mng, demux_mng_readdata) || mng_setcb_processheader(h_mng, demux_mng_processheader) || mng_setcb_getcanvasline(h_mng, demux_mng_getcanvasline) || mng_setcb_refresh(h_mng, demux_mng_refresh) || mng_setcb_gettickcount(h_mng, demux_mng_gettickcount) || mng_setcb_settimer(h_mng, demux_mng_settimer) || mng_set_canvasstyle(h_mng, MNG_CANVAS_RGBA8)) { mp_msg(MSGT_DEMUX, MSGL_ERR, "demux_mng: could not set MNG callbacks\n"); mng_cleanup(&h_mng); free(mng_priv); return NULL; } // start reading MNG data mng_ret = mng_read(h_mng); if (mng_ret) { mp_msg(MSGT_DEMUX, MSGL_ERR, "demux_mng: could not start reading MNG data: " "mng_retcode %d\n", mng_ret); mng_cleanup(&h_mng); free(mng_priv); return NULL; } // check that MNG header is processed now if (!mng_priv->header_processed) { mp_msg(MSGT_DEMUX, MSGL_ERR, "demux_mng: internal error: header not processed\n"); mng_cleanup(&h_mng); free(mng_priv); return NULL; } // create a new video stream header sh_video = new_sh_video(demuxer, 0); // Make sure the demuxer knows about the new video stream header // (even though new_sh_video() ought to take care of it). // (Thanks to demux_gif.c for this.) demuxer->video->sh = sh_video; // Make sure that the video demuxer stream header knows about its // parent video demuxer stream (this is getting wacky), or else // video_read_properties() will choke. // (Thanks to demux_gif.c for this.) sh_video->ds = demuxer->video; // set format of pixels in video packets sh_video->format = mmioFOURCC(32, 'B', 'G', 'R'); // set framerate to some value (MNG does not have a fixed framerate) sh_video->fps = 5.0f; sh_video->frametime = 1.0f / sh_video->fps; // set video frame parameters sh_video->bih = malloc(sizeof(*sh_video->bih)); sh_video->bih->biCompression = sh_video->format; sh_video->bih->biWidth = mng_priv->width; sh_video->bih->biHeight = mng_priv->height; sh_video->bih->biBitCount = 32; sh_video->bih->biPlanes = 1; // Set start time to something > 0. // - This is required for the variable frame time mechanism // (GIF, MATROSKA, MNG) in video.c to work for the first frame. sh_video->ds->pts = MNG_START_PTS; // set private data in demuxer and return demuxer demuxer->priv = mng_priv; return demuxer; }
static demuxer_t* demux_open_fli(demuxer_t* demuxer){ sh_video_t *sh_video = NULL; fli_frames_t *frames = malloc(sizeof(fli_frames_t)); int frame_number; int speed; unsigned int frame_size; int magic_number; unsigned char * header; // go back to the beginning stream_reset(demuxer->stream); stream_seek(demuxer->stream, 0); header = calloc(1, sizeof(BITMAPINFOHEADER) + 128); stream_read(demuxer->stream, header + sizeof(BITMAPINFOHEADER), 128); stream_seek(demuxer->stream, 0); demuxer->movi_start = 128; demuxer->movi_end = stream_read_dword_le(demuxer->stream); magic_number = stream_read_word_le(demuxer->stream); if ((magic_number != 0xAF11) && (magic_number != 0xAF12)) { mp_msg(MSGT_DEMUX, MSGL_ERR, "Bad/unknown magic number (%04x)\n", magic_number); free(header); free(frames); return NULL; } // fetch the number of frames frames->num_frames = stream_read_word_le(demuxer->stream); frames->current_frame = 0; // allocate enough entries for the indices // audit: num_frames is 16bit so it is safe against overflow frames->filepos = malloc(frames->num_frames * sizeof(off_t)); frames->frame_size = malloc(frames->num_frames * sizeof(int)); // create a new video stream header sh_video = new_sh_video(demuxer, 0); // make sure the demuxer knows about the new video stream header // (even though new_sh_video() ought to take care of it) demuxer->video->sh = sh_video; // make sure that the video demuxer stream header knows about its // parent video demuxer stream (this is getting wacky), or else // video_read_properties() will choke sh_video->ds = demuxer->video; // custom fourcc for internal MPlayer use sh_video->format = mmioFOURCC('F', 'L', 'I', 'C'); sh_video->disp_w = stream_read_word_le(demuxer->stream); sh_video->disp_h = stream_read_word_le(demuxer->stream); // pass extradata to codec sh_video->bih = (BITMAPINFOHEADER*)header; sh_video->bih->biSize = sizeof(BITMAPINFOHEADER) + 128; sh_video->bih->biWidth = sh_video->disp_w; sh_video->bih->biHeight = sh_video->disp_h; // skip the video depth and flags stream_skip(demuxer->stream, 4); // get the speed speed = stream_read_word_le(demuxer->stream); if (speed == 0) speed = 1; if (magic_number == 0xAF11) speed *= 1000/70; sh_video->fps = 1000 / speed; sh_video->frametime = 1/sh_video->fps; // build the frame index stream_seek(demuxer->stream, demuxer->movi_start); frame_number = 0; while ((!stream_eof(demuxer->stream)) && (frame_number < frames->num_frames)) { frames->filepos[frame_number] = stream_tell(demuxer->stream); frame_size = stream_read_dword_le(demuxer->stream); magic_number = stream_read_word_le(demuxer->stream); stream_skip(demuxer->stream, frame_size - 6); // if this chunk has the right magic number, index it if ((magic_number == 0xF1FA) || (magic_number == 0xF5FA)) { frames->frame_size[frame_number] = frame_size; frame_number++; } } // save the actual number of frames indexed frames->num_frames = frame_number; demuxer->priv = frames; return demuxer; }
static demuxer_t* demux_open_avs(demuxer_t* demuxer) { int found = 0; AVS_T *AVS = demuxer->priv; int audio_samplesize = 0; AVS->frameno = 0; AVS->sampleno = 0; mp_msg(MSGT_DEMUX, MSGL_V, "AVS: demux_open_avs()\n"); demuxer->seekable = 1; AVS->clip = AVS->avs_take_clip(AVS->handler, AVS->avs_env); if(!AVS->clip) { mp_msg(MSGT_DEMUX, MSGL_V, "AVS: avs_take_clip() failed\n"); return NULL; } AVS->video_info = AVS->avs_get_video_info(AVS->clip); if (!AVS->video_info) { mp_msg(MSGT_DEMUX, MSGL_V, "AVS: avs_get_video_info() call failed\n"); return NULL; } if (!avs_is_yv12(AVS->video_info)) { AVS->handler = AVS->avs_invoke(AVS->avs_env, "ConvertToYV12", avs_new_value_array(&AVS->handler, 1), 0); if (avs_is_error(AVS->handler)) { mp_msg(MSGT_DEMUX, MSGL_V, "AVS: Cannot convert input video to YV12: %s\n", avs_as_string(AVS->handler)); return NULL; } AVS->clip = AVS->avs_take_clip(AVS->handler, AVS->avs_env); if(!AVS->clip) { mp_msg(MSGT_DEMUX, MSGL_V, "AVS: avs_take_clip() failed\n"); return NULL; } AVS->video_info = AVS->avs_get_video_info(AVS->clip); if (!AVS->video_info) { mp_msg(MSGT_DEMUX, MSGL_V, "AVS: avs_get_video_info() call failed\n"); return NULL; } } // TODO check field-based ?? /* Video */ if (avs_has_video(AVS->video_info)) { sh_video_t *sh_video = new_sh_video(demuxer, 0); found = 1; if (demuxer->video->id == -1) demuxer->video->id = 0; if (demuxer->video->id == 0) demuxer->video->sh = sh_video; sh_video->ds = demuxer->video; sh_video->disp_w = AVS->video_info->width; sh_video->disp_h = AVS->video_info->height; //sh_video->format = get_mmioFOURCC(AVS->video_info); sh_video->format = mmioFOURCC('Y', 'V', '1', '2'); sh_video->fps = (double) AVS->video_info->fps_numerator / (double) AVS->video_info->fps_denominator; sh_video->frametime = 1.0 / sh_video->fps; sh_video->bih = malloc(sizeof(BITMAPINFOHEADER) + (256 * 4)); sh_video->bih->biCompression = sh_video->format; sh_video->bih->biBitCount = avs_bits_per_pixel(AVS->video_info); //sh_video->bih->biPlanes = 2; sh_video->bih->biWidth = AVS->video_info->width; sh_video->bih->biHeight = AVS->video_info->height; sh_video->num_frames = 0; sh_video->num_frames_decoded = 0; } /* Audio */ if (avs_has_audio(AVS->video_info)) switch (AVS->video_info->sample_type) { case AVS_SAMPLE_INT8: audio_samplesize = 1; break; case AVS_SAMPLE_INT16: audio_samplesize = 2; break; case AVS_SAMPLE_INT24: audio_samplesize = 3; break; case AVS_SAMPLE_INT32: case AVS_SAMPLE_FLOAT: audio_samplesize = 4; break; default: mp_msg(MSGT_DEMUX, MSGL_ERR, "AVS: unknown audio type, disabling\n"); } if (audio_samplesize) { sh_audio_t *sh_audio = new_sh_audio(demuxer, 0); found = 1; mp_msg(MSGT_DEMUX, MSGL_V, "AVS: Clip has audio -> Channels = %d - Freq = %d\n", AVS->video_info->nchannels, AVS->video_info->audio_samples_per_second); if (demuxer->audio->id == -1) demuxer->audio->id = 0; if (demuxer->audio->id == 0) demuxer->audio->sh = sh_audio; sh_audio->ds = demuxer->audio; sh_audio->wf = malloc(sizeof(WAVEFORMATEX)); sh_audio->wf->wFormatTag = sh_audio->format = (AVS->video_info->sample_type == AVS_SAMPLE_FLOAT) ? 0x3 : 0x1; sh_audio->wf->nChannels = sh_audio->channels = AVS->video_info->nchannels; sh_audio->wf->nSamplesPerSec = sh_audio->samplerate = AVS->video_info->audio_samples_per_second; sh_audio->samplesize = audio_samplesize; sh_audio->wf->nAvgBytesPerSec = sh_audio->channels * sh_audio->samplesize * sh_audio->samplerate; sh_audio->wf->nBlockAlign = sh_audio->channels * sh_audio->samplesize; sh_audio->wf->wBitsPerSample = sh_audio->samplesize * 8; sh_audio->wf->cbSize = 0; sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec; } AVS->init = 1; if (found) return demuxer; else return NULL; }
static demuxer_t* demux_open_rtp(demuxer_t* demuxer) { nms_rtsp_hints hints; char * url = demuxer->stream->streaming_ctrl->url->url; rtsp_ctrl * ctl; RTSP_Error reply; rtsp_medium * media; Nemesi_DemuxerStreamData * ndsd = calloc(1, sizeof(Nemesi_DemuxerStreamData)); memset(&hints,0,sizeof(hints)); if (rtsp_port) hints.first_rtp_port = rtsp_port; if (rtsp_transport_tcp) { hints.pref_rtsp_proto = TCP; hints.pref_rtp_proto = TCP; } if (rtsp_transport_sctp) { hints.pref_rtsp_proto = SCTP; hints.pref_rtp_proto = SCTP; } mp_msg(MSGT_DEMUX, MSGL_INFO, "Initializing libNemesi\n"); if ((ctl = rtsp_init(&hints)) == NULL) { free(ndsd); return STREAM_ERROR; } ndsd->rtsp = ctl; demuxer->priv = ndsd; //nms_verbosity_set(1); mp_msg(MSGT_DEMUX, MSGL_INFO, "Opening: %s\n", url); if (rtsp_open(ctl, url)) { mp_msg(MSGT_DEMUX, MSGL_ERR, "rtsp_open failed.\n"); return demuxer; } reply = rtsp_wait(ctl); if (reply.got_error) { mp_msg(MSGT_DEMUX, MSGL_ERR, "OPEN Error from the server: %s\n", reply.message.reply_str); return demuxer; } rtsp_play(ctl, 0, 0); reply = rtsp_wait(ctl); if (reply.got_error) { mp_msg(MSGT_DEMUX, MSGL_ERR, "PLAY Error from the server: %s\n", reply.message.reply_str); return demuxer; } if (!ctl->rtsp_queue) return demuxer; media = ctl->rtsp_queue->media_queue; for (; media; media=media->next) { sdp_medium_info * info = media->medium_info; rtp_session * sess = media->rtp_sess; rtp_buff buff; int media_format = atoi(info->fmts); rtp_pt * ptinfo = rtp_get_pt_info(sess, media_format); char const * format_name = ptinfo ? ptinfo->name : NULL; memset(&buff, 0, sizeof(rtp_buff)); if (sess->parsers[media_format] == NULL) { mp_msg(MSGT_DEMUX, MSGL_ERR, "libNemesi unsupported media format: %s\n", format_name ? format_name : info->fmts); continue; } else { mp_msg(MSGT_DEMUX, MSGL_INFO, "libNemesi supported media: %s\n", format_name); } if (ptinfo->type == AU) { if (ndsd->session[NEMESI_SESSION_AUDIO] == NULL) { sh_audio_t* sh_audio = new_sh_audio(demuxer,0, NULL); WAVEFORMATEX* wf; demux_stream_t* d_audio = demuxer->audio; demuxer->audio->id = 0; mp_msg(MSGT_DEMUX, MSGL_INFO, "Detected as AUDIO stream...\n"); link_session_and_fetch_conf(ndsd, NEMESI_SESSION_AUDIO, sess, &buff, NULL); wf = calloc(1,sizeof(*wf)+buff.len); wf->cbSize = buff.len; memcpy(wf+1, buff.data, buff.len); sh_audio->wf = wf; d_audio->sh = sh_audio; wf->nSamplesPerSec = 0; wf->wFormatTag = sh_audio->format = get4CC(supported_audio, format_name); if ( !(wf->wFormatTag) ) mp_msg(MSGT_DEMUX, MSGL_WARN, "Unknown MPlayer format code for MIME" " type \"audio/%s\"\n", format_name); } else { mp_msg(MSGT_DEMUX, MSGL_ERR, "There is already an audio session registered," " ignoring...\n"); } } else if (ptinfo->type == VI) { if (ndsd->session[NEMESI_SESSION_VIDEO] == NULL) { sh_video_t* sh_video; BITMAPINFOHEADER* bih; demux_stream_t* d_video; int fps = 0; mp_msg(MSGT_DEMUX, MSGL_INFO, "Detected as VIDEO stream...\n"); link_session_and_fetch_conf(ndsd, NEMESI_SESSION_VIDEO, sess, &buff, &fps); bih = calloc(1,sizeof(*bih)+buff.len); bih->biSize = sizeof(*bih)+buff.len; memcpy(bih+1, buff.data, buff.len); sh_video = new_sh_video(demuxer,0); sh_video->bih = bih; d_video = demuxer->video; d_video->sh = sh_video; if (fps) { sh_video->fps = fps; sh_video->frametime = 1.0/fps; } bih->biCompression = sh_video->format = get4CC(supported_video, format_name); if ( !(bih->biCompression) ) { mp_msg(MSGT_DEMUX, MSGL_WARN, "Unknown MPlayer format code for MIME" " type \"video/%s\"\n", format_name); } } else { mp_msg(MSGT_DEMUX, MSGL_ERR, "There is already a video session registered," " ignoring...\n"); } } else { mp_msg(MSGT_DEMUX, MSGL_ERR, "Unsupported media type\n"); } } demuxer->stream->eof = 0; return demuxer; }
static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i) { lavf_priv_t *priv= demuxer->priv; AVStream *st= avfc->streams[i]; AVCodecContext *codec= st->codec; int g; switch(codec->codec_type){ case CODEC_TYPE_AUDIO:{ WAVEFORMATEX *wf= calloc(sizeof(WAVEFORMATEX) + codec->extradata_size, 1); sh_audio_t* sh_audio; if(priv->audio_streams >= MAX_A_STREAMS) break; sh_audio=new_sh_audio(demuxer, i); mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "lavf", i); if(!sh_audio) break; priv->astreams[priv->audio_streams] = i; priv->audio_streams++; // mp4a tag is used for all mp4 files no matter what they actually contain if(codec->codec_tag == MKTAG('m', 'p', '4', 'a')) codec->codec_tag= 0; if(codec->codec_id == CODEC_ID_ADPCM_IMA_AMV) codec->codec_tag= MKTAG('A','M','V','A'); if(!codec->codec_tag) codec->codec_tag= av_codec_get_tag(mp_wav_taglists, codec->codec_id); wf->wFormatTag= codec->codec_tag; wf->nChannels= codec->channels; wf->nSamplesPerSec= codec->sample_rate; wf->nAvgBytesPerSec= codec->bit_rate/8; wf->nBlockAlign= codec->block_align ? codec->block_align : 1; wf->wBitsPerSample= codec->bits_per_sample; wf->cbSize= codec->extradata_size; if(codec->extradata_size) memcpy(wf + 1, codec->extradata, codec->extradata_size); sh_audio->wf= wf; sh_audio->audio.dwSampleSize= codec->block_align; if(codec->frame_size && codec->sample_rate){ sh_audio->audio.dwScale=codec->frame_size; sh_audio->audio.dwRate= codec->sample_rate; }else{ sh_audio->audio.dwScale= codec->block_align ? codec->block_align*8 : 8; sh_audio->audio.dwRate = codec->bit_rate; } g= ff_gcd(sh_audio->audio.dwScale, sh_audio->audio.dwRate); sh_audio->audio.dwScale /= g; sh_audio->audio.dwRate /= g; // printf("sca:%d rat:%d fs:%d sr:%d ba:%d\n", sh_audio->audio.dwScale, sh_audio->audio.dwRate, codec->frame_size, codec->sample_rate, codec->block_align); sh_audio->ds= demuxer->audio; sh_audio->format= codec->codec_tag; sh_audio->channels= codec->channels; sh_audio->samplerate= codec->sample_rate; sh_audio->i_bps= codec->bit_rate/8; switch (codec->codec_id) { case CODEC_ID_PCM_S8: case CODEC_ID_PCM_U8: sh_audio->samplesize = 1; break; case CODEC_ID_PCM_S16LE: case CODEC_ID_PCM_S16BE: case CODEC_ID_PCM_U16LE: case CODEC_ID_PCM_U16BE: sh_audio->samplesize = 2; break; case CODEC_ID_PCM_ALAW: sh_audio->format = 0x6; break; case CODEC_ID_PCM_MULAW: sh_audio->format = 0x7; break; } if(mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf, MSGL_V); if((audio_lang && st->language[0] && !strncmp(audio_lang, st->language, 3)) || (demuxer->audio->id == i || demuxer->audio->id == -1)) { demuxer->audio->id = i; demuxer->audio->sh= demuxer->a_streams[i]; } else st->discard= AVDISCARD_ALL; break; } case CODEC_TYPE_VIDEO:{ sh_video_t* sh_video; BITMAPINFOHEADER *bih; if(priv->video_streams >= MAX_V_STREAMS) break; sh_video=new_sh_video(demuxer, i); mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_VideoID, "lavf", i); if(!sh_video) break; priv->vstreams[priv->video_streams] = i; priv->video_streams++; bih=calloc(sizeof(BITMAPINFOHEADER) + codec->extradata_size,1); if(!codec->codec_tag) codec->codec_tag= av_codec_get_tag(mp_bmp_taglists, codec->codec_id); bih->biSize= sizeof(BITMAPINFOHEADER) + codec->extradata_size; bih->biWidth= codec->width; bih->biHeight= codec->height; bih->biBitCount= codec->bits_per_sample; bih->biSizeImage = bih->biWidth * bih->biHeight * bih->biBitCount/8; bih->biCompression= codec->codec_tag; sh_video->bih= bih; sh_video->disp_w= codec->width; sh_video->disp_h= codec->height; if (st->time_base.den) { /* if container has time_base, use that */ sh_video->video.dwRate= st->time_base.den; sh_video->video.dwScale= st->time_base.num; } else { sh_video->video.dwRate= codec->time_base.den; sh_video->video.dwScale= codec->time_base.num; } sh_video->fps=av_q2d(st->r_frame_rate); sh_video->frametime=1/av_q2d(st->r_frame_rate); sh_video->format=bih->biCompression; sh_video->aspect=codec->width * codec->sample_aspect_ratio.num / (float)(codec->height * codec->sample_aspect_ratio.den); sh_video->i_bps=codec->bit_rate/8; mp_msg(MSGT_DEMUX,MSGL_DBG2,"aspect= %d*%d/(%d*%d)\n", codec->width, codec->sample_aspect_ratio.num, codec->height, codec->sample_aspect_ratio.den); sh_video->ds= demuxer->video; if(codec->extradata_size) memcpy(sh_video->bih + 1, codec->extradata, codec->extradata_size); if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V); /* short biPlanes; int biXPelsPerMeter; int biYPelsPerMeter; int biClrUsed; int biClrImportant; */ if(demuxer->video->id != i && demuxer->video->id != -1) st->discard= AVDISCARD_ALL; else{ demuxer->video->id = i; demuxer->video->sh= demuxer->v_streams[i]; } break; } case CODEC_TYPE_SUBTITLE:{ sh_sub_t* sh_sub; if(priv->sub_streams >= MAX_S_STREAMS) break; /* only support text subtitles for now */ if(codec->codec_id != CODEC_ID_TEXT) break; sh_sub = new_sh_sub_sid(demuxer, i, priv->sub_streams); mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_SubtitleID, "lavf", priv->sub_streams); if(!sh_sub) break; priv->sstreams[priv->sub_streams] = i; sh_sub->type = 't'; demuxer->sub->sh = demuxer->s_streams[priv->sub_streams++]; break; } default: st->discard= AVDISCARD_ALL; } }
int read_asf_header(demuxer_t *demuxer,struct asf_priv* asf){ int hdr_len = asf->header.objh.size - sizeof(asf->header); int hdr_skip = 0; char *hdr = NULL; char guid_buffer[16]; int pos, start = stream_tell(demuxer->stream); uint32_t* streams = NULL; int audio_streams=0; int video_streams=0; uint16_t stream_count=0; int best_video = -1; int best_audio = -1; uint64_t data_len; ASF_stream_header_t *streamh; uint8_t *buffer; int audio_pos=0; if(hdr_len < 0) { mp_msg(MSGT_HEADER, MSGL_FATAL, "Header size is too small.\n"); return 0; } if (hdr_len > 1024 * 1024) { mp_msg(MSGT_HEADER, MSGL_ERR, MSGTR_MPDEMUX_ASFHDR_HeaderSizeOver1MB, hdr_len); hdr_skip = hdr_len - 1024 * 1024; hdr_len = 1024 * 1024; } hdr = malloc(hdr_len); if (!hdr) { mp_msg(MSGT_HEADER, MSGL_FATAL, MSGTR_MPDEMUX_ASFHDR_HeaderMallocFailed, hdr_len); return 0; } stream_read(demuxer->stream, hdr, hdr_len); if (hdr_skip) stream_skip(demuxer->stream, hdr_skip); if (stream_eof(demuxer->stream)) { mp_msg(MSGT_HEADER, MSGL_FATAL, MSGTR_MPDEMUX_ASFHDR_EOFWhileReadingHeader); goto err_out; } if (is_drm(hdr, hdr_len)) mp_msg(MSGT_HEADER, MSGL_FATAL, MSGTR_MPDEMUX_ASFHDR_DRMProtected); if ((pos = find_asf_guid(hdr, asf_ext_stream_audio, 0, hdr_len)) >= 0) { // Special case: found GUID for dvr-ms audio. // Now skip back to associated stream header. int sh_pos=0; sh_pos = find_backwards_asf_guid(hdr, asf_stream_header_guid, pos); if (sh_pos > 0) { sh_audio_t *sh_audio; mp_msg(MSGT_HEADER, MSGL_V, "read_asf_header found dvr-ms audio stream header pos=%d\n", sh_pos); // found audio stream header - following code reads header and // initializes audio stream. audio_pos = pos - 16 - 8; streamh = (ASF_stream_header_t *)&hdr[sh_pos]; le2me_ASF_stream_header_t(streamh); audio_pos += 64; //16+16+4+4+4+16+4; buffer = &hdr[audio_pos]; sh_audio=new_sh_audio(demuxer,streamh->stream_no & 0x7F, NULL); sh_audio->needs_parsing = 1; mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "asfheader", streamh->stream_no & 0x7F); ++audio_streams; if (!asf_init_audio_stream(demuxer, asf, sh_audio, streamh, &audio_pos, &buffer, hdr, hdr_len)) goto len_err_out; if (!get_ext_stream_properties(hdr, hdr_len, streamh->stream_no, asf, 0)) goto len_err_out; } } // find stream headers // only reset pos if we didnt find dvr_ms audio stream // if we did find it then we want to avoid reading its header twice if (audio_pos == 0) pos = 0; while ((pos = find_asf_guid(hdr, asf_stream_header_guid, pos, hdr_len)) >= 0) { streamh = (ASF_stream_header_t *)&hdr[pos]; pos += sizeof(ASF_stream_header_t); if (pos > hdr_len) goto len_err_out; le2me_ASF_stream_header_t(streamh); mp_msg(MSGT_HEADER, MSGL_V, "stream type: %s\n", asf_chunk_type(streamh->type)); mp_msg(MSGT_HEADER, MSGL_V, "stream concealment: %s\n", asf_chunk_type(streamh->concealment)); mp_msg(MSGT_HEADER, MSGL_V, "type: %d bytes, stream: %d bytes ID: %d\n", (int)streamh->type_size, (int)streamh->stream_size, (int)streamh->stream_no); mp_msg(MSGT_HEADER, MSGL_V, "unk1: %lX unk2: %X\n", (unsigned long)streamh->unk1, (unsigned int)streamh->unk2); mp_msg(MSGT_HEADER, MSGL_V, "FILEPOS=0x%X\n", pos + start); // type-specific data: buffer = &hdr[pos]; pos += streamh->type_size; if (pos > hdr_len) goto len_err_out; switch(ASF_LOAD_GUID_PREFIX(streamh->type)){ case ASF_GUID_PREFIX_audio_stream: { sh_audio_t* sh_audio=new_sh_audio(demuxer,streamh->stream_no & 0x7F, NULL); mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "asfheader", streamh->stream_no & 0x7F); ++audio_streams; if (!asf_init_audio_stream(demuxer, asf, sh_audio, streamh, &pos, &buffer, hdr, hdr_len)) goto len_err_out; //if(demuxer->audio->id==-1) demuxer->audio->id=streamh.stream_no & 0x7F; break; } case ASF_GUID_PREFIX_video_stream: { unsigned int len; float asp_ratio; sh_video_t* sh_video=new_sh_video(demuxer,streamh->stream_no & 0x7F); mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_VideoID, "asfheader", streamh->stream_no & 0x7F); len=streamh->type_size-(4+4+1+2); ++video_streams; // sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize); sh_video->bih=calloc((len<sizeof(*sh_video->bih))?sizeof(*sh_video->bih):len,1); memcpy(sh_video->bih,&buffer[4+4+1+2],len); le2me_BITMAPINFOHEADER(sh_video->bih); if (sh_video->bih->biSize > len && sh_video->bih->biSize > sizeof(*sh_video->bih)) sh_video->bih->biSize = len; if (sh_video->bih->biCompression == mmioFOURCC('D', 'V', 'R', ' ')) { //mp_msg(MSGT_DEMUXER, MSGL_WARN, MSGTR_MPDEMUX_ASFHDR_DVRWantsLibavformat); //sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale; //sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate; asf->asf_frame_state=-1; asf->asf_frame_start_found=0; asf->asf_is_dvr_ms=1; asf->dvr_last_vid_pts=0.0; } else asf->asf_is_dvr_ms=0; if (!get_ext_stream_properties(hdr, hdr_len, streamh->stream_no, asf, 1)) goto len_err_out; if (get_meta(hdr, hdr_len, streamh->stream_no, &asp_ratio)) { sh_video->aspect = asp_ratio * sh_video->bih->biWidth / sh_video->bih->biHeight; } sh_video->i_bps = asf->bps; if( mp_msg_test(MSGT_DEMUX,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V); //asf_video_id=streamh.stream_no & 0x7F; //if(demuxer->video->id==-1) demuxer->video->id=streamh.stream_no & 0x7F; break; } } // stream-specific data: // stream_read(demuxer->stream,(char*) buffer,streamh.stream_size); } // find file header pos = find_asf_guid(hdr, asf_file_header_guid, 0, hdr_len); if (pos >= 0) { ASF_file_header_t *fileh = (ASF_file_header_t *)&hdr[pos]; pos += sizeof(ASF_file_header_t); if (pos > hdr_len) goto len_err_out; le2me_ASF_file_header_t(fileh); mp_msg(MSGT_HEADER, MSGL_V, "ASF: packets: %d flags: %d " "max_packet_size: %d min_packet_size: %d max_bitrate: %d " "preroll: %d\n", (int)fileh->num_packets, (int)fileh->flags, (int)fileh->min_packet_size, (int)fileh->max_packet_size, (int)fileh->max_bitrate, (int)fileh->preroll); asf->packetsize=fileh->max_packet_size; asf->packet=malloc(asf->packetsize); // !!! asf->packetrate=fileh->max_bitrate/8.0/(double)asf->packetsize; asf->movielength=(fileh->play_duration-10000*fileh->preroll)/10000000.0; } // find content header pos = find_asf_guid(hdr, asf_content_desc_guid, 0, hdr_len); if (pos >= 0) { ASF_content_description_t *contenth = (ASF_content_description_t *)&hdr[pos]; char *string=NULL; uint16_t* wstring = NULL; uint16_t len; pos += sizeof(ASF_content_description_t); if (pos > hdr_len) goto len_err_out; le2me_ASF_content_description_t(contenth); mp_msg(MSGT_HEADER,MSGL_V,"\n"); // extract the title if((len = contenth->title_size) != 0) { wstring = (uint16_t*)&hdr[pos]; pos += len; if (pos > hdr_len) goto len_err_out; if ((string = get_ucs2str(wstring, len))) { mp_msg(MSGT_HEADER,MSGL_V," Title: %s\n", string); demux_info_add(demuxer, "title", string); free(string); } } // extract the author if((len = contenth->author_size) != 0) { wstring = (uint16_t*)&hdr[pos]; pos += len; if (pos > hdr_len) goto len_err_out; if ((string = get_ucs2str(wstring, len))) { mp_msg(MSGT_HEADER,MSGL_V," Author: %s\n", string); demux_info_add(demuxer, "author", string); free(string); } } // extract the copyright if((len = contenth->copyright_size) != 0) { wstring = (uint16_t*)&hdr[pos]; pos += len; if (pos > hdr_len) goto len_err_out; if ((string = get_ucs2str(wstring, len))) { mp_msg(MSGT_HEADER,MSGL_V," Copyright: %s\n", string); demux_info_add(demuxer, "copyright", string); free(string); } } // extract the comment if((len = contenth->comment_size) != 0) { wstring = (uint16_t*)&hdr[pos]; pos += len; if (pos > hdr_len) goto len_err_out; if ((string = get_ucs2str(wstring, len))) { mp_msg(MSGT_HEADER,MSGL_V," Comment: %s\n", string); demux_info_add(demuxer, "comments", string); free(string); } } // extract the rating if((len = contenth->rating_size) != 0) { wstring = (uint16_t*)&hdr[pos]; pos += len; if (pos > hdr_len) goto len_err_out; if ((string = get_ucs2str(wstring, len))) { mp_msg(MSGT_HEADER,MSGL_V," Rating: %s\n", string); free(string); } } mp_msg(MSGT_HEADER,MSGL_V,"\n"); } // find content header pos = find_asf_guid(hdr, asf_stream_group_guid, 0, hdr_len); if (pos >= 0) { int max_streams = (hdr_len - pos - 2) / 6; uint16_t stream_id, i; uint32_t max_bitrate; char *ptr = &hdr[pos]; mp_msg(MSGT_HEADER,MSGL_V,"============ ASF Stream group == START ===\n"); if(max_streams <= 0) goto len_err_out; stream_count = AV_RL16(ptr); ptr += sizeof(uint16_t); if(stream_count > max_streams) stream_count = max_streams; if(stream_count > 0) streams = malloc(2*stream_count*sizeof(uint32_t)); mp_msg(MSGT_HEADER,MSGL_V," stream count=[0x%x][%u]\n", stream_count, stream_count ); for( i=0 ; i<stream_count ; i++ ) { stream_id = AV_RL16(ptr); ptr += sizeof(uint16_t); max_bitrate = AV_RL32(ptr); ptr += sizeof(uint32_t); mp_msg(MSGT_HEADER,MSGL_V," stream id=[0x%x][%u]\n", stream_id, stream_id ); mp_msg(MSGT_HEADER,MSGL_V," max bitrate=[0x%x][%u]\n", max_bitrate, max_bitrate ); streams[2*i] = stream_id; streams[2*i+1] = max_bitrate; } mp_msg(MSGT_HEADER,MSGL_V,"============ ASF Stream group == END ===\n"); } free(hdr); hdr = NULL; start = stream_tell(demuxer->stream); // start of first data chunk stream_read(demuxer->stream, guid_buffer, 16); if (memcmp(guid_buffer, asf_data_chunk_guid, 16) != 0) { mp_msg(MSGT_HEADER, MSGL_FATAL, MSGTR_MPDEMUX_ASFHDR_NoDataChunkAfterHeader); free(streams); streams = NULL; return 0; } // read length of chunk data_len = stream_read_qword_le(demuxer->stream); demuxer->movi_start = stream_tell(demuxer->stream) + 26; demuxer->movi_end = start + data_len; mp_msg(MSGT_HEADER, MSGL_V, "Found movie at 0x%X - 0x%X\n", (int)demuxer->movi_start, (int)demuxer->movi_end); if(streams) { // stream selection is done in the network code, it shouldn't be done here // as the servers often do not care about what we requested. #if 0 uint32_t vr = 0, ar = 0,i; #ifdef CONFIG_NETWORKING if( demuxer->stream->streaming_ctrl!=NULL ) { if( demuxer->stream->streaming_ctrl->bandwidth!=0 && demuxer->stream->streaming_ctrl->data!=NULL ) { best_audio = ((asf_http_streaming_ctrl_t*)demuxer->stream->streaming_ctrl->data)->audio_id; best_video = ((asf_http_streaming_ctrl_t*)demuxer->stream->streaming_ctrl->data)->video_id; } } else #endif for(i = 0; i < stream_count; i++) { uint32_t id = streams[2*i]; uint32_t rate = streams[2*i+1]; if(demuxer->v_streams[id] && rate > vr) { vr = rate; best_video = id; } else if(demuxer->a_streams[id] && rate > ar) { ar = rate; best_audio = id; } } #endif free(streams); streams = NULL; } mp_msg(MSGT_HEADER,MSGL_V,"ASF: %d audio and %d video streams found\n",audio_streams,video_streams); if(!audio_streams) demuxer->audio->id=-2; // nosound else if(best_audio > 0 && demuxer->audio->id == -1) demuxer->audio->id=best_audio; if(!video_streams){ if(!audio_streams){ mp_msg(MSGT_HEADER,MSGL_ERR,MSGTR_MPDEMUX_ASFHDR_AudioVideoHeaderNotFound); return 0; } demuxer->video->id=-2; // audio-only } else if (best_video > 0 && demuxer->video->id == -1) demuxer->video->id = best_video; #if 0 if( mp_msg_test(MSGT_HEADER,MSGL_V) ){ printf("ASF duration: %d\n",(int)fileh.duration); printf("ASF start pts: %d\n",(int)fileh.start_timestamp); printf("ASF end pts: %d\n",(int)fileh.end_timestamp); } #endif return 1; len_err_out: mp_msg(MSGT_HEADER, MSGL_FATAL, MSGTR_MPDEMUX_ASFHDR_InvalidLengthInASFHeader); err_out: if (hdr) free(hdr); if (streams) free(streams); return 0; }
static demuxer_t* demux_open_mf(demuxer_t* demuxer) { sh_video_t *sh_video = NULL; mf_t *mf = NULL; int i; if(!demuxer->stream->url) return NULL; if(strncmp(demuxer->stream->url, "mf://", 5)) return NULL; mf=open_mf(demuxer->stream->url + 5); if(!mf) return NULL; if(!mf_type) { char* p=strrchr(mf->names[0],'.'); if(!p) { mp_msg(MSGT_DEMUX, MSGL_INFO, "[demux_mf] file type was not set! (try -mf type=xxx)\n" ); free( mf ); return NULL; } mf_type=strdup(p+1); mp_msg(MSGT_DEMUX, MSGL_INFO, "[demux_mf] file type was not set! trying 'type=%s'...\n", mf_type); } demuxer->filepos=mf->curr_frame=0; demuxer->movi_start = 0; demuxer->movi_end = mf->nr_of_files - 1; // create a new video stream header sh_video = new_sh_video(demuxer, 0); // make sure the demuxer knows about the new video stream header // (even though new_sh_video() ought to take care of it) demuxer->video->sh = sh_video; // make sure that the video demuxer stream header knows about its // parent video demuxer stream (this is getting wacky), or else // video_read_properties() will choke sh_video->ds = demuxer->video; for (i = 0; type2format[i].type; i++) if (strcasecmp(mf_type, type2format[i].type) == 0) break; if (!type2format[i].type) { mp_msg(MSGT_DEMUX, MSGL_INFO, "[demux_mf] unknown input file type.\n" ); free(mf); return NULL; } sh_video->format = type2format[i].format; sh_video->disp_w = mf_w; sh_video->disp_h = mf_h; sh_video->fps = mf_fps; sh_video->frametime = 1 / sh_video->fps; // emulate BITMAPINFOHEADER: sh_video->bih=malloc(sizeof(BITMAPINFOHEADER)); memset(sh_video->bih,0,sizeof(BITMAPINFOHEADER)); sh_video->bih->biSize=40; sh_video->bih->biWidth = mf_w; sh_video->bih->biHeight = mf_h; sh_video->bih->biPlanes=1; sh_video->bih->biBitCount=24; sh_video->bih->biCompression=sh_video->format; sh_video->bih->biSizeImage=sh_video->bih->biWidth*sh_video->bih->biHeight*3; /* disable seeking */ // demuxer->seekable = 0; demuxer->priv=(void*)mf; return demuxer; }
static demuxer_t* demux_open_lavf(demuxer_t *demuxer){ AVFormatContext *avfc; AVFormatParameters ap; AVOption *opt; lavf_priv_t *priv= demuxer->priv; int i,g; char mp_filename[256]="mp:"; memset(&ap, 0, sizeof(AVFormatParameters)); stream_seek(demuxer->stream, 0); register_protocol(&mp_protocol); avfc = av_alloc_format_context(); if (correct_pts) avfc->flags |= AVFMT_FLAG_GENPTS; if (index_mode == 0) avfc->flags |= AVFMT_FLAG_IGNIDX; ap.prealloced_context = 1; if(opt_probesize) { double d = (double) opt_probesize; opt = av_set_double(avfc, "probesize", opt_probesize); if(!opt) mp_msg(MSGT_HEADER,MSGL_ERR, "demux_lavf, couldn't set option probesize to %.3f\r\n", d); } if(demuxer->stream->url) strncpy(mp_filename + 3, demuxer->stream->url, sizeof(mp_filename)-3); else strncpy(mp_filename + 3, "foobar.dummy", sizeof(mp_filename)-3); url_fopen(&priv->pb, mp_filename, URL_RDONLY); ((URLContext*)(priv->pb.opaque))->priv_data= demuxer->stream; if(av_open_input_stream(&avfc, &priv->pb, mp_filename, priv->avif, &ap)<0){ mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF_header: av_open_input_stream() failed\n"); return NULL; } priv->avfc= avfc; if(av_find_stream_info(avfc) < 0){ mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF_header: av_find_stream_info() failed\n"); return NULL; } if(avfc->title [0]) demux_info_add(demuxer, "name" , avfc->title ); if(avfc->author [0]) demux_info_add(demuxer, "author" , avfc->author ); if(avfc->copyright[0]) demux_info_add(demuxer, "copyright", avfc->copyright); if(avfc->comment [0]) demux_info_add(demuxer, "comments" , avfc->comment ); if(avfc->album [0]) demux_info_add(demuxer, "album" , avfc->album ); // if(avfc->year ) demux_info_add(demuxer, "year" , avfc->year ); // if(avfc->track ) demux_info_add(demuxer, "track" , avfc->track ); if(avfc->genre [0]) demux_info_add(demuxer, "genre" , avfc->genre ); for(i=0; i<avfc->nb_streams; i++){ AVStream *st= avfc->streams[i]; AVCodecContext *codec= st->codec; switch(codec->codec_type){ case CODEC_TYPE_AUDIO:{ WAVEFORMATEX *wf= calloc(sizeof(WAVEFORMATEX) + codec->extradata_size, 1); sh_audio_t* sh_audio; if(priv->audio_streams >= MAX_A_STREAMS) break; sh_audio=new_sh_audio(demuxer, i); if(!sh_audio) break; priv->astreams[priv->audio_streams] = i; priv->audio_streams++; if(!codec->codec_tag) codec->codec_tag= av_codec_get_tag(mp_wav_taglists, codec->codec_id); wf->wFormatTag= codec->codec_tag; wf->nChannels= codec->channels; wf->nSamplesPerSec= codec->sample_rate; wf->nAvgBytesPerSec= codec->bit_rate/8; wf->nBlockAlign= codec->block_align ? codec->block_align : 1; wf->wBitsPerSample= codec->bits_per_sample; wf->cbSize= codec->extradata_size; if(codec->extradata_size){ memcpy( wf + 1, codec->extradata, codec->extradata_size); } sh_audio->wf= wf; sh_audio->audio.dwSampleSize= codec->block_align; if(codec->frame_size && codec->sample_rate){ sh_audio->audio.dwScale=codec->frame_size; sh_audio->audio.dwRate= codec->sample_rate; }else{ sh_audio->audio.dwScale= codec->block_align ? codec->block_align*8 : 8; sh_audio->audio.dwRate = codec->bit_rate; } g= ff_gcd(sh_audio->audio.dwScale, sh_audio->audio.dwRate); sh_audio->audio.dwScale /= g; sh_audio->audio.dwRate /= g; // printf("sca:%d rat:%d fs:%d sr:%d ba:%d\n", sh_audio->audio.dwScale, sh_audio->audio.dwRate, codec->frame_size, codec->sample_rate, codec->block_align); sh_audio->ds= demuxer->audio; sh_audio->format= codec->codec_tag; sh_audio->channels= codec->channels; sh_audio->samplerate= codec->sample_rate; sh_audio->i_bps= codec->bit_rate/8; switch (codec->codec_id) { case CODEC_ID_PCM_S8: case CODEC_ID_PCM_U8: sh_audio->samplesize = 1; break; case CODEC_ID_PCM_S16LE: case CODEC_ID_PCM_S16BE: case CODEC_ID_PCM_U16LE: case CODEC_ID_PCM_U16BE: sh_audio->samplesize = 2; break; case CODEC_ID_PCM_ALAW: sh_audio->format = 0x6; break; case CODEC_ID_PCM_MULAW: sh_audio->format = 0x7; break; } if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf, MSGL_V); if((audio_lang && st->language[0] && !strncmp(audio_lang, st->language, 3)) || (demuxer->audio->id == i || demuxer->audio->id == -1) ) { demuxer->audio->id = i; demuxer->audio->sh= demuxer->a_streams[i]; } else st->discard= AVDISCARD_ALL; break;} case CODEC_TYPE_VIDEO:{ sh_video_t* sh_video; BITMAPINFOHEADER *bih; if(priv->video_streams >= MAX_V_STREAMS) break; sh_video=new_sh_video(demuxer, i); if(!sh_video) break; priv->vstreams[priv->video_streams] = i; priv->video_streams++; bih=calloc(sizeof(BITMAPINFOHEADER) + codec->extradata_size,1); if(!codec->codec_tag) codec->codec_tag= av_codec_get_tag(mp_bmp_taglists, codec->codec_id); bih->biSize= sizeof(BITMAPINFOHEADER) + codec->extradata_size; bih->biWidth= codec->width; bih->biHeight= codec->height; bih->biBitCount= codec->bits_per_sample; bih->biSizeImage = bih->biWidth * bih->biHeight * bih->biBitCount/8; bih->biCompression= codec->codec_tag; sh_video->bih= bih; sh_video->disp_w= codec->width; sh_video->disp_h= codec->height; if (st->time_base.den) { /* if container has time_base, use that */ sh_video->video.dwRate= st->time_base.den; sh_video->video.dwScale= st->time_base.num; } else { sh_video->video.dwRate= codec->time_base.den; sh_video->video.dwScale= codec->time_base.num; } sh_video->fps=av_q2d(st->r_frame_rate); sh_video->frametime=1/av_q2d(st->r_frame_rate); sh_video->format = bih->biCompression; sh_video->aspect= codec->width * codec->sample_aspect_ratio.num / (float)(codec->height * codec->sample_aspect_ratio.den); sh_video->i_bps= codec->bit_rate/8; mp_msg(MSGT_DEMUX,MSGL_DBG2,"aspect= %d*%d/(%d*%d)\n", codec->width, codec->sample_aspect_ratio.num, codec->height, codec->sample_aspect_ratio.den); sh_video->ds= demuxer->video; if(codec->extradata_size) memcpy(sh_video->bih + 1, codec->extradata, codec->extradata_size); if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V); /* short biPlanes; int biXPelsPerMeter; int biYPelsPerMeter; int biClrUsed; int biClrImportant;*/ if(demuxer->video->id != i && demuxer->video->id != -1) st->discard= AVDISCARD_ALL; else{ demuxer->video->id = i; demuxer->video->sh= demuxer->v_streams[i]; } break;} default: st->discard= AVDISCARD_ALL; } } mp_msg(MSGT_HEADER,MSGL_V,"LAVF: %d audio and %d video streams found\n",priv->audio_streams,priv->video_streams); mp_msg(MSGT_HEADER,MSGL_V,"LAVF: build %d\n", LIBAVFORMAT_BUILD); if(!priv->audio_streams) demuxer->audio->id=-2; // nosound // else if(best_audio > 0 && demuxer->audio->id == -1) demuxer->audio->id=best_audio; if(!priv->video_streams){ if(!priv->audio_streams){ mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF: no audio or video headers found - broken file?\n"); return NULL; } demuxer->video->id=-2; // audio-only } //else if (best_video > 0 && demuxer->video->id == -1) demuxer->video->id = best_video; return demuxer; }
static demuxer_t* demux_open_y4m(demuxer_t* demuxer){ y4m_priv_t* priv = demuxer->priv; y4m_ratio_t ratio; sh_video_t* sh=new_sh_video(demuxer,0); int err; priv->framenum = 0; priv->si = malloc(sizeof(y4m_stream_info_t)); if (priv->is_older) { char buf[4]; int frame_rate_code; stream_skip(demuxer->stream, 8); /* YUV4MPEG */ stream_skip(demuxer->stream, 1); /* space */ stream_read(demuxer->stream, (char *)&buf[0], 3); buf[3] = 0; sh->disp_w = atoi(buf); stream_skip(demuxer->stream, 1); /* space */ stream_read(demuxer->stream, (char *)&buf[0], 3); buf[3] = 0; sh->disp_h = atoi(buf); stream_skip(demuxer->stream, 1); /* space */ stream_read(demuxer->stream, (char *)&buf[0], 1); buf[1] = 0; frame_rate_code = atoi(buf); stream_skip(demuxer->stream, 1); /* new-line */ if (!sh->fps) { /* values from xawtv */ switch(frame_rate_code) { case 1: sh->fps = 23.976f; break; case 2: sh->fps = 24.0f; break; case 3: sh->fps = 25.0f; break; case 4: sh->fps = 29.97f; break; case 5: sh->fps = 30.0f; break; case 6: sh->fps = 50.0f; break; case 7: sh->fps = 59.94f; break; case 8: sh->fps = 60.0f; break; default: sh->fps = 25.0f; } } sh->frametime = 1.0f/sh->fps; } else { y4m_init_stream_info(priv->si); if ((err=y4m_read_stream_header(demuxer->stream, priv->si)) != Y4M_OK) mp_msg(MSGT_DEMUXER, MSGL_FATAL, "error parsing YUV4MPEG header: %s\n", y4m_strerr(err)); if(!sh->fps) { ratio = y4m_si_get_framerate(priv->si); if (ratio.d != 0) sh->fps=(float)ratio.n/(float)ratio.d; else sh->fps=15.0f; } sh->frametime=1.0f/sh->fps; ratio = y4m_si_get_sampleaspect(priv->si); sh->disp_w = y4m_si_get_width(priv->si); sh->disp_h = y4m_si_get_height(priv->si); if (ratio.d != 0 && ratio.n != 0) sh->aspect = (float)(sh->disp_w*ratio.n)/(float)(sh->disp_h*ratio.d); demuxer->seekable = 0; } sh->format = mmioFOURCC('Y', 'V', '1', '2'); sh->bih=malloc(sizeof(BITMAPINFOHEADER)); memset(sh->bih,0,sizeof(BITMAPINFOHEADER)); sh->bih->biSize=40; sh->bih->biWidth = sh->disp_w; sh->bih->biHeight = sh->disp_h; sh->bih->biPlanes=3; sh->bih->biBitCount=12; sh->bih->biCompression=sh->format; sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight*3/2; /* YV12 */ demuxer->video->sh=sh; sh->ds=demuxer->video; demuxer->video->id=0; mp_msg(MSGT_DEMUX, MSGL_INFO, "YUV4MPEG2 Video stream %d size: display: %dx%d, codec: %ux%u\n", demuxer->video->id, sh->disp_w, sh->disp_h, sh->bih->biWidth, sh->bih->biHeight); return demuxer; }
static demuxer_t* demux_dshow_open (demuxer_t *demuxer) { sh_video_t *sh_video; sh_audio_t *sh_audio; stream_pos = 0; last_vpts = 0; b_stopped = 0; b_vfinished = 0; b_afinished = 0; b_firstframe = 1; b_firstaframe = 1; g_vpkg.pData = NULL; g_apkg.pData = NULL; apkg_buf = NULL; apkg_buf_size = 0; if(AudioInfo.demuxer) demux_info_add(demuxer, "DShow Demuxer", AudioInfo.demuxer); if(VideoInfo.haveVideo) { if (VideoInfo.avgtimeperframe < 10000) VideoInfo.avgtimeperframe = 400000; sh_video = new_sh_video(demuxer, 0); if (demuxer->video->id == -1) demuxer->video->id = 0; if (demuxer->video->id == 0) demuxer->video->sh = sh_video; sh_video->ds = demuxer->video; sh_video->disp_w = VideoInfo.width; sh_video->disp_h = VideoInfo.height; sh_video->format = mmioFOURCC('Y', 'V', '1', '2'); sh_video->frametime = (float)(VideoInfo.avgtimeperframe/1E7); sh_video->fps = 1.0 / sh_video->frametime; sh_video->bih = calloc (1, sizeof (BITMAPINFOHEADER)); sh_video->bih->biSize = sizeof (BITMAPINFOHEADER); sh_video->bih->biWidth = VideoInfo.width; sh_video->bih->biHeight = VideoInfo.height; sh_video->bih->biBitCount = 12; sh_video->bih->biSizeImage = sh_video->bih->biWidth * sh_video->bih->biHeight * sh_video->bih->biBitCount/8; sh_video->bih->biCompression = sh_video->format; if(VideoInfo.videoDecoder) demux_info_add(demuxer, "DShow Video", VideoInfo.videoDecoder); if(VideoInfo.aspectX > 1 && VideoInfo.aspectY > 1) sh_video->aspect = (float)VideoInfo.width*(float)VideoInfo.aspectX/((float)VideoInfo.height*(float)VideoInfo.aspectY); } if(AudioInfo.haveAudio) { sh_audio = new_sh_audio_aid(demuxer, 0, 0, NULL); demuxer->audio->id = 0; demuxer->audio->sh = sh_audio; sh_audio->ds = demuxer->audio; sh_audio->wf = malloc (sizeof (WAVEFORMATEX)); memset(sh_audio->wf, 0, sizeof (WAVEFORMATEX)); if(AudioInfo.audioDecoder) { if(AudioInfo.wFormatTag == 0xfffe && !strcmp(AudioInfo.audioDecoder, "Microsoft DTV-DVD Audio Decoder")) AudioInfo.wFormatTag = 0x3; demux_info_add(demuxer, "DShow Audio", AudioInfo.audioDecoder); } sh_audio->format = sh_audio->wf->wFormatTag = AudioInfo.wFormatTag; sh_audio->channels = sh_audio->wf->nChannels = AudioInfo.nChannels; sh_audio->samplerate = sh_audio->wf->nSamplesPerSec = AudioInfo.nSamplesPerSec; sh_audio->wf->wBitsPerSample = AudioInfo.wBitsPerSample; sh_audio->wf->nBlockAlign = sh_audio->channels * sh_audio->wf->wBitsPerSample / 8; sh_audio->wf->nAvgBytesPerSec = sh_audio->wf->nBlockAlign * sh_audio->samplerate; sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec; } duration = GetGraphDuration(g_pdgi); hWaitVSend = CreateEventA(NULL, FALSE, FALSE, NULL); hWaitASend = CreateEventA(NULL, FALSE, FALSE, NULL); hWaitVDec = CreateEventA(NULL, FALSE, FALSE, NULL); hWaitADec = CreateEventA(NULL, FALSE, FALSE, NULL); StartGraph(g_pdgi); return demuxer; }
// return value: // 0 = EOF or no stream found // 1 = successfully read a packet static int demux_lmlm4_fill_buffer(demuxer_t *demux, demux_stream_t *ds) { FrameInfo frameInfo; double pts; int id=1; int ret; //hdr: demux->filepos = stream_tell(demux->stream); mp_msg(MSGT_DEMUX, MSGL_DBG2, "fpos = %"PRId64"\n", (int64_t)demux->filepos); ret=getFrame(demux, &frameInfo); if(ret<=0) return ret; // EOF/error pts=demux->video->sh ? frames*((sh_video_t*)(demux->video->sh))->frametime : 0; switch(frameInfo.frameType) { case FRAMETYPE_AUDIO_MPEG1L2: mp_dbg(MSGT_DEMUX, MSGL_DBG2, "Audio Packet\n"); if (!video) { stream_skip(demux->stream, frameInfo.frameSize + frameInfo.paddingSize); mp_msg(MSGT_DEMUX, MSGL_V, "Skip Audio Packet\n"); return -1; //goto hdr; } if(demux->audio->id==-1) { if(!demux->a_streams[id]) new_sh_audio(demux,id, NULL); demux->audio->id=id; demux->audio->sh=demux->a_streams[id]; ((sh_audio_t*)(demux->audio->sh))->format=0x50; // mpeg audio layer 1/2 } if(demux->audio->id==id) ds_read_packet(demux->audio, demux->stream, frameInfo.frameSize, pts, demux->filepos, 0); else stream_skip(demux->stream,frameInfo.frameSize); break; case FRAMETYPE_I: if (!video) { video = 1; mp_dbg(MSGT_DEMUX, MSGL_DBG2, "First Video Packet\n"); } case FRAMETYPE_P: frames=(frames+1)&(1024*1024-1); // wrap around at 4 hrs to avoid inaccurate float calculations if (!video) { stream_skip(demux->stream, frameInfo.frameSize + frameInfo.paddingSize); mp_msg(MSGT_DEMUX, MSGL_V, "Skip Video P Packet\n"); return -1; //goto hdr; } mp_dbg(MSGT_DEMUX, MSGL_DBG2, "Video Packet\n"); if(demux->video->id==-1) { if(!demux->v_streams[id]) new_sh_video(demux,id); demux->video->id=id; demux->video->sh=demux->v_streams[id]; ((sh_video_t*)(demux->video->sh))->format=0x10000004; // mpeg4-ES } if(demux->video->id==id) ds_read_packet(demux->video, demux->stream, frameInfo.frameSize, pts, demux->filepos, 0); break; default: stream_skip(demux->stream,frameInfo.frameSize); } stream_skip(demux->stream, frameInfo.paddingSize); return 1; }
static demuxer_t* demux_open_smjpeg(demuxer_t* demuxer){ sh_video_t* sh_video; sh_audio_t* sh_audio; unsigned int htype = 0, hleng; int i = 0; /* file header */ stream_skip(demuxer->stream, 8); /* \x00\x0aSMJPEG */ stream_skip(demuxer->stream, 4); mp_msg(MSGT_DEMUX, MSGL_INFO, "This clip is %d seconds\n", stream_read_dword(demuxer->stream)); /* stream header */ while (i < 3) { i++; htype = stream_read_dword_le(demuxer->stream); if (htype == mmioFOURCC('H','E','N','D')) break; hleng = (stream_read_word(demuxer->stream)<<16)|stream_read_word(demuxer->stream); switch(htype) { case mmioFOURCC('_','V','I','D'): sh_video = new_sh_video(demuxer, 0); demuxer->video->sh = sh_video; sh_video->ds = demuxer->video; sh_video->bih = malloc(sizeof(BITMAPINFOHEADER)); memset(sh_video->bih, 0, sizeof(BITMAPINFOHEADER)); stream_skip(demuxer->stream, 4); /* number of frames */ // sh_video->fps = 24; // sh_video->frametime = 1.0f/sh_video->fps; sh_video->disp_w = stream_read_word(demuxer->stream); sh_video->disp_h = stream_read_word(demuxer->stream); sh_video->format = stream_read_dword_le(demuxer->stream); /* these are false values */ sh_video->bih->biSize = 40; sh_video->bih->biWidth = sh_video->disp_w; sh_video->bih->biHeight = sh_video->disp_h; sh_video->bih->biPlanes = 3; sh_video->bih->biBitCount = 12; sh_video->bih->biCompression = sh_video->format; sh_video->bih->biSizeImage = sh_video->disp_w*sh_video->disp_h; break; case mmioFOURCC('_','S','N','D'): sh_audio = new_sh_audio(demuxer, 0); demuxer->audio->sh = sh_audio; sh_audio->ds = demuxer->audio; sh_audio->wf = malloc(sizeof(WAVEFORMATEX)); memset(sh_audio->wf, 0, sizeof(WAVEFORMATEX)); sh_audio->samplerate = stream_read_word(demuxer->stream); sh_audio->wf->wBitsPerSample = stream_read_char(demuxer->stream); sh_audio->channels = stream_read_char(demuxer->stream); sh_audio->format = stream_read_dword_le(demuxer->stream); sh_audio->wf->wFormatTag = sh_audio->format; sh_audio->wf->nChannels = sh_audio->channels; sh_audio->wf->nSamplesPerSec = sh_audio->samplerate; sh_audio->wf->nAvgBytesPerSec = sh_audio->wf->nChannels* sh_audio->wf->wBitsPerSample*sh_audio->wf->nSamplesPerSec/8; sh_audio->wf->nBlockAlign = sh_audio->channels *2; sh_audio->wf->cbSize = 0; break; case mmioFOURCC('_','T','X','T'): stream_skip(demuxer->stream, stream_read_dword(demuxer->stream)); break; } } demuxer->seekable = 0; return demuxer; }
static demuxer_t* demux_open_lmlm4(demuxer_t* demuxer) { sh_audio_t *sh_audio=NULL; sh_video_t *sh_video=NULL; #if 0 sh_video_t* sh_video; sh_audio_t* sh_audio; unsigned int htype = 0, hleng; int i = 0; sh_video = new_sh_video(demuxer, 0); demuxer->video->sh = sh_video; sh_video->ds = demuxer->video; sh_video->disp_w = 640; sh_video->disp_h = 480; sh_video->format = mmioFOURCC('D','I','V','X'); sh_video->bih = calloc(1, sizeof(*sh_video->bih)); /* these are false values */ sh_video->bih->biSize = 40; sh_video->bih->biWidth = sh_video->disp_w; sh_video->bih->biHeight = sh_video->disp_h; sh_video->bih->biPlanes = 3; sh_video->bih->biBitCount = 16; sh_video->bih->biCompression = sh_video->format; sh_video->bih->biSizeImage = sh_video->disp_w*sh_video->disp_h; sh_audio = new_sh_audio(demuxer, 0, NULL); demuxer->audio->sh = sh_audio; sh_audio->ds = demuxer->audio; sh_audio->wf = calloc(1, sizeof(*sh_audio->wf)); sh_audio->samplerate = 48000; sh_audio->wf->wBitsPerSample = 16; sh_audio->channels = 2; sh_audio->format = 0x50; sh_audio->wf->wFormatTag = sh_audio->format; sh_audio->wf->nChannels = sh_audio->channels; sh_audio->wf->nSamplesPerSec = sh_audio->samplerate; sh_audio->wf->nAvgBytesPerSec = sh_audio->wf->nChannels* sh_audio->wf->wBitsPerSample*sh_audio->wf->nSamplesPerSec/8; sh_audio->wf->nBlockAlign = sh_audio->channels *2; sh_audio->wf->cbSize = 0; #endif demuxer->seekable = 0; if(!ds_fill_buffer(demuxer->video)) { mp_msg(MSGT_DEMUXER,MSGL_INFO,"LMLM4: " MSGTR_MissingVideoStream); demuxer->video->sh=NULL; } else { sh_video=demuxer->video->sh; sh_video->ds=demuxer->video; } if(demuxer->audio->id!=-2) { if(!ds_fill_buffer(demuxer->audio)) { mp_msg(MSGT_DEMUXER,MSGL_INFO,"LMLM4: " MSGTR_MissingAudioStream); demuxer->audio->sh=NULL; } else { sh_audio=demuxer->audio->sh; sh_audio->ds=demuxer->audio; } } return demuxer; }
void read_avi_header(demuxer_t *demuxer,int index_mode){ sh_audio_t *sh_audio=NULL; sh_video_t *sh_video=NULL; int stream_id=-1; int idxfix_videostream=0; int idxfix_divx=0; avi_priv_t* priv=demuxer->priv; off_t list_end=0; //---- AVI header: priv->idx_size=0; priv->audio_streams=0; while(1){ int id=stream_read_dword_le(demuxer->stream); unsigned chunksize,size2; static int last_fccType=0; static int last_fccHandler=0; char* hdr=NULL; // if(stream_eof(demuxer->stream)) break; // Imply -forceidx if -saveidx is specified if (index_file_save) index_mode = 2; // if(id==mmioFOURCC('L','I','S','T')){ unsigned len=stream_read_dword_le(demuxer->stream); // list size id=stream_read_dword_le(demuxer->stream); // list type mp_msg(MSGT_HEADER,MSGL_DBG2,"LIST %.4s len=%u\n",(char *) &id,len); if(len >= 4) { len -= 4; list_end=stream_tell(demuxer->stream)+((len+1)&(~1)); } else { mp_msg(MSGT_HEADER,MSGL_WARN,MSGTR_MPDEMUX_AVIHDR_EmptyList); list_end = 0; } mp_msg(MSGT_HEADER,MSGL_V,"list_end=0x%X\n",(int)list_end); if(id==listtypeAVIMOVIE){ // found MOVI header if(!demuxer->movi_start) demuxer->movi_start=stream_tell(demuxer->stream); demuxer->movi_end=stream_tell(demuxer->stream)+len; mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_FoundMovieAt,(int)demuxer->movi_start,(int)demuxer->movi_end); if(demuxer->stream->end_pos>demuxer->movi_end) demuxer->movi_end=demuxer->stream->end_pos; if(index_mode==-2 || index_mode==2 || index_mode==0) break; // reading from non-seekable source (stdin) or forced index or no index forced if(list_end>0) stream_seek(demuxer->stream,list_end); // skip movi list_end=0; } continue; } size2=stream_read_dword_le(demuxer->stream); mp_msg(MSGT_HEADER,MSGL_DBG2,"CHUNK %.4s len=%u\n",(char *) &id,size2); chunksize=(size2+1)&(~1); switch(id){ // Indicates where the subject of the file is archived case mmioFOURCC('I','A','R','L'): hdr="Archival Location";break; // Lists the artist of the original subject of the file; // for example, "Michaelangelo." case mmioFOURCC('I','A','R','T'): hdr="Artist";break; // Lists the name of the person or organization that commissioned // the subject of the file; for example "Pope Julian II." case mmioFOURCC('I','C','M','S'): hdr="Commissioned";break; // Provides general comments about the file or the subject // of the file. If the comment is several sentences long, end each // sentence with a period. Do not include new-line characters. case mmioFOURCC('I','C','M','T'): hdr="Comments";break; // Records the copyright information for the file; for example, // "Copyright Encyclopedia International 1991." If there are multiple // copyrights, separate them by semicolon followed by a space. case mmioFOURCC('I','C','O','P'): hdr="Copyright";break; // Describes whether an image has been cropped and, if so, how it // was cropped; for example, "lower-right corner." case mmioFOURCC('I','C','R','D'): hdr="Creation Date";break; // Describes whether an image has been cropped and, if so, how it // was cropped; for example, "lower-right corner." case mmioFOURCC('I','C','R','P'): hdr="Cropped";break; // Specifies the size of the original subject of the file; for // example, "8.5 in h, 11 in w." case mmioFOURCC('I','D','I','M'): hdr="Dimensions";break; // Stores dots per inch setting of the digitizer used to // produce the file, such as "300." case mmioFOURCC('I','D','P','I'): hdr="Dots Per Inch";break; // Stores the of the engineer who worked on the file. If there are // multiple engineers, separate the names by a semicolon and a blank; // for example, "Smith, John; Adams, Joe." case mmioFOURCC('I','E','N','G'): hdr="Engineer";break; // Describes the original work, such as "landscape,", "portrait," // "still liefe," etc. case mmioFOURCC('I','G','N','R'): hdr="Genre";break; // Provides a list of keywords that refer to the file or subject of the // file. Separate multiple keywords with a semicolon and a blank; // for example, "Seattle, aerial view; scenery." case mmioFOURCC('I','K','E','Y'): hdr="Keywords";break; // ILGT - Describes the changes in the lightness settings on the digitizer // required to produce the file. Note that the format of this information // depends on the hardware used. case mmioFOURCC('I','L','G','T'): hdr="Lightness";break; // IMED - Decribes the original subject of the file, such as // "computer image," "drawing," "lithograph," and so on. case mmioFOURCC('I','M','E','D'): hdr="Medium";break; // INAM - Stores the title of the subject of the file, such as // "Seattle from Above." case mmioFOURCC('I','N','A','M'): hdr="Title";break; // IPLT - Specifies the number of colors requested when digitizing // an image, such as "256." case mmioFOURCC('I','P','L','T'): hdr="Palette Setting";break; // IPRD - Specifies the name of title the file was originally intended // for, such as "Encyclopedia of Pacific Northwest Geography." case mmioFOURCC('I','P','R','D'): hdr="Product";break; // ISBJ - Decsribes the contents of the file, such as // "Aerial view of Seattle." case mmioFOURCC('I','S','B','J'): hdr="Subject";break; // ISFT - Identifies the name of the software packages used to create the // file, such as "Microsoft WaveEdit" case mmioFOURCC('I','S','F','T'): hdr="Software";break; // ISHP - Identifies the change in sharpness for the digitizer // required to produce the file (the format depends on the hardware used). case mmioFOURCC('I','S','H','P'): hdr="Sharpness";break; // ISRC - Identifies the name of the person or organization who // suplied the original subject of the file; for example, "Try Research." case mmioFOURCC('I','S','R','C'): hdr="Source";break; // ISRF - Identifies the original form of the material that was digitized, // such as "slide," "paper," "map," and so on. This is not necessarily // the same as IMED case mmioFOURCC('I','S','R','F'): hdr="Source Form";break; // ITCH - Identifies the technician who digitized the subject file; // for example, "Smith, John." case mmioFOURCC('I','T','C','H'): hdr="Technician";break; case mmioFOURCC('I','S','M','P'): hdr="Time Code";break; case mmioFOURCC('I','D','I','T'): hdr="Digitization Time";break; case ckidAVIMAINHDR: // read 'avih' stream_read(demuxer->stream,(char*) &avih,FFMIN(size2,sizeof(avih))); le2me_MainAVIHeader(&avih); // swap to machine endian chunksize-=FFMIN(size2,sizeof(avih)); if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_avih(&avih,MSGL_V); // else print_avih_flags(&avih,MSGL_V); break; case ckidSTREAMHEADER: { // read 'strh' AVIStreamHeader h; stream_read(demuxer->stream,(char*) &h,FFMIN(size2,sizeof(h))); le2me_AVIStreamHeader(&h); // swap to machine endian chunksize-=FFMIN(size2,sizeof(h)); ++stream_id; if(h.fccType==streamtypeVIDEO){ sh_video=new_sh_video(demuxer,stream_id); mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_VideoID, "aviheader", stream_id); memcpy(&sh_video->video,&h,sizeof(h)); sh_video->stream_delay = (float)sh_video->video.dwStart * sh_video->video.dwScale/sh_video->video.dwRate; } else if(h.fccType==streamtypeAUDIO){ sh_audio=new_sh_audio(demuxer,stream_id); mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "aviheader", stream_id); memcpy(&sh_audio->audio,&h,sizeof(h)); sh_audio->stream_delay = (float)sh_audio->audio.dwStart * sh_audio->audio.dwScale/sh_audio->audio.dwRate; } last_fccType=h.fccType; last_fccHandler=h.fccHandler; if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_strh(&h,MSGL_V); break; } case mmioFOURCC('i', 'n', 'd', 'x'): { uint32_t i; avisuperindex_chunk *s; if(!index_mode) break; if(chunksize<=24){ break; } priv->suidx_size++; priv->suidx = realloc_struct(priv->suidx, priv->suidx_size, sizeof (avisuperindex_chunk)); s = &priv->suidx[priv->suidx_size-1]; chunksize-=24; memcpy(s->fcc, "indx", 4); s->dwSize = size2; s->wLongsPerEntry = stream_read_word_le(demuxer->stream); s->bIndexSubType = stream_read_char(demuxer->stream); s->bIndexType = stream_read_char(demuxer->stream); s->nEntriesInUse = stream_read_dword_le(demuxer->stream); *(uint32_t *)s->dwChunkId = stream_read_dword_le(demuxer->stream); stream_read(demuxer->stream, (char *)s->dwReserved, 3*4); memset(s->dwReserved, 0, 3*4); print_avisuperindex_chunk(s,MSGL_V); // Check and fix this useless crap if(s->wLongsPerEntry != sizeof (avisuperindex_entry)/4) { mp_msg (MSGT_HEADER, MSGL_WARN, "Broken super index chunk size: %u\n",s->wLongsPerEntry); s->wLongsPerEntry = sizeof(avisuperindex_entry)/4; } if( ((chunksize/4)/s->wLongsPerEntry) < s->nEntriesInUse){ mp_msg (MSGT_HEADER, MSGL_WARN, "Broken super index chunk\n"); s->nEntriesInUse = (chunksize/4)/s->wLongsPerEntry; } s->aIndex = calloc(s->nEntriesInUse, sizeof (avisuperindex_entry)); s->stdidx = calloc(s->nEntriesInUse, sizeof (avistdindex_chunk)); // now the real index of indices for (i=0; i<s->nEntriesInUse; i++) { chunksize-=16; s->aIndex[i].qwOffset = stream_read_qword_le(demuxer->stream); s->aIndex[i].dwSize = stream_read_dword_le(demuxer->stream); s->aIndex[i].dwDuration = stream_read_dword_le(demuxer->stream); mp_msg (MSGT_HEADER, MSGL_V, "ODML (%.4s): [%d] 0x%016"PRIx64" 0x%04x %u\n", (s->dwChunkId), i, (uint64_t)s->aIndex[i].qwOffset, s->aIndex[i].dwSize, s->aIndex[i].dwDuration); } break; } case ckidSTREAMFORMAT: { // read 'strf' if(last_fccType==streamtypeVIDEO){ sh_video->bih=calloc(FFMAX(chunksize, sizeof(BITMAPINFOHEADER)), 1); // sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize); mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_FoundBitmapInfoHeader,chunksize,sizeof(BITMAPINFOHEADER)); stream_read(demuxer->stream,(char*) sh_video->bih,chunksize); le2me_BITMAPINFOHEADER(sh_video->bih); // swap to machine endian if (sh_video->bih->biSize > chunksize && sh_video->bih->biSize > sizeof(BITMAPINFOHEADER)) sh_video->bih->biSize = chunksize; // fixup MS-RLE header (seems to be broken for <256 color files) if(sh_video->bih->biCompression<=1 && sh_video->bih->biSize==40) sh_video->bih->biSize=chunksize; if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_video->bih,MSGL_V); chunksize=0; sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale; sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate; sh_video->format = sh_video->bih->biCompression; // if(demuxer->video->id==-1) demuxer->video->id=stream_id; // IdxFix: idxfix_videostream=stream_id; switch(sh_video->bih->biCompression){ case mmioFOURCC('M', 'P', 'G', '4'): case mmioFOURCC('m', 'p', 'g', '4'): case mmioFOURCC('D', 'I', 'V', '1'): idxfix_divx=3; // set index recovery mpeg4 flavour: msmpeg4v1 mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_RegeneratingKeyfTableForMPG4V1); break; case mmioFOURCC('D', 'I', 'V', '3'): case mmioFOURCC('d', 'i', 'v', '3'): case mmioFOURCC('D', 'I', 'V', '4'): case mmioFOURCC('d', 'i', 'v', '4'): case mmioFOURCC('D', 'I', 'V', '5'): case mmioFOURCC('d', 'i', 'v', '5'): case mmioFOURCC('D', 'I', 'V', '6'): case mmioFOURCC('d', 'i', 'v', '6'): case mmioFOURCC('M', 'P', '4', '3'): case mmioFOURCC('m', 'p', '4', '3'): case mmioFOURCC('M', 'P', '4', '2'): case mmioFOURCC('m', 'p', '4', '2'): case mmioFOURCC('D', 'I', 'V', '2'): case mmioFOURCC('A', 'P', '4', '1'): idxfix_divx=1; // set index recovery mpeg4 flavour: msmpeg4v3 mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_RegeneratingKeyfTableForDIVX3); break; case mmioFOURCC('D', 'I', 'V', 'X'): case mmioFOURCC('d', 'i', 'v', 'x'): case mmioFOURCC('D', 'X', '5', '0'): case mmioFOURCC('X', 'V', 'I', 'D'): case mmioFOURCC('x', 'v', 'i', 'd'): case mmioFOURCC('F', 'M', 'P', '4'): case mmioFOURCC('f', 'm', 'p', '4'): idxfix_divx=2; // set index recovery mpeg4 flavour: generic mpeg4 mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_RegeneratingKeyfTableForMPEG4); break; } } else if(last_fccType==streamtypeAUDIO){ unsigned wf_size = chunksize<sizeof(WAVEFORMATEX)?sizeof(WAVEFORMATEX):chunksize; sh_audio->wf=calloc(wf_size,1); // sh_audio->wf=malloc(chunksize); memset(sh_audio->wf,0,chunksize); mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_FoundWaveFmt,chunksize,sizeof(WAVEFORMATEX)); stream_read(demuxer->stream,(char*) sh_audio->wf,chunksize); le2me_WAVEFORMATEX(sh_audio->wf); if (sh_audio->wf->cbSize != 0 && wf_size < sizeof(WAVEFORMATEX)+sh_audio->wf->cbSize) { sh_audio->wf=realloc(sh_audio->wf, sizeof(WAVEFORMATEX)+sh_audio->wf->cbSize); } sh_audio->format=sh_audio->wf->wFormatTag; if (sh_audio->format == 1 && last_fccHandler == mmioFOURCC('A', 'x', 'a', 'n')) sh_audio->format = last_fccHandler; sh_audio->i_bps=sh_audio->wf->nAvgBytesPerSec; chunksize=0; if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf,MSGL_V); ++priv->audio_streams; // if(demuxer->audio->id==-1) demuxer->audio->id=stream_id; } break; } case mmioFOURCC('v', 'p', 'r', 'p'): { VideoPropHeader *vprp = malloc(chunksize); unsigned int i; stream_read(demuxer->stream, (void*)vprp, chunksize); le2me_VideoPropHeader(vprp); chunksize -= sizeof(*vprp)-sizeof(vprp->FieldInfo); chunksize /= sizeof(VIDEO_FIELD_DESC); if (vprp->nbFieldPerFrame > chunksize) { vprp->nbFieldPerFrame = chunksize; } chunksize = 0; for (i=0; i<vprp->nbFieldPerFrame; i++) { le2me_VIDEO_FIELD_DESC(&vprp->FieldInfo[i]); } if (sh_video) { sh_video->aspect = GET_AVI_ASPECT(vprp->dwFrameAspectRatio); } if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_vprp(vprp,MSGL_V); free(vprp); break; } case mmioFOURCC('d', 'm', 'l', 'h'): { // dmlh 00 00 00 04 frms unsigned int total_frames = stream_read_dword_le(demuxer->stream); mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_FoundAVIV2Header, chunksize, total_frames); stream_skip(demuxer->stream, chunksize-4); chunksize = 0; } break; case ckidAVINEWINDEX: if(demuxer->movi_end>stream_tell(demuxer->stream)) demuxer->movi_end=stream_tell(demuxer->stream); // fixup movi-end if(index_mode && !priv->isodml){ int i; priv->idx_size=size2>>4; mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_ReadingIndexBlockChunksForFrames, priv->idx_size,avih.dwTotalFrames, (int64_t)stream_tell(demuxer->stream)); priv->idx=malloc(priv->idx_size<<4); // printf("\nindex to %p !!!!! (priv=%p)\n",priv->idx,priv); stream_read(demuxer->stream,(char*)priv->idx,priv->idx_size<<4); for (i = 0; i < priv->idx_size; i++) { // swap index to machine endian AVIINDEXENTRY *entry=(AVIINDEXENTRY*)priv->idx + i; le2me_AVIINDEXENTRY(entry); /* * We (ab)use the upper word for bits 32-47 of the offset, so * we'll clear them here. * FIXME: AFAIK no codec uses them, but if one does it will break */ entry->dwFlags&=0xffff; } chunksize-=priv->idx_size<<4; if( mp_msg_test(MSGT_HEADER,MSGL_DBG2) ) print_index(priv->idx,priv->idx_size,MSGL_DBG2); } break; /* added May 2002 */ case mmioFOURCC('R','I','F','F'): { char riff_type[4]; mp_msg(MSGT_HEADER, MSGL_V, MSGTR_MPDEMUX_AVIHDR_AdditionalRIFFHdr); stream_read(demuxer->stream, riff_type, sizeof riff_type); if (strncmp(riff_type, "AVIX", sizeof riff_type)) mp_msg(MSGT_HEADER, MSGL_WARN, MSGTR_MPDEMUX_AVIHDR_WarnNotExtendedAVIHdr); else { /* * We got an extended AVI header, so we need to switch to * ODML to get seeking to work, provided we got indx chunks * in the header (suidx_size > 0). */ if (priv->suidx_size > 0) priv->isodml = 1; } chunksize = 0; list_end = 0; /* a new list will follow */ break; } case ckidAVIPADDING: stream_skip(demuxer->stream, chunksize); chunksize = 0; break; } if(hdr){ mp_msg(MSGT_HEADER,MSGL_V,"hdr=%s size=%u\n",hdr,size2); if(size2==3) chunksize=1; // empty else { char buf[256]; int len=(size2<250)?size2:250; stream_read(demuxer->stream,buf,len); chunksize-=len; buf[len]=0; mp_msg(MSGT_HEADER,MSGL_V,"%-10s: %s\n",hdr,buf); demux_info_add(demuxer, hdr, buf); } } mp_msg(MSGT_HEADER,MSGL_DBG2,"list_end=0x%"PRIX64" pos=0x%"PRIX64" chunksize=0x%"PRIX64" next=0x%"PRIX64"\n", (int64_t)list_end, (int64_t)stream_tell(demuxer->stream), (int64_t)chunksize, (int64_t)chunksize+(int64_t)stream_tell(demuxer->stream)); if(list_end>0 && chunksize+stream_tell(demuxer->stream) == list_end) list_end=0; if(list_end>0 && chunksize+stream_tell(demuxer->stream)>list_end){ mp_msg(MSGT_HEADER,MSGL_V,MSGTR_MPDEMUX_AVIHDR_BrokenChunk,chunksize,(char *) &id); stream_seek(demuxer->stream,list_end); list_end=0; } else if(chunksize>0) stream_skip(demuxer->stream,chunksize); else if((int)chunksize<0) mp_msg(MSGT_HEADER,MSGL_WARN,"chunksize=%u (id=%.4s)\n",chunksize,(char *) &id); }
static demuxer_t* demux_open_roq(demuxer_t* demuxer) { sh_video_t *sh_video = NULL; sh_audio_t *sh_audio = NULL; roq_data_t *roq_data = malloc(sizeof(roq_data_t)); int chunk_id; int chunk_size; int chunk_arg; int last_chunk_id = 0; int largest_audio_chunk = 0; int fps; roq_data->total_chunks = 0; roq_data->current_chunk = 0; roq_data->total_video_chunks = 0; roq_data->chunks = NULL; // position the stream and start traversing stream_seek(demuxer->stream, 6); fps = stream_read_word_le(demuxer->stream); while (!stream_eof(demuxer->stream)) { chunk_id = stream_read_word_le(demuxer->stream); chunk_size = stream_read_dword_le(demuxer->stream); chunk_arg = stream_read_word_le(demuxer->stream); // this is the only useful header info in the file if (chunk_id == RoQ_INFO) { // there should only be one RoQ_INFO chunk per file if (sh_video) { mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Found more than one RoQ_INFO chunk\n"); stream_skip(demuxer->stream, 8); } else { // this is a good opportunity to create a video stream header sh_video = new_sh_video(demuxer, 0); // make sure the demuxer knows about the new stream header demuxer->video->sh = sh_video; // make sure that the video demuxer stream header knows about its // parent video demuxer stream sh_video->ds = demuxer->video; sh_video->disp_w = stream_read_word_le(demuxer->stream); sh_video->disp_h = stream_read_word_le(demuxer->stream); stream_skip(demuxer->stream, 4); // custom fourcc for internal MPlayer use sh_video->format = mmioFOURCC('R', 'o', 'Q', 'V'); // constant frame rate sh_video->fps = fps; sh_video->frametime = 1 / sh_video->fps; } } else if ((chunk_id == RoQ_SOUND_MONO) || (chunk_id == RoQ_SOUND_STEREO)) { // create the audio stream header if it hasn't been created it if (sh_audio == NULL) { // make the header first sh_audio = new_sh_audio(demuxer, 0); // make sure the demuxer knows about the new stream header demuxer->audio->id = 0; demuxer->audio->sh = sh_audio; // make sure that the audio demuxer stream header knows about its // parent audio demuxer stream sh_audio->ds = demuxer->audio; // go through the bother of making a WAVEFORMATEX structure sh_audio->wf = malloc(sizeof(*sh_audio->wf)); // custom fourcc for internal MPlayer use sh_audio->format = mmioFOURCC('R', 'o', 'Q', 'A'); if (chunk_id == RoQ_SOUND_STEREO) sh_audio->wf->nChannels = 2; else sh_audio->wf->nChannels = 1; // always 22KHz, 16-bit sh_audio->wf->nSamplesPerSec = 22050; sh_audio->wf->wBitsPerSample = 16; } // index the chunk roq_data->chunks = realloc(roq_data->chunks, (roq_data->total_chunks + 1) * sizeof (roq_chunk_t)); roq_data->chunks[roq_data->total_chunks].chunk_type = CHUNK_TYPE_AUDIO; roq_data->chunks[roq_data->total_chunks].chunk_offset = stream_tell(demuxer->stream) - 8; roq_data->chunks[roq_data->total_chunks].chunk_size = chunk_size + 8; roq_data->chunks[roq_data->total_chunks].running_audio_sample_count = roq_data->total_audio_sample_count; // audio housekeeping if (chunk_size > largest_audio_chunk) largest_audio_chunk = chunk_size; roq_data->total_audio_sample_count += (chunk_size / sh_audio->wf->nChannels); stream_skip(demuxer->stream, chunk_size); roq_data->total_chunks++; } else if ((chunk_id == RoQ_QUAD_CODEBOOK) || ((chunk_id == RoQ_QUAD_VQ) && (last_chunk_id != RoQ_QUAD_CODEBOOK))) { // index a new chunk if it's a codebook or quad VQ not following a // codebook roq_data->chunks = realloc(roq_data->chunks, (roq_data->total_chunks + 1) * sizeof (roq_chunk_t)); roq_data->chunks[roq_data->total_chunks].chunk_type = CHUNK_TYPE_VIDEO; roq_data->chunks[roq_data->total_chunks].chunk_offset = stream_tell(demuxer->stream) - 8; roq_data->chunks[roq_data->total_chunks].chunk_size = chunk_size + 8; roq_data->chunks[roq_data->total_chunks].video_chunk_number = roq_data->total_video_chunks++; stream_skip(demuxer->stream, chunk_size); roq_data->total_chunks++; } else if ((chunk_id == RoQ_QUAD_VQ) && (last_chunk_id == RoQ_QUAD_CODEBOOK)) { // if it's a quad VQ chunk following a codebook chunk, extend the last // chunk roq_data->chunks[roq_data->total_chunks - 1].chunk_size += (chunk_size + 8); stream_skip(demuxer->stream, chunk_size); } else if (!stream_eof(demuxer->stream)) { mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Unknown RoQ chunk ID: %04X\n", chunk_id); } last_chunk_id = chunk_id; } // minimum output buffer size = largest audio chunk * 2, since each byte // in the DPCM encoding effectively represents 1 16-bit sample // (store it in wf->nBlockAlign for the time being since init_audio() will // step on it anyway) if (sh_audio) sh_audio->wf->nBlockAlign = largest_audio_chunk * 2; roq_data->current_chunk = 0; demuxer->priv = roq_data; stream_reset(demuxer->stream); return demuxer; }
static demuxer_t * demux_open_pva (demuxer_t * demuxer) { sh_video_t *sh_video = new_sh_video(demuxer,0); sh_audio_t *sh_audio = new_sh_audio(demuxer,0, NULL); pva_priv_t * priv; stream_reset(demuxer->stream); stream_seek(demuxer->stream,0); priv=malloc(sizeof(pva_priv_t)); if(demuxer->stream->type!=STREAMTYPE_FILE) demuxer->seekable=0; else demuxer->seekable=1; demuxer->priv=priv; memset(demuxer->priv,0,sizeof(pva_priv_t)); if(!pva_sync(demuxer)) { mp_msg(MSGT_DEMUX,MSGL_ERR,"Not a PVA file.\n"); return NULL; } //printf("priv->just_synced %s after initial sync!\n",priv->just_synced?"set":"UNSET"); demuxer->video->sh=sh_video; //printf("demuxer->stream->end_pos= %d\n",demuxer->stream->end_pos); mp_msg(MSGT_DEMUXER,MSGL_INFO,"Opened PVA demuxer...\n"); /* * Audio and Video codecs: * the PVA spec only allows MPEG2 video and MPEG layer II audio. No need to check the formats then. * Moreover, there would be no way to do that since the PVA stream format has no fields to describe * the used codecs. */ sh_video->format=0x10000002; sh_video->ds=demuxer->video; /* printf("demuxer->video->id==%d\n",demuxer->video->id); printf("demuxer->audio->id==%d\n",demuxer->audio->id); */ demuxer->audio->id = 0; demuxer->audio->sh=sh_audio; sh_audio->format=0x50; sh_audio->ds=demuxer->audio; demuxer->movi_start=0; demuxer->movi_end=demuxer->stream->end_pos; priv->last_video_pts=-1; priv->last_audio_pts=-1; return demuxer; }
static demuxer_t* demux_open_vivo(demuxer_t* demuxer){ vivo_priv_t* priv=demuxer->priv; if(!ds_fill_buffer(demuxer->video)){ mp_msg(MSGT_DEMUX,MSGL_ERR,"VIVO: " MSGTR_MissingVideoStreamBug); return NULL; } audio_pos=0; h263_decode_picture_header(demuxer->video->buffer); if (vivo_param_version != -1) priv->version = '0' + vivo_param_version; { sh_video_t* sh=new_sh_video(demuxer,0); /* viv1, viv2 (for better codecs.conf) */ sh->format = mmioFOURCC('v', 'i', 'v', priv->version); if(!sh->fps) { if (priv->fps) sh->fps=priv->fps; else sh->fps=15.0f; } sh->frametime=1.0f/sh->fps; /* XXX: FIXME: can't scale image. */ /* hotfix to disable: */ priv->disp_width = priv->width; priv->disp_height = priv->height; if (vivo_param_width != -1) priv->disp_width = priv->width = vivo_param_width; if (vivo_param_height != -1) priv->disp_height = priv->height = vivo_param_height; if (vivo_param_vformat != -1) { priv->disp_width = priv->width = h263_format[vivo_param_vformat][0]; priv->disp_height = priv->height = h263_format[vivo_param_vformat][1]; } if (priv->disp_width) sh->disp_w = priv->disp_width; else sh->disp_w = width; if (priv->disp_height) sh->disp_h = priv->disp_height; else sh->disp_h = height; // emulate BITMAPINFOHEADER: sh->bih=malloc(sizeof(BITMAPINFOHEADER)); memset(sh->bih,0,sizeof(BITMAPINFOHEADER)); sh->bih->biSize=40; if (priv->width) sh->bih->biWidth = priv->width; else sh->bih->biWidth = width; if (priv->height) sh->bih->biHeight = priv->height; else sh->bih->biHeight = height; sh->bih->biPlanes=1; sh->bih->biBitCount=24; sh->bih->biCompression=sh->format; sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight*3; /* insert as stream */ demuxer->video->sh=sh; sh->ds=demuxer->video; demuxer->video->id=0; /* disable seeking */ demuxer->seekable = 0; mp_msg(MSGT_DEMUX,MSGL_V,"VIVO Video stream %d size: display: %dx%d, codec: %ux%u\n", demuxer->video->id, sh->disp_w, sh->disp_h, sh->bih->biWidth, sh->bih->biHeight); } /* AUDIO init */ if (demuxer->audio->id >= -1){ if(!ds_fill_buffer(demuxer->audio)){ mp_msg(MSGT_DEMUX,MSGL_ERR,"VIVO: " MSGTR_MissingAudioStream); } else { sh_audio_t* sh=new_sh_audio(demuxer,1); /* Select audio codec */ if (priv->audio_codec == 0) { if (priv->version == '2') priv->audio_codec = VIVO_AUDIO_SIREN; else priv->audio_codec = VIVO_AUDIO_G723; } if (vivo_param_acodec != NULL) { if (!strcasecmp(vivo_param_acodec, "g723")) priv->audio_codec = VIVO_AUDIO_G723; if (!strcasecmp(vivo_param_acodec, "siren")) priv->audio_codec = VIVO_AUDIO_SIREN; } if (priv->audio_codec == VIVO_AUDIO_G723) sh->format = 0x111; else if (priv->audio_codec == VIVO_AUDIO_SIREN) sh->format = 0x112; else { mp_msg(MSGT_DEMUX, MSGL_ERR, "VIVO: Not support audio codec (%d)\n", priv->audio_codec); free_sh_audio(demuxer, 1); goto nosound; } // Emulate WAVEFORMATEX struct: sh->wf=malloc(sizeof(WAVEFORMATEX)); memset(sh->wf,0,sizeof(WAVEFORMATEX)); sh->wf->wFormatTag=sh->format; sh->wf->nChannels=1; /* 1 channels for both Siren and G.723 */ /* Set bits per sample */ if (priv->audio_codec == VIVO_AUDIO_SIREN) sh->wf->wBitsPerSample = 16; else if (priv->audio_codec == VIVO_AUDIO_G723) sh->wf->wBitsPerSample = 8; /* Set sampling rate */ if (priv->audio_samplerate) /* got from header */ sh->wf->nSamplesPerSec = priv->audio_samplerate; else { if (priv->audio_codec == VIVO_AUDIO_SIREN) sh->wf->nSamplesPerSec = 16000; if (priv->audio_codec == VIVO_AUDIO_G723) sh->wf->nSamplesPerSec = 8000; } if (vivo_param_samplerate != -1) sh->wf->nSamplesPerSec = vivo_param_samplerate; /* Set audio bitrate */ if (priv->audio_bitrate) /* got from header */ sh->wf->nAvgBytesPerSec = priv->audio_bitrate; else { if (priv->audio_codec == VIVO_AUDIO_SIREN) sh->wf->nAvgBytesPerSec = 2000; if (priv->audio_codec == VIVO_AUDIO_G723) sh->wf->nAvgBytesPerSec = 800; } if (vivo_param_abitrate != -1) sh->wf->nAvgBytesPerSec = vivo_param_abitrate; audio_rate=sh->wf->nAvgBytesPerSec; if (!priv->audio_bytesperblock) { if (priv->audio_codec == VIVO_AUDIO_SIREN) sh->wf->nBlockAlign = 40; if (priv->audio_codec == VIVO_AUDIO_G723) sh->wf->nBlockAlign = 24; } else sh->wf->nBlockAlign = priv->audio_bytesperblock; if (vivo_param_bytesperblock != -1) sh->wf->nBlockAlign = vivo_param_bytesperblock; /*sound_ok:*/ /* insert as stream */ demuxer->audio->sh=sh; sh->ds=demuxer->audio; demuxer->audio->id=1; nosound: return demuxer; } } return demuxer; }
static int demux_ty_fill_buffer( demuxer_t *demux, demux_stream_t *dsds ) { int invalidType = 0; int errorHeader = 0; int recordsDecoded = 0; int readSize; int numberRecs; unsigned char *recPtr; int offset; int counter; int aid; TiVoInfo *tivo = demux->priv; unsigned char *chunk = tivo->chunk; if ( demux->stream->type == STREAMTYPE_DVD ) return 0; mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:ty processing\n" ); if( demux->stream->eof ) return 0; // ====================================================================== // If we haven't figured out the size of the stream, let's do so // ====================================================================== if ( demux->stream->type == STREAMTYPE_VSTREAM ) { // The vstream code figures out the exact size of the stream demux->movi_start = 0; demux->movi_end = demux->stream->end_pos; tivo->size = demux->stream->end_pos; } else { // If its a local file, try to find the Part Headers, so we can // calculate the ACTUAL stream size // If we can't find it, go off with the file size and hope the // extract program did the "right thing" if ( tivo->readHeader == 0 ) { loff_t filePos; tivo->readHeader = 1; filePos = demux->filepos; stream_seek( demux->stream, 0 ); readSize = stream_read( demux->stream, chunk, CHUNKSIZE ); if ( memcmp( chunk, TMF_SIG, sizeof( TMF_SIG ) ) == 0 ) { mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Detected a tmf\n" ); tivo->tmf = 1; ty_tmf_filetoparts( demux, tivo ); readSize = tmf_load_chunk( demux, tivo, chunk, 0 ); } if ( readSize == CHUNKSIZE && AV_RB32(chunk) == TIVO_PES_FILEID ) { loff_t numberParts; readSize = 0; if ( tivo->tmf != 1 ) { loff_t offset; numberParts = demux->stream->end_pos / TIVO_PART_LENGTH; offset = numberParts * TIVO_PART_LENGTH; mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:ty/ty+Number Parts %"PRId64"\n", (int64_t)numberParts ); if ( offset + CHUNKSIZE < demux->stream->end_pos ) { stream_seek( demux->stream, offset ); readSize = stream_read( demux->stream, chunk, CHUNKSIZE ); } } else { numberParts = tivo->tmf_totalparts; offset = numberParts * TIVO_PART_LENGTH; readSize = tmf_load_chunk( demux, tivo, chunk, numberParts * ( TIVO_PART_LENGTH - CHUNKSIZE ) / CHUNKSIZE ); } if ( readSize == CHUNKSIZE && AV_RB32(chunk) == TIVO_PES_FILEID ) { int size = AV_RB24(chunk + 12); size -= 4; size *= CHUNKSIZE; tivo->size = numberParts * TIVO_PART_LENGTH; tivo->size += size; mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Header Calc Stream Size %"PRId64"\n", tivo->size ); } } if ( demux->stream->start_pos > 0 ) filePos = demux->stream->start_pos; stream_seek( demux->stream, filePos ); demux->filepos = stream_tell( demux->stream ); tivo->whichChunk = filePos / CHUNKSIZE; } demux->movi_start = 0; demux->movi_end = tivo->size; } // ====================================================================== // Give a clue as to where we are in the stream // ====================================================================== mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:ty header size %"PRIx64"\n", (int64_t)tivo->size ); mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:ty which Chunk %d\n", tivo->whichChunk ); mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:file end_pos %"PRIx64"\n", (int64_t)demux->stream->end_pos ); mp_msg( MSGT_DEMUX, MSGL_DBG3, "\nty:wanted current offset %"PRIx64"\n", (int64_t)stream_tell( demux->stream ) ); if ( tivo->size > 0 && stream_tell( demux->stream ) > tivo->size ) { demux->stream->eof = 1; return 0; } do { if ( tivo->tmf != 1 ) { // Make sure we are on a 128k boundary if ( demux->filepos % CHUNKSIZE != 0 ) { int whichChunk = demux->filepos / CHUNKSIZE; if ( demux->filepos % CHUNKSIZE > CHUNKSIZE / 2 ) whichChunk++; stream_seek( demux->stream, whichChunk * CHUNKSIZE ); } demux->filepos = stream_tell( demux->stream ); tivo->whichChunk = demux->filepos / CHUNKSIZE; readSize = stream_read( demux->stream, chunk, CHUNKSIZE ); if ( readSize != CHUNKSIZE ) return 0; } else { readSize = tmf_load_chunk( demux, tivo, chunk, tivo->whichChunk ); if ( readSize != CHUNKSIZE ) return 0; tivo->whichChunk++; } if (AV_RB32(chunk) == TIVO_PES_FILEID) mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Skipping PART Header\n" ); } while (AV_RB32(chunk) == TIVO_PES_FILEID); mp_msg( MSGT_DEMUX, MSGL_DBG3, "\nty:actual current offset %"PRIx64"\n", stream_tell( demux->stream ) - CHUNKSIZE ); // Let's make a Video Demux Stream for MPlayer aid = 0x0; if( !demux->v_streams[ aid ] ) new_sh_video( demux, aid ); if( demux->video->id == -1 ) demux->video->id = aid; if( demux->video->id == aid ) { demux_stream_t *ds = demux->video; if( !ds->sh ) ds->sh = demux->v_streams[ aid ]; } // ====================================================================== // Finally, we get to actually parse the chunk // ====================================================================== mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:ty parsing a chunk\n" ); numberRecs = chunk[ 0 ]; recPtr = &chunk[ 4 ]; offset = numberRecs * 16 + 4; for ( counter = 0 ; counter < numberRecs ; counter++ ) { int size = AV_RB24(recPtr) >> 4; int type = recPtr[ 3 ]; int nybbleType = recPtr[ 2 ] & 0x0f; recordsDecoded++; mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Record Type %x/%x %d\n", nybbleType, type, size ); // ================================================================ // Video Parsing // ================================================================ if ( type == 0xe0 ) { if ( size > 0 && size + offset <= CHUNKSIZE ) { int esOffset1 = demux_ty_FindESHeader( VIDEO_NAL, &chunk[ offset ], size); if ( esOffset1 != -1 ) tivo->lastVideoPTS = get_ty_pts( &chunk[ offset + esOffset1 + 9 ] ); // Do NOT Pass the PES Header onto the MPEG2 Decode if( nybbleType != 0x06 ) demux_ty_CopyToDemuxPacket( demux->video, &chunk[ offset ], size, demux->filepos + offset, tivo->lastVideoPTS ); offset += size; } else errorHeader++; } // ================================================================ // Audio Parsing // ================================================================ else if ( type == 0xc0 ) { if ( size > 0 && size + offset <= CHUNKSIZE ) { if( demux->audio->id == -1 ) { if ( nybbleType == 0x02 ) continue; // DTiVo inconclusive, wait for more else if ( nybbleType == 0x09 ) { mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Setting AC-3 Audio\n" ); aid = 0x80; // AC-3 } else { mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Setting MPEG Audio\n" ); aid = 0x0; // MPEG Audio } demux->audio->id = aid; if( !demux->a_streams[ aid ] ) new_sh_audio( demux, aid, NULL ); if( demux->audio->id == aid ) { demux_stream_t *ds = demux->audio; if( !ds->sh ) { sh_audio_t* sh_a; ds->sh = demux->a_streams[ aid ]; sh_a = (sh_audio_t*)ds->sh; switch(aid & 0xE0){ // 1110 0000 b (high 3 bit: type low 5: id) case 0x00: sh_a->format=0x50;break; // mpeg case 0xA0: sh_a->format=0x10001;break; // dvd pcm case 0x80: if((aid & 0xF8) == 0x88) sh_a->format=0x2001;//dts else sh_a->format=0x2000;break; // ac3 } } } } aid = demux->audio->id; // SA DTiVo Audio Data, no PES // ================================================ if ( nybbleType == 0x02 || nybbleType == 0x04 ) { if ( nybbleType == 0x02 && tivo->tivoType == 2 ) demux_ty_AddToAudioBuffer( tivo, &chunk[ offset ], size ); else { mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Adding Audio Packet Size %d\n", size ); demux_ty_CopyToDemuxPacket( demux->audio, &chunk[ offset ], size, ( demux->filepos + offset ), tivo->lastAudioPTS ); } } // 3 - MPEG Audio with PES Header, either SA or DTiVo // 9 - DTiVo AC3 Audio Data with PES Header // ================================================ if ( nybbleType == 0x03 || nybbleType == 0x09 ) { int esOffset1, esOffset2; if ( nybbleType == 0x03 ) esOffset1 = demux_ty_FindESHeader( AUDIO_NAL, &chunk[ offset ], size); // SA PES Header, No Audio Data // ================================================ if ( nybbleType == 0x03 && esOffset1 == 0 && size == 16 ) { tivo->tivoType = 1; tivo->lastAudioPTS = get_ty_pts( &chunk[ offset + SERIES2_PTS_OFFSET ] ); } else // DTiVo Audio with PES Header // ================================================ { tivo->tivoType = 2; demux_ty_AddToAudioBuffer( tivo, &chunk[ offset ], size ); demux_ty_FindESPacket( nybbleType == 9 ? AC3_NAL : AUDIO_NAL, tivo->lastAudio, tivo->lastAudioEnd, &esOffset1, &esOffset2 ); if ( esOffset1 != -1 && esOffset2 != -1 ) { int packetSize = esOffset2 - esOffset1; int headerSize; int ptsOffset; if ( IsValidAudioPacket( packetSize, &ptsOffset, &headerSize ) ) { mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:Adding DTiVo Audio Packet Size %d\n", packetSize ); tivo->lastAudioPTS = get_ty_pts( &tivo->lastAudio[ esOffset1 + ptsOffset ] ); if (nybbleType == 9) headerSize = 0; demux_ty_CopyToDemuxPacket ( demux->audio, &tivo->lastAudio[ esOffset1 + headerSize ], packetSize - headerSize, demux->filepos + offset, tivo->lastAudioPTS ); } // Collapse the Audio Buffer tivo->lastAudioEnd -= esOffset2; memmove( &tivo->lastAudio[ 0 ], &tivo->lastAudio[ esOffset2 ], tivo->lastAudioEnd ); } } } offset += size; } else errorHeader++; } // ================================================================ // 1 = Closed Caption // 2 = Extended Data Services // ================================================================ else if ( type == 0x01 || type == 0x02 ) { unsigned char lastXDS[ 16 ]; int b = AV_RB24(recPtr) >> 4; b &= 0x7f7f; mp_msg( MSGT_DEMUX, MSGL_DBG3, "ty:%s %04x\n", type == 1 ? "CC" : "XDS", b); lastXDS[ 0x00 ] = 0x00; lastXDS[ 0x01 ] = 0x00; lastXDS[ 0x02 ] = 0x01; lastXDS[ 0x03 ] = 0xb2; lastXDS[ 0x04 ] = 'T'; lastXDS[ 0x05 ] = 'Y'; lastXDS[ 0x06 ] = type; lastXDS[ 0x07 ] = b >> 8; lastXDS[ 0x08 ] = b; if ( subcc_enabled ) demux_ty_CopyToDemuxPacket( demux->video, lastXDS, 0x09, demux->filepos + offset, tivo->lastVideoPTS ); } // ================================================================ // Unknown // ================================================================ else { if ( size > 0 && size + offset <= CHUNKSIZE )