improved format support for MAD files

This commit is contained in:
itsmattkc
2018-08-03 11:14:48 +10:00
parent 461cdeb57c
commit 8e957ade58
3 changed files with 130 additions and 103 deletions
+35 -11
View File
@@ -18,13 +18,11 @@ extern "C" {
#include <libswresample/swresample.h>
}
PreviewGenerator::PreviewGenerator(QTreeWidgetItem* i, Media* m) : QThread(0), fmt_ctx(NULL), item(i), media(m) {
PreviewGenerator::PreviewGenerator(QTreeWidgetItem* i, Media* m) : QThread(0), fmt_ctx(NULL), item(i), media(m), retrieve_duration(false), contains_still_image(false) {
connect(this, SIGNAL(finished()), this, SLOT(deleteLater()));
}
void PreviewGenerator::parse_media() {
bool contains_still_image = false;
// detect video/audio streams in file
for (int i=0;i<(int)fmt_ctx->nb_streams;i++) {
// Find the decoder for the video stream
@@ -63,6 +61,14 @@ void PreviewGenerator::parse_media() {
}
media->length = fmt_ctx->duration;
if (fmt_ctx->duration == INT64_MIN) {
retrieve_duration = true;
} else {
finalize_media();
}
}
void PreviewGenerator::finalize_media() {
media->ready = true;
if (media->video_tracks.size() == 0) {
@@ -83,6 +89,7 @@ void PreviewGenerator::generate_waveform() {
SwrContext* swr_ctx;
AVFrame* temp_frame = av_frame_alloc();
AVCodecContext** codec_ctx = new AVCodecContext* [fmt_ctx->nb_streams];
int64_t* media_lengths = new int64_t[fmt_ctx->nb_streams]{0};
for (unsigned int i=0;i<fmt_ctx->nb_streams;i++) {
codec_ctx[i] = NULL;
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
@@ -125,8 +132,9 @@ void PreviewGenerator::generate_waveform() {
}
if (!end_of_file) {
MediaStream* s = media->get_stream_from_file_index(packet.stream_index);
if (s != NULL && !s->preview_done) {
if (s != NULL) {
if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
if (!s->preview_done) {
int dstH = 120;
int dstW = dstH * ((float)temp_frame->width/(float)temp_frame->height);
uint8_t* data = new uint8_t[dstW*dstH*3];
@@ -150,14 +158,18 @@ void PreviewGenerator::generate_waveform() {
s->video_preview = QImage(data, dstW, dstH, linesize[0], QImage::Format_RGB888);
// delete [] data;
// delete [] data;
s->preview_done = true;
sws_freeContext(sws_ctx);
if (!retrieve_duration) {
avcodec_close(codec_ctx[packet.stream_index]);
codec_ctx[packet.stream_index] = NULL;
}
}
media_lengths[packet.stream_index]++;
} else if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
int interval = qFloor((temp_frame->sample_rate/WAVEFORM_RESOLUTION)/4)*4;
@@ -195,19 +207,20 @@ void PreviewGenerator::generate_waveform() {
min = sample;
}
}
min /= 256;
max /= 256;
s->audio_preview.append(min);
s->audio_preview.append(max);
s->audio_preview.append(min >> 8);
s->audio_preview.append(max >> 8);
}
}
swr_free(&swr_ctx);
av_frame_free(&swr_frame);
}
}
// check if we've got all our previews
if (media->audio_tracks.size() == 0) {
if (retrieve_duration) {
done = false;
} else if (media->audio_tracks.size() == 0) {
done = true;
for (int i=0;i<media->video_tracks.size();i++) {
if (!media->video_tracks.at(i)->preview_done) {
@@ -220,7 +233,6 @@ void PreviewGenerator::generate_waveform() {
break;
}
}
}
av_packet_unref(&packet);
}
}
@@ -233,6 +245,18 @@ void PreviewGenerator::generate_waveform() {
avcodec_close(codec_ctx[i]);
}
}
if (retrieve_duration) {
media->length = 0;
int maximum_stream = 0;
for (unsigned int i=0;i<fmt_ctx->nb_streams;i++) {
if (media_lengths[i] > media_lengths[maximum_stream]) {
maximum_stream = i;
}
}
media->length = (double) media_lengths[maximum_stream] / av_q2d(fmt_ctx->streams[maximum_stream]->avg_frame_rate) * AV_TIME_BASE;
finalize_media();
}
delete [] media_lengths;
delete [] codec_ctx;
}
+3
View File
@@ -23,9 +23,12 @@ signals:
private:
void parse_media();
void generate_waveform();
void finalize_media();
QTreeWidgetItem* item;
Media* media;
AVFormatContext* fmt_ctx;
bool retrieve_duration;
bool contains_still_image;
};
#endif // PREVIEWGENERATOR_H
+1 -1
View File
@@ -436,7 +436,7 @@ void MainWindow::on_actionCrash_triggered()
temp->snapped = true;
int* kek;
kek[5] = 69;
kek[99999] = 420;
kek[99999] = kek[5];
delete temp;
}
}