<commit_before>#include <ffmpeg/avformat.h>
#include <stdlib.h>
#include <string.h>

#include "indexer.h"

#define INDEX_SIZE 29
#define HEADER_SIZE 9 

typedef struct{
    uint64_t size;
    ByteIOContext pb;
    uint64_t search_time;
    uint64_t index_binary_offset;
    uint8_t start_at;
    int key_frame_num;
    char mode;
} SearchContext;

static av_always_inline int compute_idx(Index *read_idx, ByteIOContext *seek_pb)
{
    read_idx->pts = get_le64(seek_pb);
    read_idx->dts = get_le64(seek_pb);
    read_idx->pes_offset = get_le64(seek_pb);
    read_idx->pic_type = get_byte(seek_pb);
    read_idx->timecode.frames = get_byte(seek_pb);
    read_idx->timecode.seconds = get_byte(seek_pb);
    read_idx->timecode.minutes = get_byte(seek_pb);
    read_idx->timecode.hours = get_byte(seek_pb);
    return 0;
}

int search_frame(SearchContext *search, Index *read_idx)
{
    uint64_t high = search->size;
    uint64_t low = 0;
    uint64_t mid = search->size / 2;
    ByteIOContext *seek_pb = NULL;
    uint64_t read_time = 0; // used to store the timecode members in a single 64 bits integer to facilitate comparison 
    int nb_index = (int)(search->size / INDEX_SIZE);

    printf("%d indexes\n", nb_index);
    seek_pb = &search->pb;

    // Checks if the value we want is inferior or equal to the first value in the file
    url_fseek(seek_pb, HEADER_SIZE, SEEK_SET); // reads the first index in the file
    compute_idx(read_idx, seek_pb);
    if (search->mode == 't') {
        read_time = read_idx->timecode.hours * 1000000 + read_idx->timecode.minutes * 10000 + read_idx->timecode.seconds * 100 + read_idx->timecode.frames;
    }
    else if (search->mode == 'p') {
        read_time = read_idx->pts;
    }
    else if (search->mode == 'd') {
        read_time = read_idx->dts;
    }

    if (read_time == search->search_time){
        return 1;
    } else if (read_time > search->search_time) {
        return -1;
    }
    while (low <= high) {
        mid = (int)((high + low) / 2);
        mid -= (mid % INDEX_SIZE) - HEADER_SIZE ;

        url_fseek(seek_pb, mid, SEEK_SET);

        compute_idx(read_idx, seek_pb);
        if (search->mode == 't') {
            read_time = read_idx->timecode.hours * 1000000 + read_idx->timecode.minutes * 10000 + read_idx->timecode.seconds * 100 + read_idx->timecode.frames;
        }
        else {
            read_time = read_idx->pts;
        }
        if (read_time == search->search_time){
            search->index_binary_offset = mid;
            return 1;
        } else if (read_time > search->search_time) {
            high = mid - INDEX_SIZE;
        } else if (read_time < search->search_time) {
            low = mid + INDEX_SIZE;
        }
    }
    return 0;
}

int search_frame_dts(SearchContext *search, Index *read_idx)
{
    uint64_t i = search->index_binary_offset + INDEX_SIZE;
    uint64_t tmp_pts = read_idx->pts;
    ByteIOContext *seek_pb = &search->pb;
    while (i < search->size) {
        url_fseek(seek_pb, i, SEEK_SET);
        compute_idx(read_idx, seek_pb);
        // looks for the frame that has the dts we're looking for, it's located after the frame with that value as pts
        if (read_idx->dts == tmp_pts) {
            search->index_binary_offset = i; 
            return 1;
        }
        i += INDEX_SIZE;
    }
    return 0;
}

int find_previous_key_frame(Index *key_frame, Index read_idx, SearchContext search)
{
    int i = search.index_binary_offset - INDEX_SIZE;
    ByteIOContext *seek_pb = &search.pb;

    while (i >= 0){
        url_fseek(seek_pb, i, SEEK_SET);
        compute_idx(key_frame, seek_pb);
        if (key_frame->pic_type == 1){
            return 1; 
        }
        i -= INDEX_SIZE;
    }
    return 0;
}

char get_frame_type(Index idx)
{
    char frame = 'U';
    char frame_types[3] = {'I','P','B'};
    if (idx.pic_type > 0 && idx.pic_type < 4) {
        frame = frame_types[idx.pic_type - 1];
    }
    return frame;
}

int main(int argc, char **argv)
{
    SearchContext search;
    Index read_idx;
    Index key_frame;

    if (argc < 4) {
        printf("usage: search_idx <parameter type> <index file> <hhmmssff>\n");
        printf("parameters types are :\n\t-t\ttimecode\n\t-p\tpts\n\t-d\tdts\n");
        return 1;
    }

    register_protocol(&file_protocol);
    int len = strlen(argv[3]);
    for (int i = 0; i < len; i++){
        if (argv[3][i] < '0' || argv[3][i] > '9'){
            printf("search value must be integer\n");
            return 0;
        }
    }

    if (url_fopen(&search.pb, argv[2], URL_RDONLY) < 0) {
        printf("error opening file %s\n", argv[2]);
        return 1;
    }
    search.size = url_fsize(&search.pb) - HEADER_SIZE;

    printf("Index size : %lld\n", search.size);
    int64_t magic = get_le64(&search.pb);
    if (magic != 0x534A2D494E444558LL){
        printf("%s is not an index file.\n", argv[2]);
        return 1;
    }
//    printf("Version : %d\n", get_byte(&search.pb));
    search.key_frame_num =0;
    int res = 0;
    search.mode = argv[1][1];
    switch(search.mode){
        case 't':
            if (strlen(argv[3]) != 8){
                printf("timecode is invalid\n\tmust be of the form : hhmmssff\n");
                return 0;<commit_msg>function load index, (search_idx is broken, changing it into library)<commit_after>#include <ffmpeg/avformat.h>
#include <stdlib.h>
#include <string.h>

#include "indexer.h"

#define INDEX_SIZE 29
#define HEADER_SIZE 9 

typedef struct{
    uint64_t size;
    ByteIOContext pb;
    uint64_t search_time;
    uint64_t index_binary_offset;
    uint8_t start_at;
    int key_frame_num;
    char mode;
} SearchContext;

typedef struct{
    uint64_t index_num;
    Index *idxL;
} IndexContext;

static av_always_inline int compute_idx(Index *read_idx, ByteIOContext *seek_pb)
{
    read_idx->pts = get_le64(seek_pb);
    read_idx->dts = get_le64(seek_pb);
    read_idx->pes_offset = get_le64(seek_pb);
    read_idx->pic_type = get_byte(seek_pb);
    read_idx->timecode.frames = get_byte(seek_pb);
    read_idx->timecode.seconds = get_byte(seek_pb);
    read_idx->timecode.minutes = get_byte(seek_pb);
    read_idx->timecode.hours = get_byte(seek_pb);
    return 0;
}

static IndexContext* load_index(char *filename, SearchContext *search)
{
    IndexContext *idxctx;
    register_protocol(&file_protocol);
    
    if (url_fopen(&search->pb, filename, URL_RDONLY) < 0) {
        printf("error opening file %s\n", filename);
        return NULL;
    }
    search->size = url_fsize(&search->pb) - HEADER_SIZE;
    idxctx->index_num = (int)(search->size / INDEX_SIZE);
    idxctx->idxL = av_malloc(idxctx->index_num * sizeof(Index)); 

    printf("Index size : %lld\n", search->size);
    int64_t magic = get_le64(&search->pb);
    if (magic != 0x534A2D494E444558LL){
        printf("%s is not an index file.\n", filename);
        return NULL;
    }

    for(int i = 0; i < idxctx->index_num; i++){
        compute_idx(&idxctx->idxL[i], &search->pb);
    }
    return idxctx;
}

int search_frame(SearchContext *search, Index *read_idx)
{
    uint64_t high = search->size;
    uint64_t low = 0;
    uint64_t mid = search->size / 2;
    ByteIOContext *seek_pb = NULL;
    uint64_t read_time = 0; // used to store the timecode members in a single 64 bits integer to facilitate comparison 
    int nb_index = (int)(search->size / INDEX_SIZE);

    printf("%d indexes\n", nb_index);
    seek_pb = &search->pb;

    // Checks if the value we want is inferior or equal to the first value in the file
    url_fseek(seek_pb, HEADER_SIZE, SEEK_SET); // reads the first index in the file
    compute_idx(read_idx, seek_pb);
    if (search->mode == 't') {
        read_time = read_idx->timecode.hours * 1000000 + read_idx->timecode.minutes * 10000 + read_idx->timecode.seconds * 100 + read_idx->timecode.frames;
    }
    else if (search->mode == 'p') {
        read_time = read_idx->pts;
    }
    else if (search->mode == 'd') {
        read_time = read_idx->dts;
    }

    if (read_time == search->search_time){
        return 1;
    } else if (read_time > search->search_time) {
        return -1;
    }
    while (low <= high) {
        mid = (int)((high + low) / 2);
        mid -= (mid % INDEX_SIZE) - HEADER_SIZE ;

        url_fseek(seek_pb, mid, SEEK_SET);

        compute_idx(read_idx, seek_pb);
        if (search->mode == 't') {
            read_time = read_idx->timecode.hours * 1000000 + read_idx->timecode.minutes * 10000 + read_idx->timecode.seconds * 100 + read_idx->timecode.frames;
        }
        else {
            read_time = read_idx->pts;
        }
        if (read_time == search->search_time){
            search->index_binary_offset = mid;
            return 1;
        } else if (read_time > search->search_time) {
            high = mid - INDEX_SIZE;
        } else if (read_time < search->search_time) {
            low = mid + INDEX_SIZE;
        }
    }
    return 0;
}

int search_frame_dts(SearchContext *search, Index *read_idx)
{
    uint64_t i = search->index_binary_offset + INDEX_SIZE;
    uint64_t tmp_pts = read_idx->pts;
    ByteIOContext *seek_pb = &search->pb;
    while (i < search->size) {
        url_fseek(seek_pb, i, SEEK_SET);
        compute_idx(read_idx, seek_pb);
        // looks for the frame that has the dts we're looking for, it's located after the frame with that value as pts
        if (read_idx->dts == tmp_pts) {
            search->index_binary_offset = i; 
            return 1;
        }
        i += INDEX_SIZE;
    }
    return 0;
}

int find_previous_key_frame(Index *key_frame, Index read_idx, SearchContext search)
{
    int i = search.index_binary_offset - INDEX_SIZE;
    ByteIOContext *seek_pb = &search.pb;

    while (i >= 0){
        url_fseek(seek_pb, i, SEEK_SET);
        compute_idx(key_frame, seek_pb);
        if (key_frame->pic_type == 1){
            return 1; 
        }
        i -= INDEX_SIZE;
    }
    return 0;
}

char get_frame_type(Index idx)
{
    char frame = 'U';
    char frame_types[3] = {'I','P','B'};
    if (idx.pic_type > 0 && idx.pic_type < 4) {
        frame = frame_types[idx.pic_type - 1];
    }
    return frame;
}

int main(int argc, char **argv)
{
    SearchContext search;
    IndexContext *idxctx;
    Index read_idx;
    Index key_frame;

    if (argc < 4) {
        printf("usage: search_idx <parameter type> <index file> <hhmmssff>\n");
        printf("parameters types are :\n\t-t\ttimecode\n\t-p\tpts\n\t-d\tdts\n");
        return 1;
    }

    int len = strlen(argv[3]);
    for (int i = 0; i < len; i++){
        if (argv[3][i] < '0' || argv[3][i] > '9'){
            printf("search value must be integer\n");
            return 0;
        }
    }
    
    idxctx = load_index(argv[2], &search);
    if (!idxctx) {
        printf("Index file could not be loaded\n");
        return 0;
    }
//    printf("Version : %d\n", get_byte(&search.pb));
    search.key_frame_num =0;
    int res = 0;
    search.mode = argv[1][1];
    switch(search.mode){
        case 't':
            if (strlen(argv[3]) != 8){
                printf("timecode is invalid\n\tmust be of the form : hhmmssff\n");
                return 0;
{'fraction_non_alphanumeric': 0.13078921436889726, 'fraction_numerical': 0.021320433575203798, 'mean_word_length': 2.5117961623151936, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 117, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '707675', 'n_tokens_mistral': 4121, 'n_tokens_neox': 3886, 'n_words': 918}