Paginate frames and add pts/dts fields.

This commit is contained in:
Alf
2020-11-12 23:12:36 -08:00
parent 21c0e20604
commit 1e8976b7ec
2 changed files with 48 additions and 17 deletions

View File

@@ -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);
} }

View File

@@ -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>