First try at the font extractor

This commit is contained in:
Zoe Roux
2020-10-29 22:57:06 +01:00
parent ab165e80e4
commit 8a199d664f
5 changed files with 64 additions and 172 deletions

View File

@@ -27,8 +27,10 @@ typedef struct stream
type type;
} stream;
void extract_subtitle(stream *subtitle,
const char *out_path,
AVStream *stream,
AVFormatContext *in_ctx,
AVFormatContext **out_ctx);
void extract_track(stream *track,
const char *out_path,
AVStream *stream,
AVFormatContext *in_ctx,
AVFormatContext **out_ctx);
void extract_font(stream *font, const char *out_path, AVStream *stream);

View File

@@ -91,7 +91,9 @@ stream *extract_infos(const char *path, const char *out_path, unsigned *stream_c
*track_count += 1;
streams[i] = parse_stream(stream, stream_type, path);
if (stream_type == subtitle)
extract_subtitle(&streams[i], out_path, stream, ctx, &output_list[i]);
extract_track(&streams[i], out_path, stream, ctx, &output_list[i]);
if (stream_type == font)
extract_font(&streams[i], out_path, stream);
}
}
}

View File

@@ -1,140 +0,0 @@
//
// Created by Anonymus Raccoon on 16/12/2019.
//
#include "stream.h"
#include "helper.h"
#include "path_helper.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <transcoder.h>
int get_subtitle_data(stream *substream, AVStream *in_stream, const char *file_name, const char *out_path)
{
AVDictionaryEntry *languageptr = av_dict_get(in_stream->metadata, "language", NULL, 0);
char *codec = strdup(avcodec_get_name(in_stream->codecpar->codec_id));
char *extension = get_extension_from_codec(codec);
char *folder_path;
if (!extension)
return -1;
*substream = (stream) {
NULL,
languageptr ? strdup(languageptr->value) : NULL,
codec,
in_stream->disposition & AV_DISPOSITION_DEFAULT,
in_stream->disposition & AV_DISPOSITION_FORCED,
NULL,
subtitle
};
asprintf(&folder_path, "%s/%s", out_path, substream->language);
if (path_mkdir(folder_path, 0733) < 0) {
if (!folder_path)
free(folder_path);
return -1;
}
asprintf(&substream->path, "%s/%s.%s%s%s%s", folder_path,
file_name,
substream->language,
substream->is_default ? ".default" : "",
substream->is_forced ? ".forced" : "",
extension);
free(folder_path);
if (!substream->path)
return -1;
return 0;
}
void write_data(AVFormatContext *int_ctx, AVFormatContext **output_list, unsigned int out_count)
{
AVPacket pkt;
while (av_read_frame(int_ctx, &pkt) == 0) {
AVFormatContext *out_ctx;
if ((unsigned)pkt.stream_index >= out_count)
continue;
out_ctx = output_list[pkt.stream_index];
if (!out_ctx) {
av_packet_unref(&pkt);
continue;
}
process_packet(&pkt, int_ctx->streams[pkt.stream_index], out_ctx->streams[0]);
pkt.stream_index = 0;
if (av_interleaved_write_frame(out_ctx, &pkt) < 0)
fprintf(stderr, "Error while writing a packet to the output file.\n");
av_packet_unref(&pkt);
}
}
void finish_up(AVFormatContext *int_ctx, AVFormatContext **output_list, unsigned out_count)
{
avformat_close_input(&int_ctx);
for (unsigned i = 0; i < out_count; i++) {
AVFormatContext *out_ctx = output_list[i];
if (!out_ctx)
continue;
av_write_trailer(out_ctx);
if (!(out_ctx->flags & AVFMT_NOFILE))
avio_closep(&out_ctx->pb);
avformat_free_context(out_ctx);
}
free(output_list);
}
int split_inputfile(AVFormatContext *int_ctx, AVFormatContext **output_list, stream *streams, char *path, const char *out_path)
{
int subcount = 0;
char *file_name = path_getfilename(path);
if (!file_name)
return -1;
for (unsigned int i = 0; i < int_ctx->nb_streams; i++) {
AVStream *in_stream = int_ctx->streams[i];
if (in_stream->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
if (get_subtitle_data(streams + i, in_stream, file_name, out_path) == 0 &&
copy_subtitle_stream(&output_list[i], streams + i, int_ctx, in_stream) == 0) {
subcount += 1;
continue;
}
fprintf(stderr,"Couldn't copy the %s subtitle to output\n", streams[i].language);
destroy_stream(&streams[i]);
}
streams[i] = NULLSTREAM;
output_list[i] = NULL;
}
free(file_name);
return subcount;
}
stream *extract_subtitles(char *path, const char *out_path, unsigned *stream_count, unsigned *subtitle_count)
{
AVFormatContext *int_ctx = NULL;
AVFormatContext **output_list;
stream *streams;
if (open_input_context(&int_ctx, path) != 0)
return NULL;
*stream_count = int_ctx->nb_streams;
streams = calloc(sizeof(stream), *stream_count);
output_list = malloc(sizeof(AVFormatContext *) * int_ctx->nb_streams);
if (streams && output_list) {
*subtitle_count = split_inputfile(int_ctx, output_list, streams, path, out_path);
if (*subtitle_count >= 0) {
write_data(int_ctx, output_list, *stream_count);
finish_up(int_ctx, output_list, *stream_count);
return streams;
}
}
*subtitle_count = 0;
if (streams)
free_streams(streams, (int)*stream_count);
if (output_list)
free(output_list);
avformat_close_input(&int_ctx);
return NULL;
}

View File

@@ -3,7 +3,6 @@
//
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
@@ -50,14 +49,16 @@ char *get_extension_from_codec(char *codec)
{
if (!codec)
return NULL;
if (!strcmp(codec, "subrip"))
return ".srt";
else if (!strcmp(codec, "ass"))
if (!strcmp(codec, "ass"))
return ".ass";
else {
printf("Unsupported subtitle codec: %s.\n", codec);
return NULL;
}
if (!strcmp(codec, "ttf"))
return ".ttf";
printf("Unsupported subtitle codec: %s.\n", codec);
return NULL;
}
int path_mkdir(const char *path, int mode)

View File

@@ -9,38 +9,39 @@
#include <malloc.h>
#include <libavformat/avformat.h>
#include <unistd.h>
#include <fcntl.h>
// @return -2 on error, -1 if subtitle has alreaady been extracted, 0 on success.
int create_out_path(stream *subtitle, const char *out_path)
// @return -2 on error, -1 if track has alreaady been extracted, 0 on success.
int create_out_path(stream *track, const char *out_path)
{
char *extension = get_extension_from_codec(subtitle->codec);
char *extension = get_extension_from_codec(track->codec);
char *folder_path;
char *file_name;
if (!extension)
return -2;
file_name = path_getfilename(subtitle->path);
asprintf(&folder_path, "%s/%s", out_path, subtitle->language);
file_name = path_getfilename(track->path);
asprintf(&folder_path, "%s/%s", out_path, track->language);
if (path_mkdir(folder_path, 0733) < 0) {
free(folder_path);
free(file_name);
return -2;
}
free(subtitle->path);
asprintf(&subtitle->path, "%s/%s.%s%s%s%s", folder_path,
free(track->path);
asprintf(&track->path, "%s/%s.%s%s%s%s", folder_path,
file_name,
subtitle->language,
subtitle->is_default ? ".default" : "",
subtitle->is_forced ? ".forced" : "",
track->language,
track->is_default ? ".default" : "",
track->is_forced ? ".forced" : "",
extension);
free(folder_path);
free(file_name);
if (!subtitle->path)
if (!track->path)
return -2;
return access(subtitle->path, F_OK) == 0 ? -1 : 0;
return access(track->path, F_OK) == 0 ? -1 : 0;
}
int copy_subtitle_stream(AVFormatContext **out_ctx, stream *s, AVFormatContext *int_ctx, AVStream *in_stream)
int extract_stream(AVFormatContext **out_ctx, stream *s, AVFormatContext *int_ctx, AVStream *in_stream)
{
AVStream *out_stream = NULL;
@@ -61,13 +62,39 @@ int copy_subtitle_stream(AVFormatContext **out_ctx, stream *s, AVFormatContext *
return -1;
}
void extract_subtitle(stream *subtitle,
const char *out_path,
AVStream *stream,
AVFormatContext *in_ctx,
AVFormatContext **out_ctx)
void extract_track(stream *track,
const char *out_path,
AVStream *stream,
AVFormatContext *in_ctx,
AVFormatContext **out_ctx)
{
if (create_out_path(subtitle, out_path) != 0)
if (create_out_path(track, out_path) != 0)
return;
copy_subtitle_stream(out_ctx, subtitle, in_ctx, stream);
extract_stream(out_ctx, track, in_ctx, stream);
}
void extract_font(stream *font, const char *out_path, AVStream *stream)
{
AVDictionaryEntry *filename = av_dict_get(stream->metadata, "filename", NULL, 0);
if (!filename)
return;
free(font->path);
font->path = malloc((strlen(out_path) + 7 + strlen(filename->value)) * sizeof(char));
if (!font->path)
return;
strcpy(font->path, out_path);
strcat(font->path, "/fonts/");
if (path_mkdir(font->path, 0733) < 0)
return free(font->path);
strcat(font->path, filename->value);
int count = strchr(filename->value, '.') - filename->value;
if (count > 0)
font->title = strndup(filename->value, count);
int fd = open(font->path, O_WRONLY | O_CREAT);
if (fd == -1)
return perror("Kyoo couldn't extract a subtitle's font");
write(fd, stream->codecpar->extradata, stream->codecpar->extradata_size);
close(fd);
}