Creating the transmuxer.

This commit is contained in:
Zoe Roux 2019-09-25 22:41:52 +02:00
parent 3c47c88767
commit 604c68721b
5 changed files with 40 additions and 21 deletions

View File

@ -61,8 +61,10 @@ AVStream* copy_stream_to_output(AVFormatContext *outputContext, AVStream *inputS
outputStream->time_base = av_add_q(av_stream_get_codec_timebase(outputStream), AVRational{ 0, 1 }); 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->duration = av_rescale_q(inputStream->duration, inputStream->time_base, outputStream->time_base);
outputStream->disposition = inputStream->disposition; 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); //av_dict_copy(&outputStream->metadata, inputStream->metadata, NULL);
//if (inputStream->nb_side_data) //if (inputStream->nb_side_data)
//{ //{
@ -107,7 +109,7 @@ int open_output_file_for_write(AVFormatContext *outputContext, const char* outpu
return 0; return 0;
} }
void process_packet(AVPacket pkt, AVStream* inputStream, AVStream* outputStream) 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.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.dts = av_rescale_q_rnd(pkt.dts, inputStream->time_base, outputStream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
@ -119,10 +121,6 @@ void process_packet(AVPacket pkt, AVStream* inputStream, AVStream* outputStream)
//Should add goto end;
int Transmux(const char *path, const char *outPath) int Transmux(const char *path, const char *outPath)
{ {
AVFormatContext *inputContext = NULL; AVFormatContext *inputContext = NULL;
@ -138,13 +136,29 @@ int Transmux(const char *path, const char *outPath)
return 1; return 1;
} }
int *streamsMap = new int[inputContext->nb_streams];
int streamCount = 0;
for (unsigned int i = 0; i < inputContext->nb_streams; i++) for (unsigned int i = 0; i < inputContext->nb_streams; i++)
{ {
AVStream *stream = inputContext->streams[i]; AVStream *stream = inputContext->streams[i];
if(stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) //Should support multi-audio on a good format. if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
streamsMap[i] = streamCount;
streamCount++;
if (copy_stream_to_output(outputContext, stream) == NULL) if (copy_stream_to_output(outputContext, stream) == NULL)
return 1; 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)
return 1;
}
else
streamsMap[i] = -1;
}
av_dump_format(outputContext, 0, outPath, true); av_dump_format(outputContext, 0, outPath, true);
if (open_output_file_for_write(outputContext, outPath) != 0) if (open_output_file_for_write(outputContext, outPath) != 0)
@ -153,27 +167,36 @@ int Transmux(const char *path, const char *outPath)
AVPacket pkt; AVPacket pkt;
while (av_read_frame(inputContext, &pkt) == 0) while (av_read_frame(inputContext, &pkt) == 0)
{ {
if (pkt.stream_index >= outputContext->nb_streams) if (pkt.stream_index >= inputContext->nb_streams || streamsMap[pkt.stream_index] < 0)
{
av_packet_unref(&pkt);
continue; continue;
}
AVStream *inputStream = inputContext->streams[pkt.stream_index]; AVStream *inputStream = inputContext->streams[pkt.stream_index];
pkt.stream_index = streamsMap[pkt.stream_index];
AVStream *outputStream = outputContext->streams[pkt.stream_index]; AVStream *outputStream = outputContext->streams[pkt.stream_index];
process_packet(pkt, inputStream, outputStream); process_packet(pkt, inputStream, outputStream);
if (av_interleaved_write_frame(outputContext, &pkt) < 0) if (av_interleaved_write_frame(outputContext, &pkt) < 0)
std::cout << "Error while writing a packet to the output file." << std::endl; std::cout << "Error while writing a packet to the output file." << std::endl;
av_packet_unref(&pkt); av_packet_unref(&pkt);
} }
avformat_close_input(&inputContext);
av_write_trailer(outputContext); av_write_trailer(outputContext);
avformat_close_input(&inputContext);
if (outputContext && !(outputContext->flags & AVFMT_NOFILE)) if (outputContext && !(outputContext->oformat->flags & AVFMT_NOFILE))
avio_closep(&outputContext->pb); avio_closep(&outputContext->pb);
avformat_free_context(outputContext); avformat_free_context(outputContext);
return ret; delete[] streamsMap;
if (ret < 0 && ret != AVERROR_EOF)
return 1;
return 0;
} }

View File

@ -1,8 +1,8 @@
<div id="root"> <div id="root">
<div class="player"> <div class="player">
<video id="player" poster="backdrop/{{this.item.showSlug}}" autoplay muted (click)="tooglePlayback()" class="video-js"> <video id="player" poster="backdrop/{{this.item.showSlug}}" autoplay muted (click)="tooglePlayback()" class="video-js">
<source src="/api/video/{{this.item.link}}" /> <source src="/video/{{this.item.link}}" />
<source src="/api/video/transmux/{{this.item.link}}" type="video/mp4" /> <source src="/video/transmux/{{this.item.link}}" type="video/mp4" />
</video> </video>
</div> </div>

View File

@ -1,17 +1,13 @@
using Kyoo.InternalAPI; using Kyoo.InternalAPI;
using Kyoo.Models; using Kyoo.Models;
using Kyoo.Models.Watch;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
[Route("api/[controller]")] [Route("[controller]")]
[ApiController] [ApiController]
public class SubtitleController : ControllerBase public class SubtitleController : ControllerBase
{ {

View File

@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Mvc;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
[Route("api/[controller]")] [Route("[controller]")]
[ApiController] [ApiController]
public class VideoController : ControllerBase public class VideoController : ControllerBase
{ {

View File

@ -78,7 +78,7 @@ namespace Kyoo.Models
language = "fra"; language = "fra";
DisplayName = CultureInfo.GetCultures(CultureTypes.NeutralCultures).Where(x => x.ThreeLetterISOLanguageName == language).FirstOrDefault()?.DisplayName ?? language; DisplayName = CultureInfo.GetCultures(CultureTypes.NeutralCultures).Where(x => x.ThreeLetterISOLanguageName == language).FirstOrDefault()?.DisplayName ?? language;
Link = "/api/subtitle/" + episodeSlug + "." + Language; Link = "/subtitle/" + episodeSlug + "." + Language;
if (IsForced) if (IsForced)
{ {