static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds){ lavf_priv_t *priv= demux->priv; AVPacket pkt; demux_packet_t *dp; demux_stream_t *ds; int id; mp_msg(MSGT_DEMUX,MSGL_DBG2,"demux_lavf_fill_buffer()\n"); demux->filepos=stream_tell(demux->stream); if(av_read_frame(priv->avfc, &pkt) < 0) return 0; // handle any new streams that might have been added for (id = priv->nb_streams_last; id < priv->avfc->nb_streams; id++) handle_stream(demux, priv->avfc, id); priv->nb_streams_last = priv->avfc->nb_streams; id= pkt.stream_index; if(id==demux->audio->id){ // audio ds=demux->audio; if(!ds->sh){ ds->sh=demux->a_streams[id]; mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected LAVF audio ID = %d\n",ds->id); } } else if(id==demux->video->id){ // video ds=demux->video; if(!ds->sh){ ds->sh=demux->v_streams[id]; mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected LAVF video ID = %d\n",ds->id); } } else if(id==demux->sub->id){ // subtitle ds=demux->sub; sub_utf8=1; } else { av_free_packet(&pkt); return 1; } if(pkt.destruct == av_destruct_packet && !CONFIG_MEMALIGN_HACK){ dp=new_demux_packet(0); dp->len=pkt.size; dp->buffer=pkt.data; pkt.destruct= NULL; }else{ dp=new_demux_packet(pkt.size); memcpy(dp->buffer, pkt.data, pkt.size); av_free_packet(&pkt); } if(pkt.pts != AV_NOPTS_VALUE){ dp->pts=pkt.pts * av_q2d(priv->avfc->streams[id]->time_base); priv->last_pts= dp->pts * AV_TIME_BASE; // always set endpts for subtitles, even if AV_PKT_FLAG_KEY is not set, // otherwise they will stay on screen to long if e.g. ASS is demuxed from mkv if((ds == demux->sub || (pkt.flags & AV_PKT_FLAG_KEY)) && pkt.convergence_duration > 0) dp->endpts = dp->pts + pkt.convergence_duration * av_q2d(priv->avfc->streams[id]->time_base); } dp->pos=demux->filepos; dp->flags= !!(pkt.flags&AV_PKT_FLAG_KEY); // append packet to DS stream: ds_add_packet(ds,dp); return 1; }
/** * \brief MPlayer callback: Fill buffer from MNG stream. * \param[in] demuxer demuxer structure * \param[in] ds demuxer stream * \return \p 1 on success, \p 0 on error */ static int demux_mng_fill_buffer(demuxer_t * demuxer, demux_stream_t * ds) { mng_priv_t * mng_priv = demuxer->priv; mng_handle h_mng = mng_priv->h_mng; mng_retcode mng_ret; demux_packet_t * dp; // exit if animation is finished if (mng_priv->finished) return 0; // advance animation to requested next show time while (mng_priv->anim_cur_time_ms + mng_priv->anim_frame_duration_ms <= mng_priv->show_next_time_ms && !mng_priv->finished) { // advance global and animation time mng_priv->global_time_ms += mng_priv->anim_frame_duration_ms; mng_priv->anim_cur_time_ms += mng_priv->anim_frame_duration_ms; // Clear variable MNG library will write number of milliseconds to // (via settimer callback). mng_priv->timer_ms = 0; // get next image from MNG library if (mng_priv->displaying) mng_ret = mng_display_resume(h_mng); // resume displaying MNG data // to canvas else mng_ret = mng_display(h_mng); // start displaying MNG data to canvas if (mng_ret && mng_ret != MNG_NEEDTIMERWAIT) { mp_msg(MSGT_DEMUX, MSGL_ERR, "demux_mng: could not display MNG data to canvas: " "mng_retcode %d\n", mng_ret); return 0; } mng_priv->displaying = 1; // mng_display() has been called now mng_priv->finished = mng_ret == 0; // animation is finished iff // mng_display() returned 0 // save current frame duration mng_priv->anim_frame_duration_ms = mng_priv->timer_ms < 1 ? 1 : mng_priv->timer_ms; } // while (mng_priv->anim_cur_time_ms + ... // create a new demuxer packet dp = new_demux_packet(mng_priv->height * mng_priv->width * 4); // copy image data into demuxer packet memcpy(dp->buffer, mng_priv->canvas, mng_priv->height * mng_priv->width * 4); // set current show time to requested show time mng_priv->show_cur_time_ms = mng_priv->show_next_time_ms; // get time of next frame to show mng_priv->show_next_time_ms = mng_priv->anim_cur_time_ms + mng_priv->anim_frame_duration_ms; // Set position and timing information in demuxer video and demuxer packet. // - Time must be time of next frame and always be > 0 for the variable // frame time mechanism (GIF, MATROSKA, MNG) in video.c to work. demuxer->video->dpos++; dp->pts = (float)mng_priv->show_next_time_ms / 1000.0f + MNG_START_PTS; dp->pos = stream_tell(demuxer->stream); ds_add_packet(demuxer->video, dp); return 1; }
// 0 = EOF or no stream found // 1 = successfully read a packet static int demux_pva_fill_buffer (demuxer_t * demux, demux_stream_t *ds) { uint8_t done=0; demux_packet_t * dp; pva_priv_t * priv=demux->priv; pva_payload_t current_payload; while(!done) { if(!pva_get_payload(demux,¤t_payload)) return 0; switch(current_payload.type) { case VIDEOSTREAM: if(demux->video->id==-1) demux->video->id=0; if(!current_payload.is_packet_start && priv->last_video_pts==-1) { /* We should only be here at the beginning of a stream, when we have * not yet encountered a valid Video PTS, or after a seek. * So, skip these starting packets in order not to deliver the * player a bogus PTS. */ done=0; } else { /* * In every other condition, we are delivering the payload. Set this * so that the following code knows whether to skip it or read it. */ done=1; } if(demux->video->id!=0) done=0; if(current_payload.is_packet_start) { priv->last_video_pts=current_payload.pts; //mp_msg(MSGT_DEMUXER,MSGL_DBG2,"demux_pva: Video PTS=%llu , delivered %f\n",current_payload.pts,priv->last_video_pts); } if(done) { dp=new_demux_packet(current_payload.size); dp->pts=priv->last_video_pts; stream_read(demux->stream,dp->buffer,current_payload.size); ds_add_packet(demux->video,dp); } else { //printf("Skipping %u video bytes\n",current_payload.size); stream_skip(demux->stream,current_payload.size); } break; case MAINAUDIOSTREAM: if(demux->audio->id==-1) demux->audio->id=0; if(!current_payload.is_packet_start && priv->last_audio_pts==-1) { /* Same as above for invalid video PTS, just for audio. */ done=0; } else { done=1; } if(current_payload.is_packet_start) { priv->last_audio_pts=current_payload.pts; } if(demux->audio->id!=0) done=0; if(done) { dp=new_demux_packet(current_payload.size); dp->pts=priv->last_audio_pts; if(current_payload.offset != stream_tell(demux->stream)) stream_seek(demux->stream,current_payload.offset); stream_read(demux->stream,dp->buffer,current_payload.size); ds_add_packet(demux->audio,dp); } else { stream_skip(demux->stream,current_payload.size); } break; } } return 1; }
// return value: // 0 = EOF or no stream found // 1 = successfully read a packet static int demux_vivo_fill_buffer(demuxer_t *demux, demux_stream_t *dsds){ demux_stream_t *ds=NULL; int c; int len=0; int seq; int prefix=0; demux->filepos=stream_tell(demux->stream); c=stream_read_char(demux->stream); // printf("c=%x,%02X\n",c,c&0xf0); if (c == 0x82) { /* ok, this works, but pts calculating from header is required! */ /* FIXME: "Calculate PTS from picture header!" */ prefix = 1; c = stream_read_char(demux->stream); mp_msg(MSGT_DEMUX, MSGL_V, "packet 0x82(pos=%u) chunk=%x\n", (int)stream_tell(demux->stream), c); } if (c == -256) /* EOF */ return 0; switch(c&0xF0){ case 0x00: // header - skip it! { len=stream_read_char(demux->stream); if (len == -256) /* EOF */ return 0; if(len>=0x80) { int tmp=stream_read_char(demux->stream); if (tmp == -256) /* EOF */ return 0; len=0x80*(len-0x80)+tmp; } mp_msg(MSGT_DEMUX, MSGL_V, "vivo extra header: %d bytes\n",len); #ifdef TEXTPARSE_ALL { int pos; /* also try to parse all headers */ pos = stream_tell(demux->stream); vivo_parse_text_header(demux, len); stream_seek(demux->stream, pos); } #endif break; } case 0x10: // video packet if (prefix == 1) len = stream_read_char(demux->stream); else len=128; if (len == -256) /* EOF */ return 0; ds=demux->video; break; case 0x20: // video packet len=stream_read_char(demux->stream); if (len == -256) /* EOF */ return 0; ds=demux->video; break; case 0x30: // audio packet if (prefix == 1) len = stream_read_char(demux->stream); else len=40; /* 40kbps */ if (len == -256) /* EOF */ return 0; ds=demux->audio; audio_pos+=len; break; case 0x40: // audio packet if (prefix == 1) len = stream_read_char(demux->stream); else len=24; /* 24kbps */ if (len == -256) /* EOF */ return 0; ds=demux->audio; audio_pos+=len; break; default: mp_msg(MSGT_DEMUX,MSGL_WARN,"VIVO - unknown ID found: %02X at pos %"PRIu64" contact author!\n", c, (int64_t)stream_tell(demux->stream)); return 0; } // printf("chunk=%x, len=%d\n", c, len); if(!ds || ds->id<-1){ if(len) stream_skip(demux->stream,len); return 1; } seq=c&0x0F; if(ds->asf_packet){ if(ds->asf_seq!=seq){ // closed segment, finalize packet: ds_add_packet(ds,ds->asf_packet); ds->asf_packet=NULL; // printf("packet!\n"); } else { // append data to it! demux_packet_t* dp=ds->asf_packet; if(dp->len + len + MP_INPUT_BUFFER_PADDING_SIZE < 0) return 0; dp->buffer=realloc(dp->buffer,dp->len+len+MP_INPUT_BUFFER_PADDING_SIZE); memset(dp->buffer+dp->len+len, 0, MP_INPUT_BUFFER_PADDING_SIZE); //memcpy(dp->buffer+dp->len,data,len); stream_read(demux->stream,dp->buffer+dp->len,len); mp_dbg(MSGT_DEMUX,MSGL_DBG4,"data appended! %d+%d\n",dp->len,len); dp->len+=len; // we are ready now. if((c&0xF0)==0x20) --ds->asf_seq; // hack! return 1; } } // create new packet: { demux_packet_t* dp; dp=new_demux_packet(len); //memcpy(dp->buffer,data,len); stream_read(demux->stream,dp->buffer,len); dp->pts=audio_rate?((float)audio_pos/(float)audio_rate):0; // dp->flags=keyframe; // if(ds==demux->video) printf("ASF time: %8d dur: %5d \n",time,dur); dp->pos=demux->filepos; ds->asf_packet=dp; ds->asf_seq=seq; // we are ready now. return 1; } }
static int pva_get_payload(demuxer_t *d, pva_payload_t *payload) { uint8_t flags,pes_head_len; uint16_t pack_size; off_t next_offset,pva_payload_start; unsigned char buffer[256]; #ifndef PVA_NEW_PREBYTES_CODE demux_packet_t * dp; //hack to deliver the preBytes (see PVA doc) #endif pva_priv_t * priv; if(d==NULL) { mp_msg(MSGT_DEMUX,MSGL_ERR,"demux_pva: pva_get_payload got passed a NULL pointer!\n"); return 0; } priv = (pva_priv_t *)d->priv; d->filepos=stream_tell(d->stream); if(d->stream->eof) { mp_msg(MSGT_DEMUX,MSGL_V,"demux_pva: pva_get_payload() detected stream->eof!!!\n"); return 0; } //printf("priv->just_synced %s\n",priv->just_synced?"SET":"UNSET"); #ifdef PVA_NEW_PREBYTES_CODE if(priv->prebytes_delivered) /* The previous call to this fn has delivered the preBytes. Then we are already inside * the payload. Let's just deliver the video along with its right PTS, the one we stored * in the priv structure and was in the PVA header before the PreBytes. */ { //printf("prebytes_delivered=1. Resetting.\n"); payload->size = priv->video_size_after_prebytes; payload->pts = priv->video_pts_after_prebytes; payload->is_packet_start = 1; payload->offset = stream_tell(d->stream); payload->type = VIDEOSTREAM; priv->prebytes_delivered = 0; return 1; } #endif if(!priv->just_synced) { if(stream_read_word(d->stream) != (('A'<<8)|'V')) { mp_msg(MSGT_DEMUX,MSGL_V,"demux_pva: pva_get_payload() missed a SyncWord at %"PRId64"!! Trying to sync...\n",(int64_t)stream_tell(d->stream)); if(!pva_sync(d)) { if (!d->stream->eof) { mp_msg(MSGT_DEMUX,MSGL_ERR,"demux_pva: couldn't sync! (broken file?)"); } return 0; } } } if(priv->just_synced) { payload->type=priv->synced_stream_id; priv->just_synced=0; } else { payload->type=stream_read_char(d->stream); stream_skip(d->stream,2); //counter and reserved } flags=stream_read_char(d->stream); payload->is_packet_start=flags & 0x10; pack_size=stream_read_word(d->stream); mp_msg(MSGT_DEMUX,MSGL_DBG2,"demux_pva::pva_get_payload(): pack_size=%u field read at offset %"PRIu64"\n",pack_size,(int64_t)stream_tell(d->stream)-2); pva_payload_start=stream_tell(d->stream); next_offset=pva_payload_start+pack_size; /* * The code in the #ifdef directive below is a hack needed to get badly formatted PVA files * such as the ones written by MultiDec played back correctly. * Basically, it works like this: if the PVA packet does not signal a PES header, but the * payload looks like one, let's assume it IS one. It has worked for me up to now. * It can be disabled since it's quite an ugly hack and could potentially break things up * if the PVA audio payload happens to start with 0x000001 even without being a non signalled * PES header start. * Though it's quite unlikely, it potentially could (AFAIK). */ #ifdef DEMUX_PVA_MULTIDEC_HACK if(payload->type==MAINAUDIOSTREAM) { stream_read(d->stream,buffer,3); if(buffer[0]==0x00 && buffer[1]==0x00 && buffer[2]==0x01 && !payload->is_packet_start) { mp_msg(MSGT_DEMUX,MSGL_V,"demux_pva: suspecting non signaled audio PES packet start. Maybe file by MultiDec?\n"); payload->is_packet_start=1; } stream_seek(d->stream,stream_tell(d->stream)-3); } #endif if(!payload->is_packet_start) { payload->offset=stream_tell(d->stream); payload->size=pack_size; } else { //here comes the good part... switch(payload->type) { case VIDEOSTREAM: payload->pts=(float)(stream_read_dword(d->stream))/90000; //printf("Video PTS: %f\n",payload->pts); if((flags&0x03) #ifdef PVA_NEW_PREBYTES_CODE && !priv->prebytes_delivered #endif ) { #ifndef PVA_NEW_PREBYTES_CODE dp=new_demux_packet(flags&0x03); stream_read(d->stream,dp->buffer,flags & 0x03); //read PreBytes ds_add_packet(d->video,dp); #else //printf("Delivering prebytes. Setting prebytes_delivered."); payload->offset=stream_tell(d->stream); payload->size = flags & 0x03; priv->video_pts_after_prebytes = payload->pts; priv->video_size_after_prebytes = pack_size - 4 - (flags & 0x03); payload->pts=priv->last_video_pts; payload->is_packet_start=0; priv->prebytes_delivered=1; return 1; #endif } //now we are at real beginning of payload. payload->offset=stream_tell(d->stream); //size is pack_size minus PTS size minus PreBytes size. payload->size=pack_size - 4 - (flags & 0x03); break; case MAINAUDIOSTREAM: stream_skip(d->stream,3); //FIXME properly parse PES header. //printf("StreamID in audio PES header: 0x%2X\n",stream_read_char(d->stream)); stream_skip(d->stream,4); buffer[255]=stream_read_char(d->stream); pes_head_len=stream_read_char(d->stream); stream_read(d->stream,buffer,pes_head_len); if(!(buffer[255]&0x80)) //PES header does not contain PTS. { mp_msg(MSGT_DEMUX,MSGL_V,"Audio PES packet does not contain PTS. (pes_head_len=%d)\n",pes_head_len); payload->pts=priv->last_audio_pts; break; } else //PES header DOES contain PTS { if((buffer[0] & 0xf0)!=0x20) // PTS badly formatted { mp_msg(MSGT_DEMUX,MSGL_V,"demux_pva: expected audio PTS but badly formatted... (read 0x%02X). Falling back to previous PTS (hack).\n",buffer[0]); payload->pts=priv->last_audio_pts; // return 0; } else { uint64_t temp_pts; temp_pts=0LL; temp_pts|=((uint64_t)(buffer[0] & 0x0e) << 29); temp_pts|=buffer[1]<<22; temp_pts|=(buffer[2] & 0xfe) << 14; temp_pts|=buffer[3]<<7; temp_pts|=(buffer[4] & 0xfe) >> 1; /* * PTS parsing is hopefully finished. */ payload->pts=(float)temp_pts/90000; } } payload->offset=stream_tell(d->stream); payload->size=pack_size-stream_tell(d->stream)+pva_payload_start; break; } } return 1; }
// return value: // 0 = EOF or no stream found // 1 = successfully read a packet static int demux_film_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) { int i; unsigned char byte_swap; int cvid_size; sh_video_t *sh_video = demuxer->video->sh; sh_audio_t *sh_audio = demuxer->audio->sh; film_data_t *film_data = (film_data_t *)demuxer->priv; film_chunk_t film_chunk; int length_fix_bytes; demux_packet_t* dp; // see if the end has been reached if (film_data->current_chunk >= film_data->total_chunks) return 0; film_chunk = film_data->chunks[film_data->current_chunk]; // position stream and fetch chunk stream_seek(demuxer->stream, film_chunk.chunk_offset); // load the chunks manually (instead of using ds_read_packet()), since // they require some adjustment // (all ones in syncinfo1 indicates an audio chunk) if (film_chunk.syncinfo1 == 0xFFFFFFFF) { if(demuxer->audio->id>=-1){ // audio not disabled dp = new_demux_packet(film_chunk.chunk_size); if (stream_read(demuxer->stream, dp->buffer, film_chunk.chunk_size) != film_chunk.chunk_size) return 0; dp->pts = film_chunk.pts; dp->pos = film_chunk.chunk_offset; dp->flags = 0; // adjust the data before queuing it: // 8-bit: signed -> unsigned // 16-bit: big-endian -> little-endian if (sh_audio->wf->wBitsPerSample == 8) for (i = 0; i < film_chunk.chunk_size; i++) dp->buffer[i] += 128; else for (i = 0; i < film_chunk.chunk_size; i += 2) { byte_swap = dp->buffer[i]; dp->buffer[i] = dp->buffer[i + 1]; dp->buffer[i + 1] = byte_swap; } /* for SegaSaturn .cpk file, translate audio data if stereo */ if (sh_audio->wf->nChannels == 2) { if (sh_audio->wf->wBitsPerSample == 8) { unsigned char* tmp = dp->buffer; unsigned char buf[film_chunk.chunk_size]; for(i = 0; i < film_chunk.chunk_size/2; i++) { buf[i*2] = tmp[i]; buf[i*2+1] = tmp[film_chunk.chunk_size/2+i]; } memcpy( tmp, buf, film_chunk.chunk_size ); } else {/* for 16bit */ unsigned short* tmp = dp->buffer; unsigned short buf[film_chunk.chunk_size/2]; for(i = 0; i < film_chunk.chunk_size/4; i++) { buf[i*2] = tmp[i]; buf[i*2+1] = tmp[film_chunk.chunk_size/4+i]; } memcpy( tmp, buf, film_chunk.chunk_size ); } } // append packet to DS stream ds_add_packet(demuxer->audio, dp); } } else { // if the demuxer is dealing with CVID data, deal with it a special way if (sh_video->format == mmioFOURCC('c', 'v', 'i', 'd')) { if (film_data->film_version) length_fix_bytes = 2; else length_fix_bytes = 6; // account for the fix bytes when allocating the buffer dp = new_demux_packet(film_chunk.chunk_size - length_fix_bytes); // these CVID data chunks have a few extra bytes; skip them if (stream_read(demuxer->stream, dp->buffer, 10) != 10) return 0; stream_skip(demuxer->stream, length_fix_bytes); if (stream_read(demuxer->stream, dp->buffer + 10, film_chunk.chunk_size - (10 + length_fix_bytes)) != (film_chunk.chunk_size - (10 + length_fix_bytes))) return 0; dp->pts = film_chunk.pts; dp->pos = film_chunk.chunk_offset; dp->flags = (film_chunk.syncinfo1 & 0x80000000) ? 1 : 0; // fix the CVID chunk size cvid_size = film_chunk.chunk_size - length_fix_bytes; dp->buffer[1] = (cvid_size >> 16) & 0xFF; dp->buffer[2] = (cvid_size >> 8) & 0xFF; dp->buffer[3] = (cvid_size >> 0) & 0xFF; // append packet to DS stream ds_add_packet(demuxer->video, dp); } else { ds_read_packet(demuxer->video, demuxer->stream, film_chunk.chunk_size, film_chunk.pts, film_chunk.chunk_offset, (film_chunk.syncinfo1 & 0x80000000) ? 1 : 0); } }
static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds){ lavf_priv_t *priv= demux->priv; AVPacket pkt; demux_packet_t *dp; demux_stream_t *ds; int id; double stream_pts = MP_NOPTS_VALUE; mp_msg(MSGT_DEMUX,MSGL_DBG2,"demux_lavf_fill_buffer()\n"); demux->filepos=stream_tell(demux->stream); if(av_read_frame(priv->avfc, &pkt) < 0) return 0; // handle any new streams that might have been added for (id = priv->nb_streams_last; id < priv->avfc->nb_streams; id++) handle_stream(demux, priv->avfc, id); priv->nb_streams_last = priv->avfc->nb_streams; id= pkt.stream_index; if(id==demux->audio->id){ // audio ds=demux->audio; if(!ds->sh){ ds->sh=demux->a_streams[id]; mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected LAVF audio ID = %d\n",ds->id); } } else if(id==demux->video->id){ // video ds=demux->video; if(!ds->sh){ ds->sh=demux->v_streams[id]; mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected LAVF video ID = %d\n",ds->id); } } else if(id==demux->sub->id){ // subtitle ds=demux->sub; sub_utf8=1; } else { av_free_packet(&pkt); return 1; } if(pkt.destruct == av_destruct_packet && !CONFIG_MEMALIGN_HACK){ dp=new_demux_packet(0); dp->len=pkt.size; dp->buffer=pkt.data; pkt.destruct= NULL; }else{ dp=new_demux_packet(pkt.size); memcpy(dp->buffer, pkt.data, pkt.size); av_free_packet(&pkt); } if(pkt.pts != AV_NOPTS_VALUE){ dp->pts=pkt.pts * av_q2d(priv->avfc->streams[id]->time_base); priv->last_pts= dp->pts * AV_TIME_BASE; if(pkt.duration > 0) dp->endpts = dp->pts + pkt.duration * av_q2d(priv->avfc->streams[id]->time_base); /* subtitle durations are sometimes stored in convergence_duration */ if(ds == demux->sub && pkt.convergence_duration > 0) dp->endpts = dp->pts + pkt.convergence_duration * av_q2d(priv->avfc->streams[id]->time_base); } dp->pos=demux->filepos; dp->flags= !!(pkt.flags&AV_PKT_FLAG_KEY); if (ds == demux->video && stream_control(demux->stream, STREAM_CTRL_GET_CURRENT_TIME, (void *)&stream_pts) != STREAM_UNSUPPORTED) dp->stream_pts = stream_pts; // append packet to DS stream: ds_add_packet(ds,dp); return 1; }
static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds){ lavf_priv_t *priv= demux->priv; AVPacket pkt; demux_packet_t *dp; demux_stream_t *ds; int id; mp_msg(MSGT_DEMUX,MSGL_DBG2,"demux_lavf_fill_buffer()\n"); demux->filepos=stream_tell(demux->stream); if(av_read_frame(priv->avfc, &pkt) < 0) return 0; id= pkt.stream_index; if(id==demux->audio->id){ // audio ds=demux->audio; if(!ds->sh){ ds->sh=demux->a_streams[id]; mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected LAVF audio ID = %d\n",ds->id); } } else if(id==demux->video->id){ // video ds=demux->video; if(!ds->sh){ ds->sh=demux->v_streams[id]; mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected LAVF video ID = %d\n",ds->id); } } else if(id==demux->sub->id){ // subtitle ds=demux->sub; sub_utf8=1; } else { av_free_packet(&pkt); return 1; } if(0/*pkt.destruct == av_destruct_packet*/){ //ok kids, dont try this at home :) dp=malloc(sizeof(demux_packet_t)); dp->len=pkt.size; dp->next=NULL; dp->refcount=1; dp->master=NULL; dp->buffer=pkt.data; pkt.destruct= NULL; }else{ dp=new_demux_packet(pkt.size); memcpy(dp->buffer, pkt.data, pkt.size); av_free_packet(&pkt); } if(pkt.pts != AV_NOPTS_VALUE){ dp->pts=pkt.pts * av_q2d(priv->avfc->streams[id]->time_base); priv->last_pts= dp->pts * AV_TIME_BASE; if(pkt.duration) dp->endpts = dp->pts + pkt.duration * av_q2d(priv->avfc->streams[id]->time_base); } dp->pos=demux->filepos; dp->flags= !!(pkt.flags&PKT_FLAG_KEY); // append packet to DS stream: ds_add_packet(ds,dp); return 1; }
static int demux_mkv_open_audio (FileInfo *finfo, mkv_track_t *track) { WAVEFORMATEX *finfowf = &finfo->wf; if (track->ms_compat && (track->private_size >= sizeof(WAVEFORMATEX))) { WAVEFORMATEX *wf = (WAVEFORMATEX *)track->private_data; finfowf->wFormatTag = le2me_16 (wf->wFormatTag); finfowf->nChannels = le2me_16 (wf->nChannels); finfowf->nSamplesPerSec = le2me_32 (wf->nSamplesPerSec); finfowf->nAvgBytesPerSec = le2me_32 (wf->nAvgBytesPerSec); finfowf->nBlockAlign = le2me_16 (wf->nBlockAlign); finfowf->wBitsPerSample = le2me_16 (wf->wBitsPerSample); if (track->a_sfreq == 0.0) track->a_sfreq = finfowf->nSamplesPerSec; if (track->a_channels == 0) track->a_channels = finfowf->nChannels; if (track->a_bps == 0) track->a_bps = finfowf->wBitsPerSample; track->a_formattag = finfowf->wFormatTag; } else { memset(finfowf, 0, sizeof (WAVEFORMATEX)); if (!strcmp(track->codec_id, MKV_A_MP3) || !strcmp(track->codec_id, MKV_A_MP2)) track->a_formattag = 0x0055; else if (!strncmp(track->codec_id, MKV_A_AC3, strlen(MKV_A_AC3))) track->a_formattag = 0x2000; else if (!strncmp(track->codec_id, MKV_A_EAC3, strlen(MKV_A_EAC3))) track->a_formattag = AUDIO_EAC3; else if (!strcmp(track->codec_id, MKV_A_DTS)) { track->a_formattag = 0x2001; //dts_packet = 1; } else if (!strcmp(track->codec_id, MKV_A_PCM) || !strcmp(track->codec_id, MKV_A_PCM_BE)) track->a_formattag = 0x0001; else if (!strcmp(track->codec_id, MKV_A_AAC_2MAIN) || !strncmp(track->codec_id, MKV_A_AAC_2LC, strlen(MKV_A_AAC_2LC)) || !strcmp(track->codec_id, MKV_A_AAC_2SSR) || !strcmp(track->codec_id, MKV_A_AAC_4MAIN) || !strncmp(track->codec_id, MKV_A_AAC_4LC, strlen(MKV_A_AAC_4LC)) || !strcmp(track->codec_id, MKV_A_AAC_4SSR) || !strcmp(track->codec_id, MKV_A_AAC_4LTP) || !strcmp(track->codec_id, MKV_A_AAC)) track->a_formattag = mmioFOURCC('M', 'P', '4', 'A'); else if (!strcmp(track->codec_id, MKV_A_VORBIS)) { if (track->private_data == NULL) return 1; track->a_formattag = mmioFOURCC('v', 'r', 'b', 's'); } else if (!strcmp(track->codec_id, MKV_A_QDMC)) track->a_formattag = mmioFOURCC('Q', 'D', 'M', 'C'); else if (!strcmp(track->codec_id, MKV_A_QDMC2)) track->a_formattag = mmioFOURCC('Q', 'D', 'M', '2'); else if (!strcmp(track->codec_id, MKV_A_WAVPACK)) track->a_formattag = mmioFOURCC('W', 'V', 'P', 'K'); else if (!strcmp(track->codec_id, MKV_A_TRUEHD)) track->a_formattag = mmioFOURCC('T', 'R', 'H', 'D'); else if (!strcmp(track->codec_id, MKV_A_FLAC)) { if (track->private_data == NULL || track->private_size == 0) { mp_msg (MSGT_DEMUX, MSGL_WARN, MSGTR_MPDEMUX_MKV_FlacTrackDoesNotContainValidHeaders); return 1; } track->a_formattag = mmioFOURCC ('f', 'L', 'a', 'C'); } else if (track->private_size >= RAPROPERTIES4_SIZE) { if (!strcmp(track->codec_id, MKV_A_REAL28)) track->a_formattag = mmioFOURCC('2', '8', '_', '8'); else if (!strcmp(track->codec_id, MKV_A_REALATRC)) track->a_formattag = mmioFOURCC('a', 't', 'r', 'c'); else if (!strcmp(track->codec_id, MKV_A_REALCOOK)) track->a_formattag = mmioFOURCC('c', 'o', 'o', 'k'); else if (!strcmp(track->codec_id, MKV_A_REALDNET)) track->a_formattag = mmioFOURCC('d', 'n', 'e', 't'); else if (!strcmp(track->codec_id, MKV_A_REALSIPR)) track->a_formattag = mmioFOURCC('s', 'i', 'p', 'r'); } else { mp_msg (MSGT_DEMUX, MSGL_WARN, MSGTR_MPDEMUX_MKV_UnknownAudioCodec, track->codec_id, track->tnum); return 1; } } finfowf->wFormatTag = track->a_formattag; finfowf->nChannels = track->a_channels; finfowf->nSamplesPerSec = (uint32_t) track->a_sfreq; if (track->a_bps == 0) { finfowf->wBitsPerSample = 16; } else { finfowf->wBitsPerSample = track->a_bps; } if (track->a_formattag == 0x0055) /* MP3 || MP2 */ { finfowf->nAvgBytesPerSec = 16000; finfowf->nBlockAlign = 1152; } else if (track->a_formattag == 0x2000 )/* AC3 */ { } else if (track->a_formattag == AUDIO_EAC3 )/* EAC3 */ { } else if (track->a_formattag == 0x2001) /* DTS */ { //dts_packet = 1; } else if (track->a_formattag == 0x0001) /* PCM || PCM_BE */ { finfowf->nAvgBytesPerSec = track->a_channels * track->a_sfreq * 2; finfowf->nBlockAlign = finfowf->nAvgBytesPerSec; /* if (!strcmp(track->codec_id, MKV_A_PCM_BE)) sh_a->format = mmioFOURCC('t', 'w', 'o', 's'); */ } else if (!strcmp(track->codec_id, MKV_A_QDMC) || !strcmp(track->codec_id, MKV_A_QDMC2)) { finfowf->nAvgBytesPerSec = 16000; finfowf->nBlockAlign = 1486; track->fix_i_bps = 1; track->qt_last_a_pts = 0.0; } else if (track->a_formattag == mmioFOURCC('M', 'P', '4', 'A')) { int profile, srate_idx; finfowf->nAvgBytesPerSec = 16000; finfowf->nBlockAlign = 1024; if (!strcmp (track->codec_id, MKV_A_AAC) && (NULL != track->private_data)) { return 0; } /* Recreate the 'private data' */ /* which faad2 uses in its initialization */ srate_idx = aac_get_sample_rate_index (track->a_sfreq); if (!strncmp (&track->codec_id[12], "MAIN", 4)) profile = 0; else if (!strncmp (&track->codec_id[12], "LC", 2)) profile = 1; else if (!strncmp (&track->codec_id[12], "SSR", 3)) profile = 2; else profile = 3; if (strstr(track->codec_id, "SBR") != NULL) { /* HE-AAC (aka SBR AAC) */ track->default_duration = 1024.0 / finfowf->nSamplesPerSec; finfowf->nSamplesPerSec *= 2; } else { track->default_duration = 1024.0 / (float)finfowf->nSamplesPerSec; } } else if (track->a_formattag == mmioFOURCC('v', 'r', 'b', 's')) /* VORBIS */ { //finfowf->cbSize = track->private_size; } else if (track->private_size >= RAPROPERTIES4_SIZE && !strncmp (track->codec_id, MKV_A_REALATRC, 7)) { /* Common initialization for all RealAudio codecs */ unsigned char *src = (unsigned char *)track->private_data; int codecdata_length, version; int flavor; finfowf->nAvgBytesPerSec = 0; /* FIXME !? */ version = AV_RB16(src + 4); flavor = AV_RB16(src + 22); track->coded_framesize = AV_RB32(src + 24); track->sub_packet_h = AV_RB16(src + 40); finfowf->nBlockAlign = track->audiopk_size = AV_RB16(src + 42); track->sub_packet_size = AV_RB16(src + 44); if (version == 4) { src += RAPROPERTIES4_SIZE; src += src[0] + 1; src += src[0] + 1; } else src += RAPROPERTIES5_SIZE; src += 3; if (version == 5) src++; codecdata_length = AV_RB32(src); src += 4; switch (track->a_formattag) { case mmioFOURCC('a', 't', 'r', 'c'): finfowf->nAvgBytesPerSec = atrc_fl2bps[flavor]; finfowf->nBlockAlign = track->sub_packet_size; break; case mmioFOURCC('c', 'o', 'o', 'k'): finfowf->nAvgBytesPerSec = cook_fl2bps[flavor]; finfowf->nBlockAlign = track->sub_packet_size; break; case mmioFOURCC('s', 'i', 'p', 'r'): finfowf->nAvgBytesPerSec = sipr_fl2bps[flavor]; finfowf->nBlockAlign = track->coded_framesize; break; case mmioFOURCC('2', '8', '_', '8'): finfowf->nAvgBytesPerSec = 3600; finfowf->nBlockAlign = track->coded_framesize; break; } track->realmedia = 1; } else if (!strcmp(track->codec_id, MKV_A_FLAC) || (track->a_formattag == 0xf1ac)) { unsigned char *ptr; int size; #if 1 //Fuchun 2010.06.23 if(track->a_formattag == mmioFOURCC('f', 'L', 'a', 'C')) { ptr = (unsigned char *)track->private_data; size = track->private_size; } else { //sh_a->format = mmioFOURCC('f', 'L', 'a', 'C'); ptr = (unsigned char *) track->private_data + sizeof (WAVEFORMATEX); size = track->private_size - sizeof (WAVEFORMATEX); } if(size < 4 || ptr[0] != 'f' || ptr[1] != 'L' ||ptr[2] != 'a' || ptr[3] != 'C') { //finfowf->cbSize = 4; } else { //finfowf->cbSize = size; } #else free(finfowf); finfowf = NULL; if (track->a_formattag == mmioFOURCC('f', 'L', 'a', 'C')) { ptr = (unsigned char *)track->private_data; size = track->private_size; } else { sh_a->format = mmioFOURCC('f', 'L', 'a', 'C'); ptr = (unsigned char *) track->private_data + sizeof (WAVEFORMATEX); size = track->private_size - sizeof (WAVEFORMATEX); } if (size < 4 || ptr[0] != 'f' || ptr[1] != 'L' || ptr[2] != 'a' || ptr[3] != 'C') { dp = new_demux_packet (4); memcpy (dp->buffer, "fLaC", 4); } else { dp = new_demux_packet (size); memcpy (dp->buffer, ptr, size); } dp->pts = 0; dp->flags = 0; ds_add_packet (demuxer->audio, dp); #endif } else if (track->a_formattag == mmioFOURCC('W', 'V', 'P', 'K') || track->a_formattag == mmioFOURCC('T', 'R', 'H', 'D')) { /* do nothing, still works */ } else if (!track->ms_compat || (track->private_size < sizeof(WAVEFORMATEX))) { return 1; } return 0; }