Reworking the subtitle extraction

This commit is contained in:
Zoe Roux
2019-12-29 03:59:19 +01:00
parent 48c7902eca
commit c07db50068
7 changed files with 147 additions and 52 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ include_directories(include)
add_library(transcoder SHARED
src/helper.c
src/subtitles.c
src/info.c)
src/info.c src/path_helper.c)
set_property(TARGET transcoder PROPERTY C_STANDARD 11)
target_link_libraries(transcoder
+9
View File
@@ -0,0 +1,9 @@
//
// Created by anonymus-raccoon on 12/29/19.
//
#pragma once
char *path_getfolder(const char *path);
char *get_extension_from_codec(char *codec);
+3 -1
View File
@@ -11,4 +11,6 @@
//Take the path of the file and the path of the output directory. It will return the list of subtitle streams in the streams variable. The int returned is the number of subtitles extracted.
API stream *extract_subtitles(char *path, const char *out_path, unsigned *stream_count, unsigned *subtitle_count);
API void free_memory(stream *streamsPtr);
void destroy_stream(stream *s);
API void free_streams(stream *streamsPtr, int count);
+16 -2
View File
@@ -64,7 +64,21 @@ void process_packet(AVPacket *pkt, AVStream *in_stream, AVStream *out_stream)
pkt->pos = -1;
}
void free_memory(stream *stream_ptr)
void destroy_stream(stream *s)
{
free(stream_ptr);
if (s->title)
free(s->title);
if (s->language)
free(s->language);
if (s->codec)
free(s->codec);
if (s->path)
free(s->path);
}
void free_streams(stream *s, int count)
{
for (unsigned i = 0; i < count; i++)
destroy_stream(s + i);
free(s);
}
+51
View File
@@ -0,0 +1,51 @@
//
// Created by anonymus-raccoon on 12/29/19.
//
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
char *strrnchr(const char *str, int c, int occ_to_skip)
{
const char *ptr = str + strlen(str);
while (ptr != str) {
if (*str == c) {
occ_to_skip--;
if (occ_to_skip == 0)
return ((char *)str);
}
str--;
}
return (NULL);
}
char *path_getfolder(const char *path)
{
char *start;
char *end;
char *folder;
start = strrnchr(path, '/', 1);
end = strrchr(path, '/');
if (!end)
return (NULL);
folder = strndup(start, end - start);
return (folder);
}
char *get_extension_from_codec(char *codec)
{
if (!codec)
return (NULL);
if (!strcmp(codec, "subrip"))
return(".srt");
else if (!strcmp(codec, "ass"))
return(".ass");
else {
printf("Unsupported subtitle codec: %s.\n", codec);
free(codec);
return (NULL);
}
}
+58 -46
View File
@@ -5,45 +5,44 @@
#include "stream.h"
#include "helper.h"
#include "compatibility.h"
#include "path_helper.h"
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <transcoder.h>
int get_subtitle_data(stream *substream, AVStream *in_stream, const char *folder_name, const char *out_path)
{
AVDictionaryEntry *languageptr = av_dict_get(in_stream->metadata, "language", NULL, 0);
char *extension;
char *codec = strdup(avcodec_get_name(in_stream->codecpar->codec_id));
char *extension = get_extension_from_codec(codec);
char *folder_path;
if (!codec)
return (-1);
if (!strcmp(codec, "subrip"))
extension = ".srt";
else if (!strcmp(codec, "ass"))
extension = ".ass";
else {
printf("Unsupported subtitle codec: %s.\n", codec);
free(codec);
return (-1);
}
if (!extension)
return (-1);
*substream = (stream) {
NULL,
languageptr ? languageptr->value : NULL,
languageptr ? strdup(languageptr->value) : NULL,
codec,
in_stream->disposition & AV_DISPOSITION_DEFAULT,
in_stream->disposition & AV_DISPOSITION_FORCED,
NULL
};
asprintf(&substream->path, "%s/%s", out_path, substream->language);
if (!substream->path || kmkdir(substream->path, 0733) < 0)
return (-1);
asprintf(&folder_path, "%s/%s", out_path, substream->language);
if (!folder_path)
return (-1);
if (kmkdir(folder_path, 0733) < 0) {
free(folder_path);
return (-1);
}
asprintf(&substream->path, "%s/%s.%s%s%s%s", substream->path,
folder_name,
substream->language,
substream->is_default ? ".default" : "",
substream->is_forced ? ".forced" : "",
extension);
free(folder_path);
if (!substream->path)
return (-1);
return (0);
@@ -110,42 +109,55 @@ void finish_up(AVFormatContext *int_ctx, AVFormatContext **output_list, unsigned
free(output_list);
}
int split_inputfile(AVFormatContext *int_ctx, AVFormatContext **output_list, stream *streams, char *path, const char *out_path)
{
int subcount = 0;
char *folder_name = path_getfolder(path);
if (!folder_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, folder_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(folder_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;
char *folder_name = strchr(path, '/');
char *p;
stream *streams;
if (!folder_name && (folder_name = strdup(folder_name)))
return (NULL);
p = strchr(folder_name, '.');
if (p)
*p = '\0';
if (open_input_context(&int_ctx, path) != 0)
return (NULL);
return (NULL);
*stream_count = int_ctx->nb_streams;
*subtitle_count = 0;
streams = malloc(sizeof(stream) * *stream_count);
streams = calloc(sizeof(stream), *stream_count);
output_list = malloc(sizeof(AVFormatContext *) * *stream_count);
if (!streams || !output_list)
return (NULL);
for (unsigned int i = 0; i < *stream_count; 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, folder_name, out_path) == 0) {
if (copy_subtitle_stream(output_list[i], streams + i, int_ctx, in_stream) == 0) {
*subtitle_count += 1;
continue;
}
}
}
streams[i] = NULLSTREAM;
output_list[i] = NULL;
}
write_data(int_ctx, output_list, *stream_count);
finish_up(int_ctx, output_list, *stream_count);
return (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);
return (NULL);
}
+9 -2
View File
@@ -3,15 +3,22 @@
//
#include <string.h>
#include <stdio.h>
#include "transcoder.h"
#include "stream.h"
int main(int argc, char **argv)
{
unsigned stream_count = 0;
unsigned subtitle_count = 0;
stream *streams;
if (argc == 3 && !strcmp(argv[1], "es"))
extract_subtitles(argv[2], "./", &stream_count, &subtitle_count);
if (argc == 3 && !strcmp(argv[1], "subextract")) {
streams = extract_subtitles(argv[2], ".", &stream_count, &subtitle_count);
free_streams(streams, stream_count);
} else
printf("\nUsage:\n\n\
%s subextr video_path - Test subtitle extractions\n", argv[0]);
return (0);
}