forked from forks/ffprobe-wasm
Paginate frames and add pts/dts fields.
This commit is contained in:
@@ -35,8 +35,10 @@ typedef struct Stream {
|
|||||||
} Stream;
|
} Stream;
|
||||||
|
|
||||||
typedef struct Frame {
|
typedef struct Frame {
|
||||||
char pict_type;
|
|
||||||
int frame_number;
|
int frame_number;
|
||||||
|
char pict_type;
|
||||||
|
int pts;
|
||||||
|
int dts;
|
||||||
int pkt_size;
|
int pkt_size;
|
||||||
} Frame;
|
} Frame;
|
||||||
|
|
||||||
@@ -52,6 +54,7 @@ typedef struct FileInfoResponse {
|
|||||||
|
|
||||||
typedef struct FramesResponse {
|
typedef struct FramesResponse {
|
||||||
std::vector<Frame> frames;
|
std::vector<Frame> frames;
|
||||||
|
int nb_frames;
|
||||||
} FramesResponse;
|
} FramesResponse;
|
||||||
|
|
||||||
FileInfoResponse get_file_info() {
|
FileInfoResponse get_file_info() {
|
||||||
@@ -88,11 +91,6 @@ FileInfoResponse get_file_info() {
|
|||||||
.flags = pFormatContext->flags
|
.flags = pFormatContext->flags
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get streams data.
|
|
||||||
// AVCodec *pCodec = NULL;
|
|
||||||
// AVCodecParameters *pCodecParameters = NULL;
|
|
||||||
// int video_stream_index = -1;
|
|
||||||
|
|
||||||
// Loop through the streams.
|
// Loop through the streams.
|
||||||
for (int i = 0; i < pFormatContext->nb_streams; i++) {
|
for (int i = 0; i < pFormatContext->nb_streams; i++) {
|
||||||
AVCodecParameters *pLocalCodecParameters = NULL;
|
AVCodecParameters *pLocalCodecParameters = NULL;
|
||||||
@@ -158,6 +156,7 @@ FramesResponse get_frames(int offset) {
|
|||||||
AVCodec *pCodec = NULL;
|
AVCodec *pCodec = NULL;
|
||||||
AVCodecParameters *pCodecParameters = NULL;
|
AVCodecParameters *pCodecParameters = NULL;
|
||||||
int video_stream_index = -1;
|
int video_stream_index = -1;
|
||||||
|
int nb_frames = 0;
|
||||||
|
|
||||||
// Loop through the streams.
|
// Loop through the streams.
|
||||||
for (int i = 0; i < pFormatContext->nb_streams; i++) {
|
for (int i = 0; i < pFormatContext->nb_streams; i++) {
|
||||||
@@ -169,6 +168,7 @@ FramesResponse get_frames(int offset) {
|
|||||||
if (pLocalCodecParameters->codec_type == AVMEDIA_TYPE_VIDEO) {
|
if (pLocalCodecParameters->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||||
if (video_stream_index == -1) {
|
if (video_stream_index == -1) {
|
||||||
video_stream_index = i;
|
video_stream_index = i;
|
||||||
|
nb_frames = pFormatContext->streams[i]->nb_frames;
|
||||||
pCodec = pLocalCodec;
|
pCodec = pLocalCodec;
|
||||||
pCodecParameters = pLocalCodecParameters;
|
pCodecParameters = pLocalCodecParameters;
|
||||||
}
|
}
|
||||||
@@ -182,6 +182,7 @@ FramesResponse get_frames(int offset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FramesResponse r;
|
FramesResponse r;
|
||||||
|
r.nb_frames = nb_frames;
|
||||||
|
|
||||||
AVCodecContext *pCodecContext = avcodec_alloc_context3(pCodec);
|
AVCodecContext *pCodecContext = avcodec_alloc_context3(pCodec);
|
||||||
avcodec_parameters_to_context(pCodecContext, pCodecParameters);
|
avcodec_parameters_to_context(pCodecContext, pCodecParameters);
|
||||||
@@ -190,14 +191,13 @@ FramesResponse get_frames(int offset) {
|
|||||||
AVPacket *pPacket = av_packet_alloc();
|
AVPacket *pPacket = av_packet_alloc();
|
||||||
AVFrame *pFrame = av_frame_alloc();
|
AVFrame *pFrame = av_frame_alloc();
|
||||||
|
|
||||||
int how_many_packets_to_process = 300;
|
int how_many_packets_to_process = 48; // per page.
|
||||||
int frame_count = 0;
|
int frame_count = 1;
|
||||||
|
|
||||||
// Read video frames.
|
// Read video frames.
|
||||||
// TODO: Support seek so we don't have to cap at 300 frames.
|
|
||||||
while (av_read_frame(pFormatContext, pPacket) >= 0) {
|
while (av_read_frame(pFormatContext, pPacket) >= 0) {
|
||||||
if (frame_count >= offset) {
|
if (pPacket->stream_index == video_stream_index) {
|
||||||
if (pPacket->stream_index == video_stream_index) {
|
if (frame_count >= offset) {
|
||||||
|
|
||||||
int response = 0;
|
int response = 0;
|
||||||
response = avcodec_send_packet(pCodecContext, pPacket);
|
response = avcodec_send_packet(pCodecContext, pPacket);
|
||||||
@@ -209,8 +209,10 @@ FramesResponse get_frames(int offset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Frame f = {
|
Frame f = {
|
||||||
|
.frame_number = frame_count,
|
||||||
.pict_type = (char) av_get_picture_type_char(pFrame->pict_type),
|
.pict_type = (char) av_get_picture_type_char(pFrame->pict_type),
|
||||||
.frame_number = pCodecContext->frame_number,
|
.pts = (int) pPacket->pts,
|
||||||
|
.dts = (int) pPacket->dts,
|
||||||
.pkt_size = pFrame->pkt_size,
|
.pkt_size = pFrame->pkt_size,
|
||||||
};
|
};
|
||||||
r.frames.push_back(f);
|
r.frames.push_back(f);
|
||||||
@@ -218,11 +220,9 @@ FramesResponse get_frames(int offset) {
|
|||||||
if (--how_many_packets_to_process <= 0) break;
|
if (--how_many_packets_to_process <= 0) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
frame_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame_count++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,8 +251,10 @@ EMSCRIPTEN_BINDINGS(FileInfoResponse_struct) {
|
|||||||
register_vector<Stream>("Stream");
|
register_vector<Stream>("Stream");
|
||||||
|
|
||||||
emscripten::value_object<Frame>("Frame")
|
emscripten::value_object<Frame>("Frame")
|
||||||
.field("pict_type", &Frame::pict_type)
|
|
||||||
.field("frame_number", &Frame::frame_number)
|
.field("frame_number", &Frame::frame_number)
|
||||||
|
.field("pict_type", &Frame::pict_type)
|
||||||
|
.field("pts", &Frame::pts)
|
||||||
|
.field("dts", &Frame::dts)
|
||||||
.field("pkt_size", &Frame::pkt_size);
|
.field("pkt_size", &Frame::pkt_size);
|
||||||
register_vector<Frame>("Frame");
|
register_vector<Frame>("Frame");
|
||||||
|
|
||||||
@@ -269,6 +271,7 @@ EMSCRIPTEN_BINDINGS(FileInfoResponse_struct) {
|
|||||||
|
|
||||||
emscripten::value_object<FramesResponse>("FramesResponse")
|
emscripten::value_object<FramesResponse>("FramesResponse")
|
||||||
.field("frames", &FramesResponse::frames)
|
.field("frames", &FramesResponse::frames)
|
||||||
|
.field("nb_frames", &FramesResponse::nb_frames)
|
||||||
;
|
;
|
||||||
function("get_frames", &get_frames);
|
function("get_frames", &get_frames);
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<h4>Frames</h4>
|
<h4>Frames</h4>
|
||||||
|
<p class="text-right">Total: {{ data.nb_frames }}</p>
|
||||||
|
|
||||||
|
<b-pagination
|
||||||
|
v-model="currentPage"
|
||||||
|
@change="onPageChanged"
|
||||||
|
:total-rows="pages"
|
||||||
|
:per-page="perPage"
|
||||||
|
align="right"
|
||||||
|
></b-pagination>
|
||||||
|
|
||||||
<b-table striped hover :items="frames">
|
<b-table striped hover :items="frames">
|
||||||
<template #cell(pict_type)="data">
|
<template #cell(pict_type)="data">
|
||||||
{{ String.fromCharCode(data.value) }}
|
{{ String.fromCharCode(data.value) }}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</b-table>
|
</b-table>
|
||||||
|
|
||||||
|
<b-pagination
|
||||||
|
v-model="currentPage"
|
||||||
|
@change="onPageChanged"
|
||||||
|
:total-rows="pages"
|
||||||
|
:per-page="perPage"
|
||||||
|
align="right"
|
||||||
|
></b-pagination>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -16,9 +33,14 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
data: null,
|
data: null,
|
||||||
|
currentPage: 1,
|
||||||
|
perPage: 48,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
pages() {
|
||||||
|
return this.data.nb_frames;
|
||||||
|
},
|
||||||
frames() {
|
frames() {
|
||||||
if (!this.data) return [];
|
if (!this.data) return [];
|
||||||
|
|
||||||
@@ -32,5 +54,11 @@ export default {
|
|||||||
created() {
|
created() {
|
||||||
this.data = window.Module.get_frames(0);
|
this.data = window.Module.get_frames(0);
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
|
onPageChanged(page) {
|
||||||
|
this.data = window.Module.get_frames(this.perPage * (page - 1));
|
||||||
|
window.scrollTo(0, 0);
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
Reference in New Issue
Block a user