HandBrake/libhb/batch.c

269 lines
5.9 KiB
C
Raw Normal View History

/* batch.c
2025-01-22 09:11:40 +01:00
Copyright (c) 2003-2025 HandBrake Team
This file is part of the HandBrake source code
Homepage: <http://handbrake.fr/>.
It may be used under the terms of the GNU General Public License v2.
For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
*/
#include "handbrake/handbrake.h"
#include "handbrake/lang.h"
struct hb_batch_s
{
char * path;
hb_list_t * list_file;
hb_handle_t * h;
};
static int compare_str(const void *a, const void *b)
{
return strncmp(*(const char**)a, *(const char**)b, PATH_MAX);
}
/***********************************************************************
* hb_batch_init
***********************************************************************
*
**********************************************************************/
hb_batch_t * hb_batch_init( hb_handle_t *h, char * path, hb_list_t * exclude_extensions )
{
hb_batch_t * d;
hb_stat_t sb;
HB_DIR * dir;
struct dirent * entry;
char * filename;
int count, ii;
char ** files;
if ( hb_stat( path, &sb ) )
return NULL;
if ( !S_ISDIR( sb.st_mode ) )
return NULL;
dir = hb_opendir(path);
if ( dir == NULL )
return NULL;
// Count the total number of entries
count = 0;
2023-02-11 13:26:22 +01:00
while (hb_readdir(dir))
{
count++;
}
if (count == 0)
{
return NULL;
}
files = malloc(count * sizeof(char*));
if (files == NULL)
{
return NULL;
}
// Excluded Extensions
int extension_count = hb_list_count(exclude_extensions);
hb_log("Excluding %i file extension(s) from scan. ", extension_count);
for (int i = 0; i < extension_count; i++ )
{
char * file_extension = hb_list_item( exclude_extensions, i );
hb_log(" - Excluding Extension: %s", file_extension);
}
// Find all regular files
ii = 0;
hb_rewinddir(dir);
while ( (entry = hb_readdir( dir ) ) )
{
filename = hb_strdup_printf( "%s" DIR_SEP_STR "%s", path, entry->d_name );
int excluded = 0;
for (int i = 0; i < extension_count; i++ )
{
const char *file_extension = hb_list_item(exclude_extensions, i);
if (hb_str_ends_with(filename, file_extension))
{
hb_deep_log(2, " -- Excluding File: %s", filename);
excluded = 1;
}
}
if (excluded)
{
free(filename);
continue;
}
if (hb_stat(filename, &sb))
{
free(filename);
continue;
}
if (!S_ISREG(sb.st_mode))
{
free(filename);
continue;
}
files[ii++] = filename;
}
count = ii;
// Sort the files
qsort(files, count, sizeof(char*), compare_str);
// Create file list
d = calloc( sizeof( hb_batch_t ), 1 );
if (d == NULL)
{
free(files);
return NULL;
}
d->h = h;
d->list_file = hb_list_init();
for (ii = 0; ii < count; ii++)
{
hb_list_add( d->list_file, files[ii] );
}
hb_closedir( dir );
free(files);
if ( hb_list_count( d->list_file ) == 0 )
{
hb_list_close( &d->list_file );
free( d );
return NULL;
}
d->path = strdup( path );
return d;
}
/***********************************************************************
* hb_batch_title_count
**********************************************************************/
int hb_batch_title_count( hb_batch_t * d )
{
return hb_list_count( d->list_file );
}
/***********************************************************************
* hb_batch_title_scan
**********************************************************************/
hb_title_t * hb_batch_title_scan( hb_batch_t * d, int t )
{
hb_title_t * title;
char * filename;
hb_stream_t * stream;
if ( t < 0 )
return NULL;
filename = hb_list_item( d->list_file, t - 1 );
if ( filename == NULL )
return NULL;
libhb: fix or simplify several hacks involved with Libav support For files that are demuxed by Libav, we must share the format context with the decoder iso that it can obtain the codec context for each stream. The code that did this was very convoluted and difficult to understand. It is simplified by simply passing the context in hb_title_t. Reader was closing stream files before the decoder was finished with the context. This created the need to delay the actual close and cache the context. Changed reader so it behaves more like the rest of handbrake's work objects which lets us explicitly close after the decoders are finished. Libav does some probing of the file when av_find_stream_info is called. This probing leaves the format context in a bad state for some files and causes subsequent reads or seeks to misbehave. So open 2 contexts in ffmpeg_open. One is used only for probing, and the other only for reading. decavcodec.c had 2 separate decoders for files demuxed by hb and files demuxed by Libav. They have been combined and simplified. Previously, it was not possible to decode one source audio track multiple times in order to fan it out to multiple output tracks if the file is demuxed by Libav. We were using the codec context from the format context. Since there is only one of these for each stream, we could only do one decode for each stream. Use avcodec_copy_context to make copies of the codec context and allow multiple decodes. This allows removal of a lot of special case code for Libav streams that was necessary to duplicate the output of the decoder. Patch Libav's mkv demux to fix a seek problem. This has been pushed upstreams, so the next time we update Libav, we must remove this patch. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4141 b64f7644-9d1e-0410-96f1-a4d463321fa5
2011-07-27 15:09:49 +00:00
hb_log( "batch: scanning %s", filename );
title = hb_title_init( filename, t );
stream = hb_stream_open(d->h, filename, title, 1);
if ( stream == NULL )
libhb: fix or simplify several hacks involved with Libav support For files that are demuxed by Libav, we must share the format context with the decoder iso that it can obtain the codec context for each stream. The code that did this was very convoluted and difficult to understand. It is simplified by simply passing the context in hb_title_t. Reader was closing stream files before the decoder was finished with the context. This created the need to delay the actual close and cache the context. Changed reader so it behaves more like the rest of handbrake's work objects which lets us explicitly close after the decoders are finished. Libav does some probing of the file when av_find_stream_info is called. This probing leaves the format context in a bad state for some files and causes subsequent reads or seeks to misbehave. So open 2 contexts in ffmpeg_open. One is used only for probing, and the other only for reading. decavcodec.c had 2 separate decoders for files demuxed by hb and files demuxed by Libav. They have been combined and simplified. Previously, it was not possible to decode one source audio track multiple times in order to fan it out to multiple output tracks if the file is demuxed by Libav. We were using the codec context from the format context. Since there is only one of these for each stream, we could only do one decode for each stream. Use avcodec_copy_context to make copies of the codec context and allow multiple decodes. This allows removal of a lot of special case code for Libav streams that was necessary to duplicate the output of the decoder. Patch Libav's mkv demux to fix a seek problem. This has been pushed upstreams, so the next time we update Libav, we must remove this patch. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4141 b64f7644-9d1e-0410-96f1-a4d463321fa5
2011-07-27 15:09:49 +00:00
{
hb_title_close( &title );
return NULL;
libhb: fix or simplify several hacks involved with Libav support For files that are demuxed by Libav, we must share the format context with the decoder iso that it can obtain the codec context for each stream. The code that did this was very convoluted and difficult to understand. It is simplified by simply passing the context in hb_title_t. Reader was closing stream files before the decoder was finished with the context. This created the need to delay the actual close and cache the context. Changed reader so it behaves more like the rest of handbrake's work objects which lets us explicitly close after the decoders are finished. Libav does some probing of the file when av_find_stream_info is called. This probing leaves the format context in a bad state for some files and causes subsequent reads or seeks to misbehave. So open 2 contexts in ffmpeg_open. One is used only for probing, and the other only for reading. decavcodec.c had 2 separate decoders for files demuxed by hb and files demuxed by Libav. They have been combined and simplified. Previously, it was not possible to decode one source audio track multiple times in order to fan it out to multiple output tracks if the file is demuxed by Libav. We were using the codec context from the format context. Since there is only one of these for each stream, we could only do one decode for each stream. Use avcodec_copy_context to make copies of the codec context and allow multiple decodes. This allows removal of a lot of special case code for Libav streams that was necessary to duplicate the output of the decoder. Patch Libav's mkv demux to fix a seek problem. This has been pushed upstreams, so the next time we update Libav, we must remove this patch. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4141 b64f7644-9d1e-0410-96f1-a4d463321fa5
2011-07-27 15:09:49 +00:00
}
libhb: fix or simplify several hacks involved with Libav support For files that are demuxed by Libav, we must share the format context with the decoder iso that it can obtain the codec context for each stream. The code that did this was very convoluted and difficult to understand. It is simplified by simply passing the context in hb_title_t. Reader was closing stream files before the decoder was finished with the context. This created the need to delay the actual close and cache the context. Changed reader so it behaves more like the rest of handbrake's work objects which lets us explicitly close after the decoders are finished. Libav does some probing of the file when av_find_stream_info is called. This probing leaves the format context in a bad state for some files and causes subsequent reads or seeks to misbehave. So open 2 contexts in ffmpeg_open. One is used only for probing, and the other only for reading. decavcodec.c had 2 separate decoders for files demuxed by hb and files demuxed by Libav. They have been combined and simplified. Previously, it was not possible to decode one source audio track multiple times in order to fan it out to multiple output tracks if the file is demuxed by Libav. We were using the codec context from the format context. Since there is only one of these for each stream, we could only do one decode for each stream. Use avcodec_copy_context to make copies of the codec context and allow multiple decodes. This allows removal of a lot of special case code for Libav streams that was necessary to duplicate the output of the decoder. Patch Libav's mkv demux to fix a seek problem. This has been pushed upstreams, so the next time we update Libav, we must remove this patch. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4141 b64f7644-9d1e-0410-96f1-a4d463321fa5
2011-07-27 15:09:49 +00:00
title = hb_stream_title_scan( stream, title );
hb_stream_close( &stream );
return title;
}
hb_title_t * hb_batch_title_scan_single(hb_handle_t *h, char *filename, int title_index)
{
hb_title_t *title;
hb_stream_t *stream;
if (title_index < 0)
{
return NULL;
}
if (!hb_is_valid_batch_path(filename))
{
return NULL;
}
hb_log("batch: scanning %s", filename);
title = hb_title_init(filename, title_index);
if (title == NULL)
{
return NULL;
}
stream = hb_stream_open(h, filename, title, 1);
if (stream == NULL)
{
hb_title_close(&title);
return NULL;
}
title = hb_stream_title_scan(stream, title);
hb_stream_close(&stream);
return title;
}
int hb_is_valid_batch_path(const char *filename)
{
hb_stat_t sb;
if (hb_stat(filename, &sb))
{
return 0;
}
if (S_ISDIR(sb.st_mode))
{
return 0;
}
if (!S_ISREG(sb.st_mode))
{
return 0;
}
return 1;
}
/***********************************************************************
* hb_batch_close
***********************************************************************
* Closes and frees everything
**********************************************************************/
void hb_batch_close( hb_batch_t ** _d )
{
hb_batch_t * d = *_d;
char * filename;
while ( ( filename = hb_list_item( d->list_file, 0 ) ) )
{
hb_list_rem( d->list_file, filename );
free( filename );
}
hb_list_close( &d->list_file );
free( d->path );
free( d );
*_d = NULL;
}