mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-18 07:44:43 +01:00
Improve init_seek: don't add existing index, find packet size (for M4A)
This commit is contained in:
parent
8cdce2c196
commit
80c8791288
@ -373,43 +373,58 @@ fail:
|
|||||||
*
|
*
|
||||||
* Fortunately seek_frame_generic can use an index to find the correct position. This function reads the
|
* Fortunately seek_frame_generic can use an index to find the correct position. This function reads the
|
||||||
* first frame/packet and sets up index to timestamp 0. This ensures faulty demuxers will seek to 0 correctly.
|
* first frame/packet and sets up index to timestamp 0. This ensures faulty demuxers will seek to 0 correctly.
|
||||||
* Some formats may not seek to 0 even with this though.
|
* Some formats may not seek to 0 even with this, though.
|
||||||
*/
|
*/
|
||||||
static int init_seek(ffmpeg_codec_data * data) {
|
static int init_seek(ffmpeg_codec_data * data) {
|
||||||
int ret, found = 0;
|
int ret, ts_index, found_first = 0;
|
||||||
int64_t ts = 0;
|
int64_t ts = 0;
|
||||||
|
int64_t pos; /* offset */
|
||||||
|
int size; /* coded size */
|
||||||
|
int distance = 0; /* always? */
|
||||||
|
|
||||||
AVStream * stream;
|
AVStream * stream;
|
||||||
AVPacket * pkt;
|
AVPacket * pkt;
|
||||||
|
|
||||||
/* read_seek wouldn't use the index, but direct access to FFmpeg's internals is no good */
|
stream = data->formatCtx->streams[data->streamIndex];
|
||||||
/* if (data->formatCtx->iformat->read_seek || data->formatCtx->iformat->read_seek2)
|
|
||||||
return; */
|
|
||||||
|
|
||||||
|
|
||||||
pkt = data->lastReadPacket;
|
pkt = data->lastReadPacket;
|
||||||
|
|
||||||
/* find the first packet */
|
/* read_seek shouldn't need this index, but direct access to FFmpeg's internals is no good */
|
||||||
while (!found) {
|
/* if (data->formatCtx->iformat->read_seek || data->formatCtx->iformat->read_seek2)
|
||||||
|
return 0; */
|
||||||
|
|
||||||
|
/* some formats already have a proper index (e.g. M4A) */
|
||||||
|
ts_index = av_index_search_timestamp(stream, ts, AVSEEK_FLAG_ANY);
|
||||||
|
if (ts_index>=0)
|
||||||
|
goto test_seek;
|
||||||
|
|
||||||
|
|
||||||
|
/* find the first + second packets to get pos/size */
|
||||||
|
while (1) {
|
||||||
av_packet_unref(pkt);
|
av_packet_unref(pkt);
|
||||||
ret = av_read_frame(data->formatCtx, pkt);
|
ret = av_read_frame(data->formatCtx, pkt);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
goto fail;
|
||||||
|
|
||||||
if (pkt->stream_index != data->streamIndex)
|
if (pkt->stream_index != data->streamIndex)
|
||||||
continue; /* ignore non-selected streams */
|
continue; /* ignore non-selected streams */
|
||||||
|
|
||||||
found = 1;
|
if (!found_first) { /* first found */
|
||||||
|
found_first = 1;
|
||||||
|
pos = pkt->pos;
|
||||||
|
continue;
|
||||||
|
} else { /* second found */
|
||||||
|
size = pkt->pos - pos; /* coded, pkt->size is decoded size */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!found)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* add index 0 */
|
/* add index 0 */
|
||||||
stream = data->formatCtx->streams[data->streamIndex];
|
ret = av_add_index_entry(stream, pos, ts, size, distance, AVINDEX_KEYFRAME);
|
||||||
ret = av_add_index_entry(stream, pkt->pos, ts, pkt->size, 0, AVINDEX_KEYFRAME);
|
|
||||||
if ( ret < 0 )
|
if ( ret < 0 )
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* move back to beginning, since we just consumed packets */
|
|
||||||
|
test_seek:
|
||||||
|
/* seek to 0 test / move back to beginning, since we just consumed packets */
|
||||||
ret = avformat_seek_file(data->formatCtx, data->streamIndex, ts, ts, ts, AVSEEK_FLAG_ANY);
|
ret = avformat_seek_file(data->formatCtx, data->streamIndex, ts, ts, ts, AVSEEK_FLAG_ANY);
|
||||||
if ( ret < 0 )
|
if ( ret < 0 )
|
||||||
return ret; /* we can't even reset_vgmstream the file */
|
return ret; /* we can't even reset_vgmstream the file */
|
||||||
@ -417,6 +432,10 @@ static int init_seek(ffmpeg_codec_data * data) {
|
|||||||
avcodec_flush_buffers(data->codecCtx);
|
avcodec_flush_buffers(data->codecCtx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user