discard errors when parsing ffprobe output, fixes #530 #546

This commit is contained in:
Taner Sener 2022-08-26 07:39:25 +01:00
parent c82f9c8e74
commit be711ac426
8 changed files with 58 additions and 36 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2021 Taner Sener
* Copyright (c) 2018-2022 Taner Sener
*
* This file is part of FFmpegKit.
*
@ -696,7 +696,15 @@ public class FFmpegKitConfig {
final ReturnCode returnCode = new ReturnCode(returnCodeValue);
mediaInformationSession.complete(returnCode);
if (returnCode.isValueSuccess()) {
MediaInformation mediaInformation = MediaInformationJsonParser.fromWithError(mediaInformationSession.getAllLogsAsString(waitTimeout));
List<Log> allLogs = mediaInformationSession.getAllLogs(waitTimeout);
final StringBuilder ffprobeJsonOutput = new StringBuilder();
for (int i = 0, allLogsSize = allLogs.size(); i < allLogsSize; i++) {
Log log = allLogs.get(i);
if (log.getLevel() == Level.AV_LOG_STDERR) {
ffprobeJsonOutput.append(log.getMessage());
}
}
MediaInformation mediaInformation = MediaInformationJsonParser.fromWithError(ffprobeJsonOutput.toString());
mediaInformationSession.setMediaInformation(mediaInformation);
}
} catch (final Exception e) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Taner Sener
* Copyright (c) 2021-2022 Taner Sener
*
* This file is part of FFmpegKit.
*
@ -208,7 +208,7 @@ extern void addSessionToSessionHistory(id<Session> session);
}
- (void)fail:(NSException*)exception {
_failStackTrace = [NSString stringWithFormat:@"%@", [exception callStackSymbols]];
_failStackTrace = [NSString stringWithFormat:@"%@\n%@", [exception userInfo], [exception callStackSymbols]];
_state = SessionStateFailed;
_endTime = [NSDate date];
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2021 Taner Sener
* Copyright (c) 2018-2022 Taner Sener
*
* This file is part of FFmpegKit.
*
@ -998,12 +998,20 @@ int executeFFprobe(long sessionId, NSArray* arguments) {
ReturnCode* returnCode = [[ReturnCode alloc] init:returnCodeValue];
[mediaInformationSession complete:returnCode];
if ([returnCode isValueSuccess]) {
MediaInformation* mediaInformation = [MediaInformationJsonParser from:[mediaInformationSession getAllLogsAsStringWithTimeout:waitTimeout]];
NSArray* allLogs = [mediaInformationSession getAllLogsWithTimeout:waitTimeout];
NSMutableString* ffprobeJsonOutput = [[NSMutableString alloc] init];
for (int i=0; i < [allLogs count]; i++) {
Log* log = [allLogs objectAtIndex:i];
if ([log getLevel] == LevelAVLogStdErr) {
[ffprobeJsonOutput appendString:[log getMessage]];
}
}
MediaInformation* mediaInformation = [MediaInformationJsonParser fromWithError:ffprobeJsonOutput];
[mediaInformationSession setMediaInformation:mediaInformation];
}
} @catch (NSException *exception) {
[mediaInformationSession fail:exception];
NSLog(@"Get media information execute failed: %@.%@", [FFmpegKitConfig argumentsToString:[mediaInformationSession getArguments]], [NSString stringWithFormat:@"%@", [exception callStackSymbols]]);
NSLog(@"Get media information execute failed: %@.%@", [FFmpegKitConfig argumentsToString:[mediaInformationSession getArguments]], [NSString stringWithFormat:@"\n%@\n%@", [exception userInfo], [exception callStackSymbols]]);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2021 Taner Sener
* Copyright (c) 2018-2022 Taner Sener
*
* This file is part of FFmpegKit.
*
@ -37,13 +37,13 @@
+ (MediaInformation*)from:(NSString*)ffprobeJsonOutput;
/**
* Extracts <code>MediaInformation</code> from the given FFprobe json output.
* Extracts <code>MediaInformation</code> from the given FFprobe json output. If a parsing error occurs an NSException
* is thrown.
*
* @param ffprobeJsonOutput FFprobe json output
* @param error error to save the parsing error if a parsing error occurs
* @return created MediaInformation instance
*/
+ (MediaInformation*)from:(NSString*)ffprobeJsonOutput with:(NSError*)error;
+ (MediaInformation*)fromWithError:(NSString*)ffprobeJsonOutput;
@end

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2021 Taner Sener
* Copyright (c) 2018-2022 Taner Sener
*
* This file is part of FFmpegKit.
*
@ -25,21 +25,22 @@ NSString* const MediaInformationJsonParserKeyChapters = @"chapters";
@implementation MediaInformationJsonParser
+ (MediaInformation*)from:(NSString*)ffprobeJsonOutput {
NSError *error;
MediaInformation* mediaInformation = [self from: ffprobeJsonOutput with: error];
if (error != nil) {
NSLog(@"MediaInformation parsing failed: %@.\n", error);
@try {
return [self fromWithError:ffprobeJsonOutput];
} @catch (NSException *exception) {
NSLog(@"MediaInformation parsing failed: %@.\n", [NSString stringWithFormat:@"%@\n%@", [exception userInfo], [exception callStackSymbols]]);
return nil;
}
}
return mediaInformation;
}
+ (MediaInformation*)from:(NSString*)ffprobeJsonOutput with:(NSError*)error {
+ (MediaInformation*)fromWithError:(NSString*)ffprobeJsonOutput {
NSError* error = nil;
NSData *jsonData = [ffprobeJsonOutput dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
if (error != nil || jsonDictionary == nil) {
if (error != nil) {
@throw [NSException exceptionWithName:@"ParsingException" reason:[NSString stringWithFormat:@"%ld",[error code]] userInfo:[error userInfo]];
}
if (jsonDictionary == nil) {
return nil;
}

View File

@ -42,6 +42,7 @@ extern "C" {
#include <condition_variable>
#include <iostream>
#include <fstream>
#include <algorithm>
/**
* Generates ids for named ffmpeg kit pipes.
@ -1035,7 +1036,14 @@ void ffmpegkit::FFmpegKitConfig::getMediaInformationExecute(const std::shared_pt
auto returnCode = std::make_shared<ffmpegkit::ReturnCode>(returnCodeValue);
mediaInformationSession->complete(returnCode);
if (returnCode->isValueSuccess()) {
auto mediaInformation = ffmpegkit::MediaInformationJsonParser::from(mediaInformationSession->getAllLogsAsStringWithTimeout(waitTimeout).c_str());
auto allLogs = mediaInformationSession->getAllLogsWithTimeout(waitTimeout);
std::string ffprobeJsonOutput;
std::for_each(allLogs->cbegin(), allLogs->cend(), [&](std::shared_ptr<ffmpegkit::Log> log) {
if (log->getLevel() == LevelAVLogStdErr) {
ffprobeJsonOutput.append(log->getMessage());
}
});
auto mediaInformation = ffmpegkit::MediaInformationJsonParser::fromWithError(ffprobeJsonOutput.c_str());
mediaInformationSession->setMediaInformation(mediaInformation);
}
} catch(const std::exception& exception) {

View File

@ -29,24 +29,21 @@ static const char* MediaInformationJsonParserKeyStreams = "streams";
static const char* MediaInformationJsonParserKeyChapters = "chapters";
std::shared_ptr<ffmpegkit::MediaInformation> ffmpegkit::MediaInformationJsonParser::from(const std::string& ffprobeJsonOutput) {
std::string error;
std::shared_ptr<ffmpegkit::MediaInformation> mediaInformation = fromWithError(ffprobeJsonOutput, error);
if (mediaInformation == nullptr) {
std::cout << "MediaInformation parsing failed: " << error << std::endl;
try {
return fromWithError(ffprobeJsonOutput);
} catch(const std::exception& exception) {
std::cout << "MediaInformation parsing failed: " << exception.what() << std::endl;
return nullptr;
}
}
return mediaInformation;
}
std::shared_ptr<ffmpegkit::MediaInformation> ffmpegkit::MediaInformationJsonParser::fromWithError(const std::string& ffprobeJsonOutput, std::string& error) {
std::shared_ptr<ffmpegkit::MediaInformation> ffmpegkit::MediaInformationJsonParser::fromWithError(const std::string& ffprobeJsonOutput) {
std::shared_ptr<rapidjson::Document> document = std::make_shared<rapidjson::Document>();
document->Parse(ffprobeJsonOutput.c_str());
if (document->HasParseError()) {
error = GetParseError_En(document->GetParseError());
return nullptr;
throw std::runtime_error(GetParseError_En(document->GetParseError()));
} else {
std::shared_ptr<std::vector<std::shared_ptr<ffmpegkit::StreamInformation>>> streams = std::make_shared<std::vector<std::shared_ptr<ffmpegkit::StreamInformation>>>();
std::shared_ptr<std::vector<std::shared_ptr<ffmpegkit::Chapter>>> chapters = std::make_shared<std::vector<std::shared_ptr<ffmpegkit::Chapter>>>();

View File

@ -40,13 +40,13 @@ namespace ffmpegkit {
static std::shared_ptr<ffmpegkit::MediaInformation> from(const std::string& ffprobeJsonOutput);
/**
* Extracts <code>MediaInformation</code> from the given FFprobe json output.
* Extracts <code>MediaInformation</code> from the given FFprobe json output. If a parsing error occurs an
* std::exception is thrown.
*
* @param ffprobeJsonOutput FFprobe json output
* @param error error to save the parsing error if a parsing error occurs
* @return created MediaInformation instance
*/
static std::shared_ptr<ffmpegkit::MediaInformation> fromWithError(const std::string& ffprobeJsonOutput, std::string& error);
static std::shared_ptr<ffmpegkit::MediaInformation> fromWithError(const std::string& ffprobeJsonOutput);
};