mirror of
https://github.com/zoriya/Kyoo.Transcoder.git
synced 2025-12-06 06:26:11 +00:00
First try at the font extractor
This commit is contained in:
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user