Adding an option dictionary for the dash creation.

This commit is contained in:
Zoe Roux
2019-11-09 22:01:20 +01:00
parent 05d297201e
commit 6270aac959
8 changed files with 79 additions and 79 deletions
-37
View File
@@ -1,37 +0,0 @@
#pragma once
#ifdef TRANSCODER_EXPORTS
#define API __declspec(dllexport)
#else
#define API __declspec(dllimport)
#endif
#include <iostream>
#include <sstream>
extern "C" struct Stream
{
char *title;
char *language;
char *codec;
bool isDefault;
bool isForced;
char *path;
Stream()
: title(NULL), language(NULL), codec(NULL), isDefault(NULL), isForced(NULL), path(NULL) {}
Stream(const char* title, const char* languageCode, const char* codec, bool isDefault, bool isForced)
: title(NULL), language(NULL), codec(NULL), isDefault(isDefault), isForced(isForced), path(NULL)
{
if(title != NULL)
this->title= strdup(title);
if (languageCode != NULL)
language = strdup(languageCode);
else
language = strdup("und");
if (codec != NULL)
this->codec = strdup(codec);
}
};
+56 -52
View File
@@ -8,13 +8,14 @@ int Init()
return sizeof(Stream);
}
int transmux(const char *path, const char *out_path)
int transmux(const char *path, const char *out_path, const char *get_uri)
{
AVFormatContext *in_ctx = NULL;
AVFormatContext* out_ctx = NULL;
AVStream* stream;
AVFormatContext *out_ctx = NULL;
AVStream *stream;
AVPacket pkt;
int* stream_map;
AVDictionary *options = NULL;
int *stream_map;
int stream_count;
int ret = 0;
@@ -52,7 +53,10 @@ int transmux(const char *path, const char *out_path)
}
av_dump_format(out_ctx, 0, out_path, true);
if (open_output_file_for_write(out_ctx, out_path) != 0)
av_dict_set(&options, "init_seg_name", ((std::string)get_uri + (std::string)"/init-stream$RepresentationID$.m4s").c_str(), AV_DICT_DONT_STRDUP_VAL);
av_dict_set(&options, "media_seg_name", ((std::string)get_uri + (std::string)"/chunk-stream$RepresentationID$-$Number%05d$.m4s").c_str(), AV_DICT_DONT_STRDUP_VAL);
if (open_output_file_for_write(out_ctx, out_path, &options) != 0)
return 1;
while (av_read_frame(in_ctx, &pkt) == 0)
@@ -91,8 +95,8 @@ int transmux(const char *path, const char *out_path)
Stream *extract_subtitles(const char *path, const char *out_path, int *stream_count, int *subtitle_count)
{
AVFormatContext *int_ctx = NULL;
AVFormatContext** output_list;
Stream* streams;
AVFormatContext **output_list;
Stream *streams;
AVPacket pkt;
unsigned int out_count;
@@ -104,51 +108,51 @@ Stream *extract_subtitles(const char *path, const char *out_path, int *stream_co
streams = new Stream[*stream_count];
out_count = int_ctx->nb_streams;
output_list = new AVFormatContext*[out_count];
output_list = new AVFormatContext *[out_count];
//Initialize output and set headers.
for (unsigned int i = 0; i < int_ctx->nb_streams; i++)
{
AVStream *inputStream = int_ctx->streams[i];
const AVCodecParameters *inputCodecpar = inputStream->codecpar;
AVStream *in_stream = int_ctx->streams[i];
const AVCodecParameters *in_codecpar = in_stream->codecpar;
if (inputCodecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
if (in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
output_list[i] = NULL;
else
{
*subtitle_count += 1;
AVDictionaryEntry *languagePtr = av_dict_get(inputStream->metadata, "language", NULL, 0);
AVDictionaryEntry *languageptr = av_dict_get(in_stream->metadata, "language", NULL, 0);
//Get metadata for file name
streams[i] = Stream(NULL, //title
languagePtr ? languagePtr->value : NULL, //language
avcodec_get_name(inputCodecpar->codec_id), //format
inputStream->disposition & AV_DISPOSITION_DEFAULT, //isDefault
inputStream->disposition & AV_DISPOSITION_FORCED); //isForced
languageptr ? languageptr->value : NULL, //language
avcodec_get_name(in_codecpar->codec_id), //format
in_stream->disposition & AV_DISPOSITION_DEFAULT, //isDefault
in_stream->disposition & AV_DISPOSITION_FORCED); //isForced
//Create the language subfolder
std::stringstream outStream;
outStream << out_path << (char)std::filesystem::path::preferred_separator << streams[i].language;
std::filesystem::create_directory(outStream.str());
std::stringstream out_strstream;
out_strstream << out_path << (char)std::filesystem::path::preferred_separator << streams[i].language;
std::filesystem::create_directory(out_strstream.str());
//Get file name
std::string fileName(path);
size_t lastSeparator = fileName.find_last_of((char)std::filesystem::path::preferred_separator);
fileName = fileName.substr(lastSeparator, fileName.find_last_of('.') - lastSeparator);
std::string file_name(path);
size_t last_separator = file_name.find_last_of((char)std::filesystem::path::preferred_separator);
file_name = file_name.substr(last_separator, file_name.find_last_of('.') - last_separator);
//Construct output file name
outStream << fileName << "." << streams[i].language;
out_strstream << file_name << "." << streams[i].language;
if (streams[i].isDefault)
outStream << ".default";
if (streams[i].isForced)
outStream << ".forced";
if (streams[i].is_default)
out_strstream << ".default";
if (streams[i].is_forced)
out_strstream << ".forced";
if (strcmp(streams[i].codec, "subrip") == 0)
outStream << ".srt";
out_strstream << ".srt";
else if (strcmp(streams[i].codec, "ass") == 0)
outStream << ".ass";
out_strstream << ".ass";
else
{
std::cout << "Unsupported subtitle codec: " << streams[i].codec << std::endl;
@@ -156,36 +160,36 @@ Stream *extract_subtitles(const char *path, const char *out_path, int *stream_co
continue;
}
streams[i].path = strdup(outStream.str().c_str());
streams[i].path = strdup(out_strstream.str().c_str());
std::cout << "Stream #" << i << "(" << streams[i].language << "), stream type: " << inputCodecpar->codec_type << " codec: " << streams[i].codec << std::endl;
std::cout << "Stream #" << i << "(" << streams[i].language << "), stream type: " << in_codecpar->codec_type << " codec: " << streams[i].codec << std::endl;
AVFormatContext *outputContext = NULL;
if (avformat_alloc_output_context2(&outputContext, NULL, NULL, streams[i].path) < 0)
AVFormatContext *out_ctx = NULL;
if (avformat_alloc_output_context2(&out_ctx, NULL, NULL, streams[i].path) < 0)
{
std::cout << "Error: Couldn't create an output file." << std::endl;
continue;
}
av_dict_copy(&outputContext->metadata, int_ctx->metadata, NULL);
av_dict_copy(&out_ctx->metadata, int_ctx->metadata, NULL);
AVStream *outputStream = copy_stream_to_output(outputContext, inputStream);
if (outputStream == NULL)
AVStream *out_stream = copy_stream_to_output(out_ctx, in_stream);
if (out_stream == NULL)
goto end;
av_dump_format(outputContext, 0, streams[i].path, true);
av_dump_format(out_ctx, 0, streams[i].path, true);
if (open_output_file_for_write(outputContext, streams[i].path) != 0)
if (open_output_file_for_write(out_ctx, streams[i].path, NULL) != 0)
goto end;
output_list[i] = outputContext;
output_list[i] = out_ctx;
if (false)
{
end:
if (outputContext && !(outputContext->flags & AVFMT_NOFILE))
avio_closep(&outputContext->pb);
avformat_free_context(outputContext);
if (out_ctx && !(out_ctx->flags & AVFMT_NOFILE))
avio_closep(&out_ctx->pb);
avformat_free_context(out_ctx);
output_list[i] = nullptr;
std::cout << "An error occured, cleaning up th output context for the stream #" << i << std::endl;
@@ -199,17 +203,17 @@ Stream *extract_subtitles(const char *path, const char *out_path, int *stream_co
if ((unsigned int)pkt.stream_index >= out_count)
continue;
AVFormatContext *outputContext = output_list[pkt.stream_index];
if (outputContext == nullptr)
AVFormatContext *out_ctx = output_list[pkt.stream_index];
if (out_ctx == nullptr)
{
av_packet_unref(&pkt);
continue;
}
process_packet(pkt, int_ctx->streams[pkt.stream_index], outputContext->streams[0]);
process_packet(pkt, int_ctx->streams[pkt.stream_index], out_ctx->streams[0]);
pkt.stream_index = 0;
if (av_interleaved_write_frame(outputContext, &pkt) < 0)
if (av_interleaved_write_frame(out_ctx, &pkt) < 0)
std::cout << "Error while writing a packet to the output file." << std::endl;
av_packet_unref(&pkt);
@@ -219,16 +223,16 @@ Stream *extract_subtitles(const char *path, const char *out_path, int *stream_co
for (unsigned int i = 0; i < out_count; i++)
{
AVFormatContext *outputContext = output_list[i];
AVFormatContext *out_ctx = output_list[i];
if (outputContext == NULL)
if (out_ctx == NULL)
continue;
av_write_trailer(outputContext);
av_write_trailer(out_ctx);
if (outputContext && !(outputContext->flags & AVFMT_NOFILE))
avio_closep(&outputContext->pb);
avformat_free_context(outputContext);
if (out_ctx && !(out_ctx->flags & AVFMT_NOFILE))
avio_closep(&out_ctx->pb);
avformat_free_context(out_ctx);
}
delete[] output_list;
-19
View File
@@ -1,19 +0,0 @@
#pragma once
#ifdef TRANSCODER_EXPORTS
#define API __declspec(dllexport)
#else
#define API __declspec(dllimport)
#endif
#include <iostream>
#include "Stream.h"
extern "C" API int Init();
extern "C" API int transmux(const char *path, const char *outPath);
//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.
extern "C" API Stream* extract_subtitles(const char *path, const char *outPath, int *streamCount, int *subtitleCount);
extern "C" API void free_memory(Stream *streamsPtr);
+14 -14
View File
@@ -1,25 +1,25 @@
#include "helper.h"
#include <iostream>
int open_input_context(AVFormatContext** inputContext, const char* path)
int open_input_context(AVFormatContext **in_ctx, const char *path)
{
if (avformat_open_input(inputContext, path, NULL, NULL))
if (avformat_open_input(in_ctx, path, NULL, NULL))
{
std::cout << "Error: Can't open the file at " << path << std::endl;
return 1;
}
if (avformat_find_stream_info(*inputContext, NULL) < 0)
if (avformat_find_stream_info(*in_ctx, NULL) < 0)
{
std::cout << "Error: Could't find streams informations for the file at " << path << std::endl;
return 1;
}
av_dump_format(*inputContext, 0, path, false);
av_dump_format(*in_ctx, 0, path, false);
return 0;
}
AVStream* copy_stream_to_output(AVFormatContext* out_ctx, AVStream* in_stream)
AVStream *copy_stream_to_output(AVFormatContext *out_ctx, AVStream *in_stream)
{
AVStream* out_stream = avformat_new_stream(out_ctx, NULL);
AVStream *out_stream = avformat_new_stream(out_ctx, NULL);
if (out_stream == NULL)
{
@@ -33,7 +33,7 @@ AVStream* copy_stream_to_output(AVFormatContext* out_ctx, AVStream* in_stream)
}
out_stream->codecpar->codec_tag = 0;
avformat_transfer_internal_stream_timing_info(out_ctx->oformat, out_stream, in_stream, AVTimebaseSource::AVFMT_TBCF_AUTO);
out_stream->time_base = av_add_q(av_stream_get_codec_timebase(out_stream), AVRational{ 0, 1 });
out_stream->time_base = av_add_q(av_stream_get_codec_timebase(out_stream), AVRational {0, 1});
out_stream->duration = av_rescale_q(in_stream->duration, in_stream->time_base, out_stream->time_base);
out_stream->disposition = in_stream->disposition;
out_stream->avg_frame_rate = in_stream->avg_frame_rate;
@@ -46,27 +46,27 @@ constexpr enum AVRounding operator |(const enum AVRounding a, const enum AVRound
return (enum AVRounding)(uint32_t(a) | uint32_t(b));
}
int open_output_file_for_write(AVFormatContext* outputContext, const char* outputPath)
int open_output_file_for_write(AVFormatContext *out_ctx, const char *out_path, AVDictionary **options)
{
if (!(outputContext->flags & AVFMT_NOFILE))
if (!(out_ctx->flags & AVFMT_NOFILE))
{
if (avio_open(&outputContext->pb, outputPath, AVIO_FLAG_WRITE) < 0)
if (avio_open(&out_ctx->pb, out_path, AVIO_FLAG_WRITE) < 0)
{
std::cout << "Error: Couldn't open file at " << outputPath << std::endl;
std::cout << "Error: Couldn't open file at " << out_path << std::endl;
return 1;
}
}
else
std::cout << "Output flag set to AVFMT_NOFILE." << std::endl;
if (avformat_write_header(outputContext, NULL) < 0)
if (avformat_write_header(out_ctx, options) < 0)
{
std::cout << "Error: Couldn't write headers to file at " << outputPath << std::endl;
std::cout << "Error: Couldn't write headers to file at " << out_path << std::endl;
return 1;
}
return 0;
}
void process_packet(AVPacket& pkt, AVStream* in_stream, AVStream* out_stream)
void process_packet(AVPacket &pkt, AVStream *in_stream, AVStream *out_stream)
{
pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
-11
View File
@@ -1,11 +0,0 @@
#pragma once
extern "C"
{
#include <libavformat/avformat.h>
#include <libavutil/dict.h>
#include <libavutil/timestamp.h>
}
int open_input_context(AVFormatContext** inputContext, const char* path);
AVStream* copy_stream_to_output(AVFormatContext* out_ctx, AVStream* in_stream);
int open_output_file_for_write(AVFormatContext* out_ctx, const char* out_path);
void process_packet(AVPacket& pkt, AVStream* in_stream, AVStream* out_stream);