mirror of
https://github.com/zoriya/Kyoo.git
synced 2026-06-05 13:55:18 -04:00
Starting to implement dash streaming.
This commit is contained in:
@@ -24,14 +24,14 @@ extern "C" struct Stream
|
||||
: title(NULL), language(NULL), codec(NULL), isDefault(isDefault), isForced(isForced), path(NULL)
|
||||
{
|
||||
if(title != NULL)
|
||||
this->title= _strdup(title);
|
||||
this->title= strdup(title);
|
||||
|
||||
if (languageCode != NULL)
|
||||
language = _strdup(languageCode);
|
||||
language = strdup(languageCode);
|
||||
else
|
||||
language = _strdup("und");
|
||||
language = strdup("und");
|
||||
|
||||
if (codec != NULL)
|
||||
this->codec = _strdup(codec);
|
||||
this->codec = strdup(codec);
|
||||
}
|
||||
};
|
||||
@@ -1,197 +1,85 @@
|
||||
#include "pch.h"
|
||||
#include <filesystem>
|
||||
#include <sstream>
|
||||
#include "Transcoder.h"
|
||||
|
||||
//ffmpeg imports
|
||||
extern "C"
|
||||
{
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/dict.h>
|
||||
#include <libavutil/timestamp.h>
|
||||
}
|
||||
|
||||
constexpr enum AVRounding operator |(const enum AVRounding a, const enum AVRounding b)
|
||||
{
|
||||
return (enum AVRounding)(uint32_t(a) | uint32_t(b));
|
||||
}
|
||||
#include "helper.h"
|
||||
|
||||
int Init()
|
||||
{
|
||||
return sizeof(Stream);
|
||||
}
|
||||
|
||||
|
||||
#pragma region InternalProcess
|
||||
int open_input_context(AVFormatContext **inputContext, const char *path)
|
||||
int transmux(const char *path, const char *out_path)
|
||||
{
|
||||
if (avformat_open_input(inputContext, 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)
|
||||
{
|
||||
std::cout << "Error: Could't find streams informations for the file at " << path << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
av_dump_format(*inputContext, 0, path, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
AVStream* copy_stream_to_output(AVFormatContext *outputContext, AVStream *inputStream)
|
||||
{
|
||||
AVStream *outputStream = avformat_new_stream(outputContext, NULL);
|
||||
if (outputStream == NULL)
|
||||
{
|
||||
std::cout << "Error: Couldn't create stream." << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (avcodec_parameters_copy(outputStream->codecpar, inputStream->codecpar) < 0)
|
||||
{
|
||||
std::cout << "Error: Couldn't copy parameters to the output file." << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
outputStream->codecpar->codec_tag = 0;
|
||||
|
||||
avformat_transfer_internal_stream_timing_info(outputContext->oformat, outputStream, inputStream, AVTimebaseSource::AVFMT_TBCF_AUTO);
|
||||
outputStream->time_base = av_add_q(av_stream_get_codec_timebase(outputStream), AVRational{ 0, 1 });
|
||||
outputStream->duration = av_rescale_q(inputStream->duration, inputStream->time_base, outputStream->time_base);
|
||||
outputStream->disposition = inputStream->disposition;
|
||||
outputStream->avg_frame_rate = inputStream->avg_frame_rate;
|
||||
outputStream->r_frame_rate = inputStream->r_frame_rate;
|
||||
|
||||
//av_dict_copy(&outputStream->metadata, inputStream->metadata, NULL);
|
||||
|
||||
//if (inputStream->nb_side_data)
|
||||
//{
|
||||
// for (int i = 0; i < inputStream->nb_side_data; i++)
|
||||
// {
|
||||
// std::cout << "Copying side packet #" << i << std::endl;
|
||||
|
||||
// AVPacketSideData *sidePkt = &inputStream->side_data[i];
|
||||
// uint8_t *newPkt = av_stream_new_side_data(outputStream, sidePkt->type, sidePkt->size);
|
||||
// if (newPkt == NULL)
|
||||
// {
|
||||
// std::cout << "Error copying side package." << std::endl;
|
||||
// //Should handle return here
|
||||
// return;
|
||||
// }
|
||||
// memcpy(newPkt, sidePkt->data, sidePkt->size);
|
||||
// }
|
||||
//}
|
||||
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
int open_output_file_for_write(AVFormatContext *outputContext, const char* outputPath)
|
||||
{
|
||||
if (!(outputContext->flags & AVFMT_NOFILE))
|
||||
{
|
||||
if (avio_open(&outputContext->pb, outputPath, AVIO_FLAG_WRITE) < 0)
|
||||
{
|
||||
std::cout << "Error: Couldn't open file at " << outputPath << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
std::cout << "Output flag set to AVFMT_NOFILE." << std::endl;
|
||||
|
||||
if (avformat_write_header(outputContext, NULL) < 0)
|
||||
{
|
||||
std::cout << "Error: Couldn't write headers to file at " << outputPath << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void process_packet(AVPacket &pkt, AVStream* inputStream, AVStream* outputStream)
|
||||
{
|
||||
pkt.pts = av_rescale_q_rnd(pkt.pts, inputStream->time_base, outputStream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
|
||||
pkt.dts = av_rescale_q_rnd(pkt.dts, inputStream->time_base, outputStream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
|
||||
pkt.duration = av_rescale_q(pkt.duration, inputStream->time_base, outputStream->time_base);
|
||||
pkt.pos = -1;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
|
||||
|
||||
|
||||
int Transmux(const char *path, const char *outPath)
|
||||
{
|
||||
AVFormatContext *inputContext = NULL;
|
||||
AVFormatContext *in_ctx = NULL;
|
||||
AVFormatContext* out_ctx = NULL;
|
||||
AVStream* stream;
|
||||
AVPacket pkt;
|
||||
int* stream_map;
|
||||
int stream_count;
|
||||
int ret = 0;
|
||||
|
||||
if (open_input_context(&inputContext, path) != 0)
|
||||
if (open_input_context(&in_ctx, path) != 0)
|
||||
return 1;
|
||||
|
||||
AVFormatContext *outputContext = NULL;
|
||||
if (avformat_alloc_output_context2(&outputContext, NULL, NULL, outPath) < 0)
|
||||
if (avformat_alloc_output_context2(&out_ctx, NULL, NULL, out_path) < 0)
|
||||
{
|
||||
std::cout << "Error: Couldn't create an output file." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int *streamsMap = new int[inputContext->nb_streams];
|
||||
int streamCount = 0;
|
||||
stream_map = new int[in_ctx->nb_streams];
|
||||
stream_count = 0;
|
||||
|
||||
for (unsigned int i = 0; i < inputContext->nb_streams; i++)
|
||||
for (unsigned int i = 0; i < in_ctx->nb_streams; i++)
|
||||
{
|
||||
AVStream *stream = inputContext->streams[i];
|
||||
stream = in_ctx->streams[i];
|
||||
if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||
{
|
||||
streamsMap[i] = streamCount;
|
||||
streamCount++;
|
||||
if (copy_stream_to_output(outputContext, stream) == NULL)
|
||||
stream_map[i] = stream_count;
|
||||
stream_count++;
|
||||
if (copy_stream_to_output(out_ctx, stream) == NULL)
|
||||
return 1;
|
||||
}
|
||||
else if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) //Should support multi-audio on a good format.
|
||||
{
|
||||
streamsMap[i] = streamCount;
|
||||
streamCount++;
|
||||
if (copy_stream_to_output(outputContext, stream) == NULL)
|
||||
stream_map[i] = stream_count;
|
||||
stream_count++;
|
||||
if (copy_stream_to_output(out_ctx, stream) == NULL)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
streamsMap[i] = -1;
|
||||
stream_map[i] = -1;
|
||||
}
|
||||
|
||||
av_dump_format(outputContext, 0, outPath, true);
|
||||
if (open_output_file_for_write(outputContext, outPath) != 0)
|
||||
av_dump_format(out_ctx, 0, out_path, true);
|
||||
if (open_output_file_for_write(out_ctx, out_path) != 0)
|
||||
return 1;
|
||||
|
||||
AVPacket pkt;
|
||||
while (av_read_frame(inputContext, &pkt) == 0)
|
||||
while (av_read_frame(in_ctx, &pkt) == 0)
|
||||
{
|
||||
if (pkt.stream_index >= inputContext->nb_streams || streamsMap[pkt.stream_index] < 0)
|
||||
if ((unsigned int)pkt.stream_index >= in_ctx->nb_streams || stream_map[pkt.stream_index] < 0)
|
||||
{
|
||||
av_packet_unref(&pkt);
|
||||
continue;
|
||||
}
|
||||
|
||||
AVStream *inputStream = inputContext->streams[pkt.stream_index];
|
||||
pkt.stream_index = streamsMap[pkt.stream_index];
|
||||
AVStream *outputStream = outputContext->streams[pkt.stream_index];
|
||||
stream = in_ctx->streams[pkt.stream_index];
|
||||
pkt.stream_index = stream_map[pkt.stream_index];
|
||||
process_packet(pkt, stream, out_ctx->streams[pkt.stream_index]);
|
||||
|
||||
process_packet(pkt, inputStream, outputStream);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
av_write_trailer(outputContext);
|
||||
avformat_close_input(&inputContext);
|
||||
av_write_trailer(out_ctx);
|
||||
avformat_close_input(&in_ctx);
|
||||
|
||||
if (outputContext && !(outputContext->oformat->flags & AVFMT_NOFILE))
|
||||
avio_closep(&outputContext->pb);
|
||||
avformat_free_context(outputContext);
|
||||
delete[] streamsMap;
|
||||
if (out_ctx && !(out_ctx->oformat->flags & AVFMT_NOFILE))
|
||||
avio_closep(&out_ctx->pb);
|
||||
avformat_free_context(out_ctx);
|
||||
delete[] stream_map;
|
||||
|
||||
if (ret < 0 && ret != AVERROR_EOF)
|
||||
return 1;
|
||||
@@ -200,31 +88,35 @@ int Transmux(const char *path, const char *outPath)
|
||||
}
|
||||
|
||||
|
||||
Stream *ExtractSubtitles(const char *path, const char *outPath, int *streamCount, int *subtitleCount)
|
||||
Stream *extract_subtitles(const char *path, const char *out_path, int *stream_count, int *subtitle_count)
|
||||
{
|
||||
AVFormatContext *inputContext = NULL;
|
||||
AVFormatContext *int_ctx = NULL;
|
||||
AVFormatContext** output_list;
|
||||
Stream* streams;
|
||||
AVPacket pkt;
|
||||
unsigned int out_count;
|
||||
|
||||
if (open_input_context(&inputContext, path) != 0)
|
||||
if (open_input_context(&int_ctx, path) != 0)
|
||||
return nullptr;
|
||||
|
||||
*streamCount = inputContext->nb_streams;
|
||||
*subtitleCount = 0;
|
||||
Stream *streams = new Stream[*streamCount];
|
||||
*stream_count = int_ctx->nb_streams;
|
||||
*subtitle_count = 0;
|
||||
streams = new Stream[*stream_count];
|
||||
|
||||
const unsigned int outputCount = inputContext->nb_streams;
|
||||
AVFormatContext **outputList = new AVFormatContext*[outputCount];
|
||||
out_count = int_ctx->nb_streams;
|
||||
output_list = new AVFormatContext*[out_count];
|
||||
|
||||
//Initialize output and set headers.
|
||||
for (unsigned int i = 0; i < inputContext->nb_streams; i++)
|
||||
for (unsigned int i = 0; i < int_ctx->nb_streams; i++)
|
||||
{
|
||||
AVStream *inputStream = inputContext->streams[i];
|
||||
AVStream *inputStream = int_ctx->streams[i];
|
||||
const AVCodecParameters *inputCodecpar = inputStream->codecpar;
|
||||
|
||||
if (inputCodecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
|
||||
outputList[i] = NULL;
|
||||
output_list[i] = NULL;
|
||||
else
|
||||
{
|
||||
*subtitleCount += 1;
|
||||
*subtitle_count += 1;
|
||||
|
||||
AVDictionaryEntry *languagePtr = av_dict_get(inputStream->metadata, "language", NULL, 0);
|
||||
|
||||
@@ -237,7 +129,7 @@ Stream *ExtractSubtitles(const char *path, const char *outPath, int *streamCount
|
||||
|
||||
//Create the language subfolder
|
||||
std::stringstream outStream;
|
||||
outStream << outPath << (char)std::filesystem::path::preferred_separator << streams[i].language;
|
||||
outStream << out_path << (char)std::filesystem::path::preferred_separator << streams[i].language;
|
||||
std::filesystem::create_directory(outStream.str());
|
||||
|
||||
//Get file name
|
||||
@@ -260,11 +152,11 @@ Stream *ExtractSubtitles(const char *path, const char *outPath, int *streamCount
|
||||
else
|
||||
{
|
||||
std::cout << "Unsupported subtitle codec: " << streams[i].codec << std::endl;
|
||||
outputList[i] = NULL;
|
||||
output_list[i] = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
streams[i].path = _strdup(outStream.str().c_str());
|
||||
streams[i].path = strdup(outStream.str().c_str());
|
||||
|
||||
std::cout << "Stream #" << i << "(" << streams[i].language << "), stream type: " << inputCodecpar->codec_type << " codec: " << streams[i].codec << std::endl;
|
||||
|
||||
@@ -275,7 +167,7 @@ Stream *ExtractSubtitles(const char *path, const char *outPath, int *streamCount
|
||||
continue;
|
||||
}
|
||||
|
||||
av_dict_copy(&outputContext->metadata, inputContext->metadata, NULL);
|
||||
av_dict_copy(&outputContext->metadata, int_ctx->metadata, NULL);
|
||||
|
||||
AVStream *outputStream = copy_stream_to_output(outputContext, inputStream);
|
||||
if (outputStream == NULL)
|
||||
@@ -286,7 +178,7 @@ Stream *ExtractSubtitles(const char *path, const char *outPath, int *streamCount
|
||||
if (open_output_file_for_write(outputContext, streams[i].path) != 0)
|
||||
goto end;
|
||||
|
||||
outputList[i] = outputContext;
|
||||
output_list[i] = outputContext;
|
||||
|
||||
if (false)
|
||||
{
|
||||
@@ -295,30 +187,27 @@ Stream *ExtractSubtitles(const char *path, const char *outPath, int *streamCount
|
||||
avio_closep(&outputContext->pb);
|
||||
avformat_free_context(outputContext);
|
||||
|
||||
outputList[i] = nullptr;
|
||||
output_list[i] = nullptr;
|
||||
std::cout << "An error occured, cleaning up th output context for the stream #" << i << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Write subtitle data to files.
|
||||
AVPacket pkt;
|
||||
while (av_read_frame(inputContext, &pkt) == 0)
|
||||
while (av_read_frame(int_ctx, &pkt) == 0)
|
||||
{
|
||||
if (pkt.stream_index >= outputCount)
|
||||
if ((unsigned int)pkt.stream_index >= out_count)
|
||||
continue;
|
||||
|
||||
AVFormatContext *outputContext = outputList[pkt.stream_index];
|
||||
AVFormatContext *outputContext = output_list[pkt.stream_index];
|
||||
if (outputContext == nullptr)
|
||||
{
|
||||
av_packet_unref(&pkt);
|
||||
continue;
|
||||
}
|
||||
|
||||
AVStream *inputStream = inputContext->streams[pkt.stream_index];
|
||||
AVStream *outputStream = outputContext->streams[0];
|
||||
|
||||
process_packet(pkt, int_ctx->streams[pkt.stream_index], outputContext->streams[0]);
|
||||
pkt.stream_index = 0;
|
||||
process_packet(pkt, inputStream, outputStream);
|
||||
|
||||
if (av_interleaved_write_frame(outputContext, &pkt) < 0)
|
||||
std::cout << "Error while writing a packet to the output file." << std::endl;
|
||||
@@ -326,11 +215,11 @@ Stream *ExtractSubtitles(const char *path, const char *outPath, int *streamCount
|
||||
av_packet_unref(&pkt);
|
||||
}
|
||||
|
||||
avformat_close_input(&inputContext);
|
||||
avformat_close_input(&int_ctx);
|
||||
|
||||
for (unsigned int i = 0; i < outputCount; i++)
|
||||
for (unsigned int i = 0; i < out_count; i++)
|
||||
{
|
||||
AVFormatContext *outputContext = outputList[i];
|
||||
AVFormatContext *outputContext = output_list[i];
|
||||
|
||||
if (outputContext == NULL)
|
||||
continue;
|
||||
@@ -342,11 +231,11 @@ Stream *ExtractSubtitles(const char *path, const char *outPath, int *streamCount
|
||||
avformat_free_context(outputContext);
|
||||
}
|
||||
|
||||
delete[] outputList;
|
||||
delete[] output_list;
|
||||
return streams;
|
||||
}
|
||||
|
||||
void FreeMemory(Stream *streamsPtr)
|
||||
void free_memory(Stream *stream_ptr)
|
||||
{
|
||||
delete[] streamsPtr;
|
||||
delete[] stream_ptr;
|
||||
}
|
||||
@@ -11,11 +11,9 @@
|
||||
|
||||
extern "C" API int Init();
|
||||
|
||||
extern "C" API int Transmux(const char *path, const char *outPath);
|
||||
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* ExtractSubtitles(const char *path, const char *outPath, int *streamCount, int *subtitleCount);
|
||||
extern "C" API Stream* extract_subtitles(const char *path, const char *outPath, int *streamCount, int *subtitleCount);
|
||||
|
||||
extern "C" API void FreeMemory(Stream *streamsPtr);
|
||||
|
||||
extern "C" API Stream* TestMemory(const char *path, const char *outPath, int *streamCount, int *subtitleCount);
|
||||
extern "C" API void free_memory(Stream *streamsPtr);
|
||||
@@ -1,19 +0,0 @@
|
||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "pch.h"
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files
|
||||
#include <windows.h>
|
||||
@@ -0,0 +1,75 @@
|
||||
#include "helper.h"
|
||||
#include <iostream>
|
||||
|
||||
int open_input_context(AVFormatContext** inputContext, const char* path)
|
||||
{
|
||||
if (avformat_open_input(inputContext, 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)
|
||||
{
|
||||
std::cout << "Error: Could't find streams informations for the file at " << path << std::endl;
|
||||
return 1;
|
||||
}
|
||||
av_dump_format(*inputContext, 0, path, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
AVStream* copy_stream_to_output(AVFormatContext* out_ctx, AVStream* in_stream)
|
||||
{
|
||||
AVStream* out_stream = avformat_new_stream(out_ctx, NULL);
|
||||
|
||||
if (out_stream == NULL)
|
||||
{
|
||||
std::cout << "Error: Couldn't create stream." << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
if (avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar) < 0)
|
||||
{
|
||||
std::cout << "Error: Couldn't copy parameters to the output file." << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
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->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;
|
||||
out_stream->r_frame_rate = in_stream->r_frame_rate;
|
||||
return out_stream;
|
||||
}
|
||||
|
||||
constexpr enum AVRounding operator |(const enum AVRounding a, const enum AVRounding b)
|
||||
{
|
||||
return (enum AVRounding)(uint32_t(a) | uint32_t(b));
|
||||
}
|
||||
|
||||
int open_output_file_for_write(AVFormatContext* outputContext, const char* outputPath)
|
||||
{
|
||||
if (!(outputContext->flags & AVFMT_NOFILE))
|
||||
{
|
||||
if (avio_open(&outputContext->pb, outputPath, AVIO_FLAG_WRITE) < 0)
|
||||
{
|
||||
std::cout << "Error: Couldn't open file at " << outputPath << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
std::cout << "Output flag set to AVFMT_NOFILE." << std::endl;
|
||||
if (avformat_write_header(outputContext, NULL) < 0)
|
||||
{
|
||||
std::cout << "Error: Couldn't write headers to file at " << outputPath << std::endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
|
||||
pkt.pos = -1;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#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);
|
||||
@@ -1,5 +0,0 @@
|
||||
// pch.cpp: source file corresponding to the pre-compiled header
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
|
||||
@@ -1,14 +0,0 @@
|
||||
// pch.h: This is a precompiled header file.
|
||||
// Files listed below are compiled only once, improving build performance for future builds.
|
||||
// This also affects IntelliSense performance, including code completion and many code browsing features.
|
||||
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
|
||||
// Do not add files here that you will be updating frequently as this negates the performance advantage.
|
||||
|
||||
#ifndef PCH_H
|
||||
#define PCH_H
|
||||
|
||||
// add headers that you want to pre-compile here
|
||||
#include "framework.h"
|
||||
#include <iostream>
|
||||
|
||||
#endif //PCH_H
|
||||
Reference in New Issue
Block a user