Skip to content

Commit

Permalink
Fix output again
Browse files Browse the repository at this point in the history
  • Loading branch information
cyanreg committed Nov 23, 2023
1 parent f8ec840 commit 117d0da
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 64 deletions.
39 changes: 0 additions & 39 deletions libavtransport/avtransport.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,45 +56,6 @@ void avt_close(AVTContext **ctx)
}
}

AVTStream *avt_alloc_stream(AVTContext *ctx, uint16_t id, AVTStream **stl, int *nb_st)
{
if (!ctx->output.ctx)
return NULL;

AVTStream *ret = NULL;
AVTStream **new = realloc(ctx->stream, sizeof(*new)*(ctx->nb_stream + 1));
if (!new)
return NULL;
ctx->stream = new;

ret = calloc(1, sizeof(**new));
if (!ret)
return NULL;

ret->priv = calloc(1, sizeof(*ret->priv));
if (!ret->priv) {
free(ret);
return NULL;
}

new[ctx->nb_stream] = ret;
ctx->nb_stream++;

return ret;
}

AVTStream *avt_find_stream(AVTContext *ctx, uint16_t id)
{
int i;
for (i = 0; i < ctx->nb_stream; i++) {
if (ctx->stream[i]->id == id)
break;
}
if (i == ctx->nb_stream)
return NULL;
return ctx->stream[i];
}

void avt_log(void *ctx, enum AVTLogLevel level, const char *fmt, ...)
{
va_list args;
Expand Down
3 changes: 0 additions & 3 deletions libavtransport/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,4 @@ struct AVTContext {
AVTContextOptions opts;
};

AVTStream *avt_alloc_stream(AVTContext *ctx, uint16_t id);
AVTStream *avt_find_stream(AVTContext *ctx, uint16_t id);

#endif
4 changes: 2 additions & 2 deletions libavtransport/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,10 +288,10 @@ int avt_init_io(AVTContext *ctx, const AVTIO **_io, AVTIOCtx **io_ctx,
return err;
}

void avt_connection_flush(AVTContext *ctx, AVTConnection **conn)
void avt_connection_flush(AVTConnection *conn)
{
}

void avt_connection_destroy(AVTContext *ctx, AVTConnection **conn)
void avt_connection_destroy(AVTConnection **conn)
{
}
4 changes: 2 additions & 2 deletions libavtransport/include/avtransport/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,13 @@ AVT_API int avt_connection_create(AVTContext *ctx, AVTConnection **conn,
* Immediately flush all buffered data for a connection.
* Should be called before avt_connection_destroy().
*/
AVT_API void avt_connection_flush(AVTContext *ctx, AVTConnection **conn);
AVT_API void avt_connection_flush(AVTConnection *conn);

/**
* Immediately destroy a connection, and free all resources associated
* with it.
* Will not flush.
*/
AVT_API void avt_connection_destroy(AVTContext *ctx, AVTConnection **conn);
AVT_API void avt_connection_destroy(AVTConnection **conn);

#endif
18 changes: 16 additions & 2 deletions libavtransport/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,28 @@ int avt_output_open(AVTContext *ctx, AVTOutput **_out,

avt_send_session_start(out);

*_out = out;

return 0;
}

FN_CREATING(avt_out, AVTOutput, AVTStream, stream, streams, nb_streams)

AVTStream *avt_output_stream_add(AVTOutput *out, uint16_t id)
{
AVTStream *st = avt_out_create_stream(out);
if (!st)
return NULL;

st->priv = calloc(1, sizeof(*st->priv));
if (!st->priv) {
return NULL;
}

st->id = id;
st->priv->out = out;

// return avt_alloc_stream(out->ctx, id);
return NULL;
return st;
}

int avt_output_stream_update(AVTOutput *out, AVTStream *st)
Expand Down
4 changes: 2 additions & 2 deletions libavtransport/output_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ typedef struct AVTOutput {
AVTConnection **conn;
uint32_t nb_conn;

AVTStream **stream;
int nb_stream;
AVTStream **streams;
int nb_streams;

atomic_uint_least64_t seq;
atomic_uint_least64_t epoch;
Expand Down
21 changes: 21 additions & 0 deletions libavtransport/utils_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,25 @@ static inline void avt_assert2(int cond)

uint64_t avt_get_time_ns(void);

/* Generic macro for creating contexts which need to keep their addresses
* if another context is created. */
#define FN_CREATING(prefix, ctx, type, shortname, array, num) \
static inline type * prefix## _ ## create_ ## shortname(ctx *dctx) \
{ \
type **array, *sctx = calloc(1, sizeof(*sctx)); \
if (!sctx) \
return NULL; \
\
array = realloc(dctx->array, sizeof(*dctx->array) * (dctx->num + 1)); \
if (!array) { \
free(sctx); \
return NULL; \
} \
\
dctx->array = array; \
dctx->array[dctx->num++] = sctx; \
\
return sctx; \
}

#endif
150 changes: 136 additions & 14 deletions tools/avcat.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,40 +44,104 @@

#define MAX_INPUTS 4

enum IOMode {
IO_RAW,
IO_AVT,
IO_LAVF,
};

typedef struct IOContext {
int is_avt;
enum IOMode mode;

enum AVTConnectionType type;
AVTContext *avt;
AVTConnection *conn;
AVTStream *st;
AVTOutput *out;

FILE *raw;

#ifdef HAVE_FFMPEG
AVFormatContext *avf;
#endif
} IOContext;

static int path_is_avt(const char *path, enum AVTConnectionType *conn_type)
static enum IOMode path_is_avt(const char *path, enum AVTConnectionType *conn_type, int is_out)
{
int len = strlen(path);

if (!strncmp(path, "avt://", strlen("avt://")) ||
!strncmp(path, "file://", strlen("file://"))) {
*conn_type = AVT_CONNECTION_URL;
return 1;
return IO_AVT;
} else if (!strcmp(&path[len - 4], ".avt") || !strcmp(&path[len - 3], ".at")) {
*conn_type = AVT_CONNECTION_FILE;
return 1;
return IO_AVT;
} else if (is_out && /* For output, anything that can be concat'd payload */
(!strcmp(&path[len - 5], ".h264") ||
!strcmp(&path[len - 5], ".h265") ||
!strcmp(&path[len - 5], ".hevc") ||
!strcmp(&path[len - 5], ".tiff") ||
!strcmp(&path[len - 5], ".jpeg") ||
!strcmp(&path[len - 4], ".dng") ||
!strcmp(&path[len - 4], ".png") ||
!strcmp(&path[len - 4], ".jpg") ||
!strcmp(&path[len - 4], ".aac") ||
!strcmp(&path[len - 4], ".ac3") ||
!strcmp(&path[len - 4], ".svg"))) {
return IO_RAW;
} else if (!is_out && /* Individual files do not need any framing */
(!strcmp(&path[len - 5], ".tiff") ||
!strcmp(&path[len - 5], ".jpeg") ||
!strcmp(&path[len - 4], ".dng") ||
!strcmp(&path[len - 4], ".png") ||
!strcmp(&path[len - 4], ".jpg") ||
!strcmp(&path[len - 4], ".svg"))) {
return IO_RAW;
}

return 0;
}

static int close_io(IOContext *io, int is_out)
{
switch (io->mode) {
case IO_AVT: {
avt_output_close(&io->out);
avt_connection_flush(io->conn);
avt_connection_destroy(&io->conn);
avt_close(&io->avt);
break;
}
case IO_RAW: {
fclose(io->raw);
break;
}
case IO_LAVF: {
if (is_out) {
av_write_trailer(io->avf);
avformat_flush(io->avf);
avio_closep(&io->avf->pb);
avformat_free_context(io->avf);
io->avf = NULL;
} else {
avformat_close_input(&io->avf);
}
break;
}
};

return 0;
}

static int open_io(IOContext *io, const char *path, int is_out)
{
int err;

io->is_avt = path_is_avt(path, &io->type);
io->mode = path_is_avt(path, &io->type, is_out);

if (io->is_avt) {
switch (io->mode) {
case IO_AVT: {
AVTContextOptions ctx_opts = {
.log_cb = NULL,
.producer_name = "avcat",
Expand Down Expand Up @@ -115,8 +179,20 @@ static int open_io(IOContext *io, const char *path, int is_out)
io->st = avt_output_stream_add(io->out, 12765);

avt_output_stream_update(io->out, io->st);
} else {

}
break;
}
case IO_RAW: {
io->raw = fopen(path, is_out ? "w+" : "r");
if (!io->raw) {
avt_log(NULL, AVT_LOG_ERROR, "Couldn't open %s: %i!\n", path, errno);
return AVT_ERROR(errno);
}
} else {
break;
}
case IO_LAVF: {
#ifdef HAVE_FFMPEG
if (is_out) {
err = avformat_alloc_output_context2(&io->avf, NULL, NULL, path);
Expand All @@ -125,6 +201,14 @@ static int open_io(IOContext *io, const char *path, int is_out)
av_err2str(err));
return err;
}

/* Open for writing */
err = avio_open(&io->avf->pb, path, AVIO_FLAG_WRITE);
if (err < 0) {
avt_log(NULL, AVT_LOG_ERROR, "Couldn't open output %s: %s!\n", path,
av_err2str(err));
return err;
}
} else {
err = avformat_open_input(&io->avf, path, NULL, NULL);
if (err < 0) {
Expand All @@ -144,7 +228,9 @@ static int open_io(IOContext *io, const char *path, int is_out)
avt_log(NULL, AVT_LOG_ERROR, "FFmpeg support not compiled in, cannot open %s!\n", path);
return AVT_ERROR(EINVAL);
#endif
break;
}
};

avt_log(NULL, AVT_LOG_INFO, "Opened file %s for %s\n", path, is_out ? "writing" : "reading");

Expand Down Expand Up @@ -182,17 +268,53 @@ int main(int argc, char **argv)
goto end;
}

AVPacket *out_packet = av_packet_alloc();
av_read_frame(in->avf, out_packet);
switch (in[0].mode) {
case IO_AVT: {

AVTBuffer *buf = avt_buffer_create(out_packet->data, out_packet->size, NULL, NULL);
break;
}
case IO_RAW: {
fseek(in[0].raw, 0L, SEEK_END);
size_t len = ftell(in[0].raw);
fseek(in[0].raw, 0L, SEEK_SET);
uint8_t *data = malloc(len);
if (!data)
return AVT_ERROR(ENOMEM);

AVTPacket pkt = {
.type = AVT_FRAME_TYPE_KEY,
.data = buf,
fread(data, len, 1, in[0].raw);

AVTBuffer *buf = avt_buffer_create(data, len, NULL, NULL);
AVTPacket pkt = {
.type = AVT_FRAME_TYPE_KEY,
.data = buf,
};

avt_output_stream_data(out.st, &pkt);

break;
}
case IO_LAVF: {
#ifdef HAVE_FFMPEG
AVPacket *out_packet = av_packet_alloc();
av_read_frame(in[0].avf, out_packet);

/* Todo: import */
AVTBuffer *buf = avt_buffer_create(out_packet->data, out_packet->size, NULL, NULL);

AVTPacket pkt = {
.type = AVT_FRAME_TYPE_KEY,
.data = buf,
};

avt_output_stream_data(out.st, &pkt);
#endif
break;
}
};

avt_output_stream_data(out.st, &pkt);
for (int i = 0; input[i]; i++)
close_io(&in[i], 0);
close_io(&out, 1);

end:
return 0;
Expand Down

0 comments on commit 117d0da

Please sign in to comment.