Exemple #1
0
 LockedQueue() {
     _start = 0;
     _end = 0;
     _length = 0;
     _capacity = 0;
     _items = NULL;
     _shutdown = false;
     if (!(_mutex = os_mutex_create()))
         mutex_err = GenesisErrorNoMem;
     if (!(_cond = os_cond_create()))
         cond_err = GenesisErrorNoMem;
 }
/* ----------------------------------------------------------------------
 * allocate space for a new non-wrap fifo, and return pointer to
 * opaque handle.  returns NULL on failure
 * -------------------------------------------------------------------- */
VCHI_NWFIFO_T *
non_wrap_fifo_create( const char *name, const uint32_t size, int alignment, int no_of_slots )
{
   int32_t success = -1;
   NON_WRAP_FIFO_HANDLE_T *fifo;

   // check that the alignment is a power of 2 or 0
#ifndef WIN32
   os_assert((OS_COUNT(alignment) == 1) || (alignment == 0));
#endif

   // put the alignment into a form we can use (must be power of 2)
   alignment = alignment ? alignment - 1 : 0;

   // create new non-wrap fifo struct
   fifo = (NON_WRAP_FIFO_HANDLE_T *)os_malloc( sizeof(NON_WRAP_FIFO_HANDLE_T), OS_ALIGN_DEFAULT, "" );
   os_assert( fifo );
   if (!fifo) return NULL;
   
   memset( fifo, 0, sizeof(NON_WRAP_FIFO_HANDLE_T) );
   fifo->name = name;

   // allocate slightly more space than we need so that we can get the required alignment
   fifo->malloc_address = (uint8_t *)os_malloc(size+alignment, OS_ALIGN_DEFAULT, "");
   if ( fifo->malloc_address ) {
      fifo->base_address = (uint8_t *)(((size_t)fifo->malloc_address + alignment) & ~alignment);
      fifo->read_ptr = fifo->base_address;
      fifo->write_ptr = fifo->base_address;
      // now allocate the space for the slot_info structures
      fifo->slot_info = (NON_WRAP_SLOT_T *)os_malloc(no_of_slots*sizeof(NON_WRAP_SLOT_T), OS_ALIGN_DEFAULT, "");
      memset( fifo->slot_info, 0, no_of_slots * sizeof(NON_WRAP_SLOT_T) );
      fifo->size = size;
      fifo->num_of_slots = no_of_slots;
      success = os_semaphore_create( &fifo->sem, OS_SEMAPHORE_TYPE_SUSPEND );
      os_assert(success == 0);
      success = os_cond_create( &fifo->space_available_cond, &fifo->sem );
      os_assert(success == 0);
   }
   else {
      os_free(fifo);
      fifo = NULL;
   }

   return (VCHI_NWFIFO_T *)fifo;
}
Exemple #3
0
int audio_graph_create_render(Project *project, GenesisContext *genesis_context,
        const GenesisExportFormat *export_format, const ByteBuffer &out_path,
        AudioGraph **out_audio_graph)
{
    AudioGraph *ag = audio_graph_create_common(project, genesis_context, 0.10);

    ag->render_export_format = *export_format;
    ag->render_out_path = out_path;

    ag->render_frame_index = 0;
    ag->render_frame_count = project_get_duration_frames(project);
    ag->render_cond = ok_mem(os_cond_create());
    ag->is_playing = true;

    ag->render_descr = genesis_create_node_descriptor(ag->pipeline,
            1, "render", "Master render node.");
    if (!ag->render_descr)
        panic("unable to create render node descriptor");

    genesis_node_descriptor_set_userdata(ag->render_descr, ag);
    genesis_node_descriptor_set_run_callback(ag->render_descr, render_node_run);
    genesis_node_descriptor_set_activate_callback(ag->render_descr, render_node_activate);
    ag->render_port_descr = genesis_node_descriptor_create_port(
            ag->render_descr, 0, GenesisPortTypeAudioIn, "audio_in");
    if (!ag->render_port_descr)
        panic("unable to create render port descriptor");
    genesis_audio_port_descriptor_set_channel_layout(ag->render_port_descr,
            &project->channel_layout, true, -1);
    genesis_audio_port_descriptor_set_sample_rate(ag->render_port_descr,
            export_format->sample_rate, true, -1);

    ag->master_node = ok_mem(genesis_node_descriptor_create_node(ag->render_descr));

    ag->render_stream = ok_mem(genesis_audio_file_stream_create(ag->pipeline->context));

    int render_sample_rate = genesis_audio_file_codec_best_sample_rate(export_format->codec,
            export_format->sample_rate);

    genesis_audio_file_stream_set_sample_rate(ag->render_stream, render_sample_rate);
    genesis_audio_file_stream_set_channel_layout(ag->render_stream, &project->channel_layout);

    ByteBuffer encoded;
    encoded = project->tag_title.encode();
    genesis_audio_file_stream_set_tag(ag->render_stream, "title", -1, encoded.raw(), encoded.length());

    encoded = project->tag_artist.encode();
    genesis_audio_file_stream_set_tag(ag->render_stream, "artist", -1, encoded.raw(), encoded.length());

    encoded = project->tag_album_artist.encode();
    genesis_audio_file_stream_set_tag(ag->render_stream, "album_artist", -1, encoded.raw(), encoded.length());

    encoded = project->tag_album.encode();
    genesis_audio_file_stream_set_tag(ag->render_stream, "album", -1, encoded.raw(), encoded.length());

    // TODO looks like I messed up the year tag; it should actually be ISO 8601 "date"
    // TODO so we need to write the date tag here, not year.

    genesis_audio_file_stream_set_export_format(ag->render_stream, export_format);

    int err;
    if ((err = genesis_audio_file_stream_open(ag->render_stream, out_path.raw(),
                    out_path.length())))
    {
        audio_graph_destroy(ag);
        return err;
    }

    *out_audio_graph = ag;
    return 0;
}
int ordered_map_file_open(const char *path, OrderedMapFile **out_omf) {
    *out_omf = nullptr;
    OrderedMapFile *omf = create_zero<OrderedMapFile>();
    if (!omf) {
        ordered_map_file_close(omf);
        return GenesisErrorNoMem;
    }
    if (!(omf->cond = os_cond_create())) {
        ordered_map_file_close(omf);
        return GenesisErrorNoMem;
    }
    if (!(omf->mutex = os_mutex_create())) {
        ordered_map_file_close(omf);
        return GenesisErrorNoMem;
    }
    if (omf->queue.error()) {
        ordered_map_file_close(omf);
        return omf->queue.error();
    }
    omf->list = create_zero<List<OrderedMapFileEntry *>>();
    if (!omf->list) {
        ordered_map_file_close(omf);
        return GenesisErrorNoMem;
    }

    omf->map = create_zero<HashMap<ByteBuffer, OrderedMapFileEntry *, ByteBuffer::hash>>();
    if (!omf->map) {
        ordered_map_file_close(omf);
        return GenesisErrorNoMem;
    }

    omf->running = true;
    int err;
    if ((err = os_thread_create(run_write, omf, false, &omf->write_thread))) {
        ordered_map_file_close(omf);
        return err;
    }

    bool open_for_writing = false;
    omf->file = fopen(path, "rb+");
    if (omf->file) {
        int err = read_header(omf);
        if (err == GenesisErrorEmptyFile) {
            open_for_writing = true;
        } else if (err) {
            ordered_map_file_close(omf);
            return err;
        }
    } else {
        open_for_writing = true;
    }
    if (open_for_writing) {
        omf->file = fopen(path, "wb+");
        if (!omf->file) {
            ordered_map_file_close(omf);
            return GenesisErrorFileAccess;
        }
        int err = write_header(omf);
        if (err) {
            ordered_map_file_close(omf);
            return err;
        }
    }

    // read everything into list
    bool partial_transaction = false;
    omf->write_buffer.resize(TRANSACTION_METADATA_SIZE);
    omf->transaction_offset = UUID_SIZE;
    for (;;) {
        size_t amt_read = fread(omf->write_buffer.raw(), 1, TRANSACTION_METADATA_SIZE, omf->file);
        if (amt_read != TRANSACTION_METADATA_SIZE) {
            // partial transaction. ignore it and we're done.
            if (amt_read > 0)
                partial_transaction = true;
            break;
        }
        uint8_t *transaction_ptr = (uint8_t*)omf->write_buffer.raw();
        int transaction_size = read_uint32be(&transaction_ptr[4]);
        if (transaction_size < TRANSACTION_METADATA_SIZE ||
            transaction_size > MAX_TRANSACTION_SIZE)
        {
            // invalid value
            partial_transaction = true;
            break;
        }

        omf->write_buffer.resize(transaction_size);
        transaction_ptr = (uint8_t*)omf->write_buffer.raw();

        size_t amt_to_read = transaction_size - TRANSACTION_METADATA_SIZE;
        amt_read = fread(&transaction_ptr[TRANSACTION_METADATA_SIZE], 1, amt_to_read, omf->file);
        if (amt_read != amt_to_read) {
            // partial transaction. ignore it and we're done.
            partial_transaction = true;
            break;
        }
        uint32_t computed_crc = crc32(0, &transaction_ptr[4], transaction_size - 4);
        uint32_t crc_from_file = read_uint32be(&transaction_ptr[0]);
        if (computed_crc != crc_from_file) {
            // crc check failed. ignore this transaction and we're done.
            partial_transaction = true;
            break;
        }

        int put_count = read_uint32be(&transaction_ptr[8]);
        int del_count = read_uint32be(&transaction_ptr[12]);

        int offset = TRANSACTION_METADATA_SIZE;
        for (int i = 0; i < put_count; i += 1) {
            int key_size = read_uint32be(&transaction_ptr[offset]); offset += 4;
            int val_size = read_uint32be(&transaction_ptr[offset]); offset += 4;

            OrderedMapFileEntry *entry = create_zero<OrderedMapFileEntry>();
            if (!entry) {
                ordered_map_file_close(omf);
                return GenesisErrorNoMem;
            }

            entry->key = ByteBuffer((char*)&transaction_ptr[offset], key_size); offset += key_size;
            entry->offset = omf->transaction_offset + offset;
            entry->size = val_size;
            offset += val_size;

            auto old_hash_entry = omf->map->maybe_get(entry->key);
            if (old_hash_entry) {
                OrderedMapFileEntry *old_entry = old_hash_entry->value;
                destroy(old_entry, 1);
            }

            omf->map->put(entry->key, entry);
        }
        for (int i = 0; i < del_count; i += 1) {
            int key_size = read_uint32be(&transaction_ptr[offset]); offset += 4;
            ByteBuffer key((char*)&transaction_ptr[offset], key_size); offset += key_size;

            auto hash_entry = omf->map->maybe_get(key);
            if (hash_entry) {
                OrderedMapFileEntry *entry = hash_entry->value;
                omf->map->remove(key);
                destroy(entry, 1);
            }
        }

        omf->transaction_offset += transaction_size;

    }

    if (partial_transaction)
        fprintf(stderr, "Warning: Partial transaction found in project file.\n");

    // transfer map to list and sort
    auto it = omf->map->entry_iterator();
    if (omf->list->ensure_capacity(omf->map->size())) {
        ordered_map_file_close(omf);
        return GenesisErrorNoMem;
    }
    for (;;) {
        auto *map_entry = it.next();
        if (!map_entry)
            break;

        ok_or_panic(omf->list->append(map_entry->value));
    }
    omf->map->clear();
    destroy_map(omf);

    omf->list->sort<compare_entries>();

    *out_omf = omf;
    return 0;
}