int av_strerror(int errnum, char *errbuf, size_t errbuf_size) { int ret = 0, i; const struct error_entry *entry = NULL; for (i = 0; i < FF_ARRAY_ELEMS(error_entries); i++) { if (errnum == error_entries[i].num) { entry = &error_entries[i]; break; } } if (entry) { av_strlcpy(errbuf, entry->str, errbuf_size); } else { #if HAVE_STRERROR_R ret = AVERROR(strerror_r(AVUNERROR(errnum), errbuf, errbuf_size)); #else ret = -1; #endif if (ret < 0) snprintf(errbuf, errbuf_size, "Error number %d occurred", errnum); } return ret; }
AVPacket * read_raw_video_frame (AVFormatContext * pifc, int vi) { int ok = 0; AVPacket * pkt = av_malloc(sizeof(AVPacket)); av_init_packet(pkt); pkt->data = NULL; pkt->size = 0; while (1) { // read a raw packet ok = av_read_frame(pifc, pkt); if (ok != 0) { ok = AVUNERROR(ok); goto failed; } // the raw packet may belong to other streams after seeking if (pkt->stream_index == vi) { break; } av_packet_unref(pkt); } return pkt; failed: delete_raw_video_frame(&pkt); return NULL; }
/** Send a prepared MMST command packet. */ static int send_command_packet(MMSTContext *mmst) { MMSContext *mms = &mmst->mms; int len= mms->write_out_ptr - mms->out_buffer; int exact_length = FFALIGN(len, 8); int first_length= exact_length - 16; int len8= first_length/8; int write_result; // update packet length fields. AV_WL32(mms->out_buffer + 8, first_length); AV_WL32(mms->out_buffer + 16, len8); AV_WL32(mms->out_buffer + 32, len8-2); memset(mms->write_out_ptr, 0, exact_length - len); // write it out. write_result= ffurl_write(mms->mms_hd, mms->out_buffer, exact_length); if(write_result != exact_length) { av_log(NULL, AV_LOG_ERROR, "Failed to write data of length %d: %d (%s)\n", exact_length, write_result, write_result < 0 ? strerror(AVUNERROR(write_result)) : "The server closed the connection"); return AVERROR(EIO); } return 0; }
int av_strerror(int errnum, char *errbuf, size_t errbuf_size) { int ret = 0; const char *errstr = NULL; switch (errnum) { case AVERROR_BSF_NOT_FOUND: errstr = "Bitstream filter not found" ; break; case AVERROR_DECODER_NOT_FOUND: errstr = "Decoder not found" ; break; case AVERROR_DEMUXER_NOT_FOUND: errstr = "Demuxer not found" ; break; case AVERROR_ENCODER_NOT_FOUND: errstr = "Encoder not found" ; break; case AVERROR_EOF: errstr = "End of file" ; break; case AVERROR_EXIT: errstr = "Immediate exit requested" ; break; case AVERROR_FILTER_NOT_FOUND: errstr = "Filter not found" ; break; case AVERROR_INVALIDDATA: errstr = "Invalid data found when processing input" ; break; case AVERROR_MUXER_NOT_FOUND: errstr = "Muxer not found" ; break; case AVERROR_OPTION_NOT_FOUND: errstr = "Option not found" ; break; case AVERROR_PATCHWELCOME: errstr = "Not yet implemented in FFmpeg, patches welcome"; break; case AVERROR_PROTOCOL_NOT_FOUND:errstr = "Protocol not found" ; break; case AVERROR_STREAM_NOT_FOUND: errstr = "Stream not found" ; break; } if (errstr) { av_strlcpy(errbuf, errstr, errbuf_size); } else { #if HAVE_STRERROR_R ret = strerror_r(AVUNERROR(errnum), errbuf, errbuf_size); #else ret = -1; #endif if (ret < 0) snprintf(errbuf, errbuf_size, "Error number %d occurred", errnum); } return ret; }
/***************************************************************************** * Write: *****************************************************************************/ static ssize_t Write(sout_access_out_t *p_access, block_t *p_buffer) { sout_access_out_sys_t *p_sys = (sout_access_out_sys_t*)p_access->p_sys; size_t i_write = 0; int val; while (p_buffer != NULL) { block_t *p_next = p_buffer->p_next; avio_write(p_sys->context, p_buffer->p_buffer, p_buffer->i_buffer); avio_flush(p_sys->context); if ((val = p_sys->context->error) != 0) { p_sys->context->error = 0; /* FIXME? */ goto error; } i_write += p_buffer->i_buffer; block_Release(p_buffer); p_buffer = p_next; } return i_write; error: msg_Err(p_access, "Wrote only %zu bytes: %s", i_write, vlc_strerror_c(AVUNERROR(val))); block_ChainRelease( p_buffer ); return i_write; }
static int mux_next(stream_t *stream) { int result; AVPacket packet; do { result = get_next(stream); if (result <= 0) { return result; } } while (stream->dst_size == 0); av_init_packet(&packet); packet.data = stream->dst_data; packet.size = stream->dst_size; /*packet.pts = stream->pts;*/ /* FIXME: proper PTS/DTS handling */ packet.stream_index = 0; result = av_interleaved_write_frame(stream->dst_ctx, &packet); if (result < 0) { musicd_log(LOG_ERROR, "stream", "av_interleaved_write_frame failed: %s", strerror(AVUNERROR(result))); return -1; } return 1; }
int OutOpenAvio(vlc_object_t *object) { sout_access_out_t *access = (sout_access_out_t*)object; config_ChainParse( access, "sout-avio-", ppsz_sout_options, access->p_cfg ); sout_access_out_sys_t *sys = malloc(sizeof(*sys)); if (!sys) return VLC_ENOMEM; sys->context = NULL; /* */ vlc_init_avformat(object); if (!access->psz_path) goto error; int ret; #if LIBAVFORMAT_VERSION_MAJOR < 54 ret = avio_open(&sys->context, access->psz_path, AVIO_FLAG_WRITE); #else AVDictionary *options = NULL; char *psz_opts = var_InheritString(access, "sout-avio-options"); if (psz_opts && *psz_opts) { options = vlc_av_get_options(psz_opts); free(psz_opts); } ret = avio_open2(&sys->context, access->psz_path, AVIO_FLAG_WRITE, NULL, &options); AVDictionaryEntry *t = NULL; while ((t = av_dict_get(options, "", t, AV_DICT_IGNORE_SUFFIX))) msg_Err( access, "unknown option \"%s\"", t->key ); av_dict_free(&options); #endif if (ret < 0) { errno = AVUNERROR(ret); msg_Err(access, "Failed to open %s", access->psz_path); goto error; } #if LIBAVFORMAT_VERSION_MAJOR < 54 /* We can accept only one active user at any time */ if (SetupAvioCb(VLC_OBJECT(access))) { msg_Err(access, "Module aready in use"); goto error; } #endif access->pf_write = Write; access->pf_control = OutControl; access->pf_seek = OutSeek; access->p_sys = sys; return VLC_SUCCESS; error: free(sys); return VLC_EGENERIC; }
static void print_averror(int err) { char errbuf[128]; const char *errbuf_ptr = errbuf; if (av_strerror(err, errbuf, sizeof(errbuf)) < 0) errbuf_ptr = strerror(AVUNERROR(err)); fprintf(stderr, "%s\n", errbuf_ptr); }
void print_error(const char *filename, int err) { char errbuf[128]; const char *errbuf_ptr = errbuf; if (av_strerror(err, errbuf, sizeof(errbuf)) < 0) errbuf_ptr = strerror(AVUNERROR(err)); av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, errbuf_ptr); }
void print_error(const char *filename, int err) { char errbuf[128]; const char *errbuf_ptr = errbuf; if (av_strerror(err, errbuf, sizeof(errbuf)) < 0) errbuf_ptr = strerror(AVUNERROR(err)); fprintf(stderr, "%s: %s\n", filename, errbuf_ptr); }
int print_av_error(const char *function_name, int error) { char errorbuf[128]; char *error_ptr = errorbuf; if (av_strerror(error, errorbuf, sizeof(errorbuf)) < 0) { error_ptr = strerror(AVUNERROR(error)); } fprintf(stderr, "dr_meter: %s: %s\n", function_name, error_ptr); return error; }
void PrintError(const wxString& msg, int err) { char errbuf[128]; const char *errbuf_ptr = errbuf; if (av_strerror(err, errbuf, sizeof(errbuf)) < 0) errbuf_ptr = strerror(AVUNERROR(err)); wxString errorStr(errbuf_ptr, wxConvUTF8); wxLogError(msg + wxT(": ") + errorStr); }
int decode_video_frame (AVCodecContext * picc, const AVPacket * pkt, AVFrame * pf) { int ok = 0; // may need to feed multiple times to get one frame while (1) { ok = avcodec_send_packet(picc, pkt); if (ok != 0) { ok = AVUNERROR(ok); return ok; } ok = avcodec_receive_frame(picc, pf); ok = AVUNERROR(ok); if (ok != EAGAIN) { // maybe failed, just return the error code return ok; } // need to feed raw packet again } return ok; }
/***************************************************************************** * Write: *****************************************************************************/ static ssize_t Write(sout_access_out_t *p_access, block_t *p_buffer) { access_sys_t *p_sys = (access_sys_t*)p_access->p_sys; size_t i_write = 0; while (p_buffer != NULL) { block_t *p_next = p_buffer->p_next; #if LIBAVFORMAT_VERSION_MAJOR < 54 int written = url_write(p_sys->context, p_buffer->p_buffer, p_buffer->i_buffer); if (written < 0) { errno = AVUNERROR(written); goto error; } i_write += written; #else avio_write(p_sys->context, p_buffer->p_buffer, p_buffer->i_buffer); avio_flush(p_sys->context); if (p_sys->context->error) { errno = AVUNERROR(p_sys->context->error); p_sys->context->error = 0; /* FIXME? */ goto error; } i_write += p_buffer->i_buffer; #endif block_Release(p_buffer); p_buffer = p_next; } return i_write; error: msg_Err(p_access, "Wrote only %zu bytes (%m)", i_write); block_ChainRelease( p_buffer ); return i_write; }
/***************************************************************************** * Mux: multiplex available data in input fifos *****************************************************************************/ static int Mux( sout_mux_t *p_mux ) { sout_mux_sys_t *p_sys = p_mux->p_sys; if( p_sys->b_error ) return VLC_EGENERIC; if( p_sys->b_write_header ) { int error; msg_Dbg( p_mux, "writing header" ); char *psz_opts = var_GetNonEmptyString( p_mux, "sout-avformat-options" ); AVDictionary *options = NULL; if (psz_opts) { vlc_av_get_options(psz_opts, &options); free(psz_opts); } av_dict_set( &p_sys->oc->metadata, "encoding_tool", "VLC "VERSION, 0 ); error = avformat_write_header( p_sys->oc, options ? &options : NULL); AVDictionaryEntry *t = NULL; while ((t = av_dict_get(options, "", t, AV_DICT_IGNORE_SUFFIX))) { msg_Err( p_mux, "Unknown option \"%s\"", t->key ); } av_dict_free(&options); if( error < 0 ) { msg_Err( p_mux, "could not write header: %s", vlc_strerror_c(AVUNERROR(error)) ); p_sys->b_write_header = false; p_sys->b_error = true; return VLC_EGENERIC; } avio_flush( p_sys->oc->pb ); p_sys->b_write_header = false; } for( ;; ) { mtime_t i_dts; int i_stream = sout_MuxGetStream( p_mux, 1, &i_dts ); if( i_stream < 0 ) return VLC_SUCCESS; MuxBlock( p_mux, p_mux->pp_inputs[i_stream] ); } return VLC_SUCCESS; }
int ff_listen_connect(int fd, const struct sockaddr *addr, socklen_t addrlen, int timeout, URLContext *h, int will_try_next) { struct pollfd p = {fd, POLLOUT, 0}; int ret; socklen_t optlen; if (ff_socket_nonblock(fd, 1) < 0) av_log(NULL, AV_LOG_DEBUG, "ff_socket_nonblock failed\n"); while ((ret = connect(fd, addr, addrlen))) { ret = ff_neterrno(); switch (ret) { case AVERROR(EINTR): if (ff_check_interrupt(&h->interrupt_callback)) return AVERROR_EXIT; continue; case AVERROR(EINPROGRESS): case AVERROR(EAGAIN): ret = ff_poll_interrupt(&p, 1, timeout, &h->interrupt_callback); if (ret < 0) return ret; optlen = sizeof(ret); if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen)) ret = AVUNERROR(ff_neterrno()); if (ret != 0) { char errbuf[100]; ret = AVERROR(ret); av_strerror(ret, errbuf, sizeof(errbuf)); if (will_try_next) av_log(h, AV_LOG_WARNING, "Connection to %s failed (%s), trying next address\n", h->filename, errbuf); else av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n", h->filename, errbuf); } default: return ret; } } return ret; }
int OutOpenAvio(vlc_object_t *object) { sout_access_out_t *access = (sout_access_out_t*)object; config_ChainParse( access, "sout-avio-", ppsz_sout_options, access->p_cfg ); sout_access_out_sys_t *sys = vlc_obj_malloc(object, sizeof(*sys)); if (!sys) return VLC_ENOMEM; sys->context = NULL; /* */ vlc_init_avformat(object); if (!access->psz_path) return VLC_EGENERIC; int ret; AVDictionary *options = NULL; char *psz_opts = var_InheritString(access, "sout-avio-options"); if (psz_opts) { vlc_av_get_options(psz_opts, &options); free(psz_opts); } ret = avio_open2(&sys->context, access->psz_path, AVIO_FLAG_WRITE, NULL, &options); AVDictionaryEntry *t = NULL; while ((t = av_dict_get(options, "", t, AV_DICT_IGNORE_SUFFIX))) msg_Err( access, "unknown option \"%s\"", t->key ); av_dict_free(&options); if (ret < 0) { errno = AVUNERROR(ret); msg_Err(access, "Failed to open %s", access->psz_path); return VLC_EGENERIC; } access->pf_write = Write; access->pf_control = OutControl; access->pf_seek = OutSeek; access->p_sys = sys; return VLC_SUCCESS; }
static OSStatus tls_write_cb(SSLConnectionRef connection, const void *data, size_t *dataLength) { URLContext *h = (URLContext*)connection; TLSContext *c = h->priv_data; int written = ffurl_write(c->tls_shared.tcp, data, *dataLength); if (written <= 0) { *dataLength = 0; switch(AVUNERROR(written)) { case EAGAIN: return errSSLWouldBlock; default: c->lastErr = written; return ioErr; } } else { *dataLength = written; return noErr; } }
static int Seek(stream_t *access, uint64_t position) { access_sys_t *sys = access->p_sys; int ret; #ifndef EOVERFLOW # define EOVERFLOW EFBIG #endif if (position > INT64_MAX) ret = AVERROR(EOVERFLOW); else ret = avio_seek(sys->context, position, SEEK_SET); if (ret < 0) { msg_Err(access, "Seek to %"PRIu64" failed: %s", position, vlc_strerror_c(AVUNERROR(ret))); if (sys->size < 0 || position != (uint64_t)sys->size) return VLC_EGENERIC; } return VLC_SUCCESS; }
int open_radio( struct transcode_ctx *ctx, struct media_file_info *mfi ) { ctx->fmtctx = avformat_alloc_context(); URLContext *stream; url_alloc(&stream, mfi->url, URL_RDONLY ); ff_http_set_headers( stream, "Icy-MetaData:1\r\n"); DPRINTF(E_DBG, L_XCODE, "Trying to open url %s\n", mfi->url); int ret = url_connect(stream); if (ret != 0) { DPRINTF(E_WARN, L_XCODE, "Could not open url %s: %s\n", mfi->url, strerror(AVUNERROR(ret))); return -1; } DPRINTF(E_DBG, L_XCODE, "URL opened successfully"); if (icy) free(icy); icy = (struct icy_ctx *)malloc(sizeof(struct icy_ctx)); icy->context = stream; icy->data_pos = 0; icy->icy_metaint = get_meta_int( stream ); icy->rewritten_album = 0; icy->mfi = mfi; ctx->fmtctx = avformat_alloc_context(); if (buff) av_free( buff ); buff = (uint8_t *) av_malloc( BIO_BUFFER_SIZE ); ctx->fmtctx->pb = avio_alloc_context(buff, BIO_BUFFER_SIZE, 0, icy, ReadFunc2, NULL, NULL); return avformat_open_input(&ctx->fmtctx, mfi->url, NULL, NULL); }
static int unix_open(URLContext *h, const char *filename, int flags) { UnixContext *s = h->priv_data; int fd, ret; av_strstart(filename, "unix:", &filename); s->addr.sun_family = AF_UNIX; av_strlcpy(s->addr.sun_path, filename, sizeof(s->addr.sun_path)); if ((fd = ff_socket(AF_UNIX, s->type, 0)) < 0) return ff_neterrno(); if (s->timeout < 0 && h->rw_timeout) s->timeout = h->rw_timeout / 1000; if (s->listen) { ret = ff_listen_bind(fd, (struct sockaddr *)&s->addr, sizeof(s->addr), s->timeout, h); if (ret < 0) goto fail; fd = ret; } else { ret = ff_listen_connect(fd, (struct sockaddr *)&s->addr, sizeof(s->addr), s->timeout, h, 0); if (ret < 0) goto fail; } s->fd = fd; return 0; fail: if (s->listen && AVUNERROR(ret) != EADDRINUSE) unlink(s->addr.sun_path); if (fd >= 0) closesocket(fd); return ret; }
static int Seek(access_t *access, uint64_t position) { access_sys_t *sys = access->p_sys; int ret; #ifndef EOVERFLOW # define EOVERFLOW EFBIG #endif if (position > INT64_MAX) ret = AVERROR(EOVERFLOW); else ret = avio_seek(sys->context, position, SEEK_SET); if (ret < 0) { errno = AVUNERROR(ret); msg_Err(access, "Seek to %"PRIu64" failed: %m", position); if (sys->size == 0 || position != sys->size) return VLC_EGENERIC; } access->info.i_pos = position; access->info.b_eof = false; return VLC_SUCCESS; }
static int encode_next(stream_t *stream) { int result, got_packet; AVFrame *frame = stream->encode_frame; AVPacket *packet = &stream->encode_packet; while (av_audio_fifo_size(stream->src_buf) < stream->encoder->frame_size) { result = decode_next(stream); if (result <= 0) { return result; } } av_audio_fifo_read(stream->src_buf, (void **)frame->extended_data, stream->encoder->frame_size); av_free_packet(packet); result = avcodec_encode_audio2(stream->encoder, packet, frame, &got_packet); if (result < 0) { musicd_log(LOG_ERROR, "stream", "can't encode: %s", strerror(AVUNERROR(result))); return -1; } if (!got_packet) { return 1; } stream->dst_data = packet->data; stream->dst_size = packet->size; return 1; }
static OSStatus tls_read_cb(SSLConnectionRef connection, void *data, size_t *dataLength) { URLContext *h = (URLContext*)connection; TLSContext *c = h->priv_data; int read = ffurl_read_complete(c->tls_shared.tcp, data, *dataLength); if (read <= 0) { *dataLength = 0; switch(AVUNERROR(read)) { case ENOENT: case 0: return errSSLClosedGraceful; case ECONNRESET: return errSSLClosedAbort; case EAGAIN: return errSSLWouldBlock; default: c->lastErr = read; return ioErr; } } else { *dataLength = read; return noErr; } }
static int read_next(stream_t *stream) { int result; while (1) { av_free_packet(&stream->src_packet); result = av_read_frame(stream->src_ctx, &stream->src_packet); if (result < 0) { if (result == AVERROR_EOF) { /* end of file */ return 0; } musicd_log(LOG_ERROR, "stream", "av_read_frame failed: %s", strerror(AVUNERROR(result))); return 0; } if (stream->src_packet.stream_index != 0) { continue; } break; } if (stream->src_packet.pts * av_q2d(stream->src_ctx->streams[0]->time_base) > stream->track->start + stream->track->duration) { if (stream->track->cuefile) { /* Accurate end of track */ return 0; } else { /* Miscalculated track length */ } } return 1; }
int OpenAvio(vlc_object_t *object) { stream_t *access = (stream_t*)object; access_sys_t *sys = vlc_obj_malloc(object, sizeof(*sys)); if (!sys) return VLC_ENOMEM; sys->context = NULL; /* We accept: * - avio://full_url * - url (only a subset of available protocols). */ char *url; if (!strcmp(access->psz_name, "avio")) url = strdup(access->psz_location); else if (asprintf(&url, "%s://%s", access->psz_name, access->psz_location) < 0) url = NULL; if (!url) return VLC_ENOMEM; /* */ vlc_init_avformat(object); int ret; AVIOInterruptCB cb = { .callback = UrlInterruptCallback, .opaque = access, }; AVDictionary *options = NULL; char *psz_opts = var_InheritString(access, "avio-options"); if (psz_opts) { vlc_av_get_options(psz_opts, &options); free(psz_opts); } ret = avio_open2(&sys->context, url, AVIO_FLAG_READ, &cb, &options); AVDictionaryEntry *t = NULL; while ((t = av_dict_get(options, "", t, AV_DICT_IGNORE_SUFFIX))) msg_Err( access, "unknown option \"%s\"", t->key ); av_dict_free(&options); if (ret < 0) { msg_Err(access, "Failed to open %s: %s", url, vlc_strerror_c(AVUNERROR(ret))); free(url); return VLC_EGENERIC; } free(url); sys->size = avio_size(sys->context); bool seekable; seekable = sys->context->seekable; msg_Dbg(access, "%sseekable, size=%"PRIi64, seekable ? "" : "not ", sys->size); /* */ access->pf_read = Read; access->pf_block = NULL; access->pf_control = Control; access->pf_seek = Seek; access->p_sys = sys; return VLC_SUCCESS; }
int save_snapshot (const char * filename, const AVCodecContext * picc, const AVFrame * pif) { int ok = 0; OutputContext * output_context = output_context_new(filename, pif); if (!output_context) { ok = -1; goto failed; } // write file header ok = avformat_write_header(output_context->format_context, NULL); if (ok != 0) { ok = 1; goto failed; } // prepare pixel convertion AVCodecContext * pcc = output_context->codec_context; struct SwsContext * psc = sws_getCachedContext(NULL, picc->width, picc->height, picc->pix_fmt, pcc->width, pcc->height, pcc->pix_fmt, SWS_BILINEAR, NULL, NULL, NULL); if (!psc) { ok = 1; goto failed; } // prepare converted picture AVFrame * pf = av_frame_alloc(); if (!pf) { ok = 1; goto close_sws; } pf->width = pcc->width; pf->height = pcc->height; pf->format = pcc->pix_fmt; ok = av_image_alloc(pf->data, pf->linesize, pcc->width, pcc->height, pcc->pix_fmt, 1); if (ok < 0) { ok = AVUNERROR(ok); goto close_frame; } // convert pixel format ok = sws_scale(psc, (const uint8_t * const *)pif->data, pif->linesize, 0, picc->height, pf->data, pf->linesize); if (ok <= 0) { ok = 1; goto close_picture; } // encode frame AVPacket pkt; av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; ok = avcodec_send_frame(pcc, pf); if (ok != 0) { ok = AVUNERROR(ok); goto close_packet; } ok = avcodec_receive_packet(pcc, &pkt); if (ok != 0) { ok = AVUNERROR(ok); goto close_packet; } // NOTE does not matter in image pkt.pts = 0; pkt.dts = 0; // write encoded frame ok = av_interleaved_write_frame(output_context->format_context, &pkt); if (ok != 0) { ok = 1; goto close_file; } ok = 0; close_file: av_write_trailer(output_context->format_context); close_packet: av_packet_unref(&pkt); close_picture: av_freep(&pf->data[0]); close_frame: av_frame_free(&pf); close_sws: sws_freeContext(psc); failed: output_context_delete(&output_context); return ok; }
/** Read incoming MMST media, header or command packet. */ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) { int read_result; MMSSCPacketType packet_type= -1; MMSContext *mms = &mmst->mms; for(;;) { read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer, 8); if (read_result != 8) { if(read_result < 0) { av_log(NULL, AV_LOG_ERROR, "Error reading packet header: %d (%s)\n", read_result, strerror(AVUNERROR(read_result))); packet_type = SC_PKT_CANCEL; } else { av_log(NULL, AV_LOG_ERROR, "The server closed the connection\n"); packet_type = SC_PKT_NO_DATA; } return packet_type; } // handle command packet. if(AV_RL32(mms->in_buffer + 4)==0xb00bface) { int length_remaining, hr; mmst->incoming_flags= mms->in_buffer[3]; read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer+8, 4); if(read_result != 4) { av_log(NULL, AV_LOG_ERROR, "Reading command packet length failed: %d (%s)\n", read_result, read_result < 0 ? strerror(AVUNERROR(read_result)) : "The server closed the connection"); return read_result < 0 ? read_result : AVERROR(EIO); } length_remaining= AV_RL32(mms->in_buffer+8) + 4; av_log(NULL, AV_LOG_TRACE, "Length remaining is %d\n", length_remaining); // read the rest of the packet. if (length_remaining < 0 || length_remaining > sizeof(mms->in_buffer) - 12) { av_log(NULL, AV_LOG_ERROR, "Incoming packet length %d exceeds bufsize %"SIZE_SPECIFIER"\n", length_remaining, sizeof(mms->in_buffer) - 12); return AVERROR_INVALIDDATA; } read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer + 12, length_remaining) ; if (read_result != length_remaining) { av_log(NULL, AV_LOG_ERROR, "Reading pkt data (length=%d) failed: %d (%s)\n", length_remaining, read_result, read_result < 0 ? strerror(AVUNERROR(read_result)) : "The server closed the connection"); return read_result < 0 ? read_result : AVERROR(EIO); } packet_type= AV_RL16(mms->in_buffer+36); if (read_result >= 44 && (hr = AV_RL32(mms->in_buffer + 40))) { av_log(NULL, AV_LOG_ERROR, "Server sent a message with packet type 0x%x and error status code 0x%08x\n", packet_type, hr); return AVERROR(EINVAL); } } else { int length_remaining; int packet_id_type; int tmp; // note we cache the first 8 bytes, // then fill up the buffer with the others tmp = AV_RL16(mms->in_buffer + 6); length_remaining = (tmp - 8) & 0xffff; mmst->incoming_packet_seq = AV_RL32(mms->in_buffer); packet_id_type = mms->in_buffer[4]; mmst->incoming_flags = mms->in_buffer[5]; if (length_remaining < 0 || length_remaining > sizeof(mms->in_buffer) - 8) { av_log(NULL, AV_LOG_ERROR, "Data length %d is invalid or too large (max=%"SIZE_SPECIFIER")\n", length_remaining, sizeof(mms->in_buffer)); return AVERROR_INVALIDDATA; } mms->remaining_in_len = length_remaining; mms->read_in_ptr = mms->in_buffer; read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer, length_remaining); if(read_result != length_remaining) { av_log(NULL, AV_LOG_ERROR, "Failed to read packet data of size %d: %d (%s)\n", length_remaining, read_result, read_result < 0 ? strerror(AVUNERROR(read_result)) : "The server closed the connection"); return read_result < 0 ? read_result : AVERROR(EIO); } // if we successfully read everything. if(packet_id_type == mmst->header_packet_id) { int err; packet_type = SC_PKT_ASF_HEADER; // Store the asf header if(!mms->header_parsed) { if ((err = av_reallocp(&mms->asf_header, mms->asf_header_size + mms->remaining_in_len)) < 0) { mms->asf_header_size = 0; return err; } memcpy(mms->asf_header + mms->asf_header_size, mms->read_in_ptr, mms->remaining_in_len); mms->asf_header_size += mms->remaining_in_len; } // 0x04 means asf header is sent in multiple packets. if (mmst->incoming_flags == 0x04) continue; } else if(packet_id_type == mmst->packet_id) { packet_type = SC_PKT_ASF_MEDIA; } else { av_log(NULL, AV_LOG_TRACE, "packet id type %d is old.", packet_id_type); continue; } } // preprocess some packet type if(packet_type == SC_PKT_KEEPALIVE) { send_keepalive_packet(mmst); continue; } else if(packet_type == SC_PKT_STREAM_CHANGING) { handle_packet_stream_changing_type(mmst); } else if(packet_type == SC_PKT_ASF_MEDIA) { pad_media_packet(mms); } return packet_type; } }
int scan_metadata_ffmpeg(char *file, struct media_file_info *mfi) { AVFormatContext *ctx; const struct metadata_map *extra_md_map; enum CodecID codec_id; enum CodecID video_codec_id; enum CodecID audio_codec_id; AVStream *video_stream; AVStream *audio_stream; int mdcount; int i; int ret; ctx = NULL; #if LIBAVFORMAT_VERSION_MAJOR >= 53 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVCODEC_VERSION_MINOR >= 3) ret = avformat_open_input(&ctx, file, NULL, NULL); #else ret = av_open_input_file(&ctx, file, NULL, 0, NULL); #endif if (ret != 0) { DPRINTF(E_WARN, L_SCAN, "Cannot open media file '%s': %s\n", file, strerror(AVUNERROR(ret))); return -1; } ret = av_find_stream_info(ctx); if (ret < 0) { DPRINTF(E_WARN, L_SCAN, "Cannot get stream info: %s\n", strerror(AVUNERROR(ret))); av_close_input_file(ctx); return -1; } #if 0 /* Dump input format as determined by ffmpeg */ # if LIBAVFORMAT_VERSION_MAJOR >= 52 || (LIBAVFORMAT_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 101) av_dump_format(ctx, 0, file, 0); # else dump_format(ctx, 0, file, FALSE); # endif #endif DPRINTF(E_DBG, L_SCAN, "File has %d streams\n", ctx->nb_streams); /* Extract codec IDs, check for video */ video_codec_id = CODEC_ID_NONE; video_stream = NULL; audio_codec_id = CODEC_ID_NONE; audio_stream = NULL; for (i = 0; i < ctx->nb_streams; i++) { switch (ctx->streams[i]->codec->codec_type) { #if LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 64) case AVMEDIA_TYPE_VIDEO: #else case CODEC_TYPE_VIDEO: #endif if (!video_stream) { DPRINTF(E_DBG, L_SCAN, "File has video (stream %d)\n", i); mfi->has_video = 1; video_stream = ctx->streams[i]; video_codec_id = video_stream->codec->codec_id; } break; #if LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 64) case AVMEDIA_TYPE_AUDIO: #else case CODEC_TYPE_AUDIO: #endif if (!audio_stream) { audio_stream = ctx->streams[i]; audio_codec_id = audio_stream->codec->codec_id; } break; default: break; } } if (audio_codec_id == CODEC_ID_NONE) { DPRINTF(E_DBG, L_SCAN, "File has no audio streams, discarding\n"); av_close_input_file(ctx); return -1; } /* Common media information */ if (ctx->duration > 0) mfi->song_length = ctx->duration / (AV_TIME_BASE / 1000); /* ms */ if (ctx->bit_rate > 0) mfi->bitrate = ctx->bit_rate / 1000; else if (ctx->duration > AV_TIME_BASE) /* guesstimate */ mfi->bitrate = ((mfi->file_size * 8) / (ctx->duration / AV_TIME_BASE)) / 1000; DPRINTF(E_DBG, L_SCAN, "Duration %d ms, bitrate %d kbps\n", mfi->song_length, mfi->bitrate); /* Get some more information on the audio stream */ if (audio_stream) { if (audio_stream->codec->sample_rate != 0) mfi->samplerate = audio_stream->codec->sample_rate; /* Try sample format first */ #if LIBAVUTIL_VERSION_MAJOR >= 51 || (LIBAVUTIL_VERSION_MAJOR == 51 && LIBAVUTIL_VERSION_MINOR >= 4) mfi->bits_per_sample = 8 * av_get_bytes_per_sample(audio_stream->codec->sample_fmt); #elif LIBAVCODEC_VERSION_MAJOR >= 53 mfi->bits_per_sample = av_get_bits_per_sample_fmt(audio_stream->codec->sample_fmt); #else mfi->bits_per_sample = av_get_bits_per_sample_format(audio_stream->codec->sample_fmt); #endif if (mfi->bits_per_sample == 0) { /* Try codec */ mfi->bits_per_sample = av_get_bits_per_sample(audio_codec_id); } DPRINTF(E_DBG, L_SCAN, "samplerate %d, bps %d\n", mfi->samplerate, mfi->bits_per_sample); } /* Check codec */ extra_md_map = NULL; codec_id = (mfi->has_video) ? video_codec_id : audio_codec_id; switch (codec_id) { case CODEC_ID_AAC: DPRINTF(E_DBG, L_SCAN, "AAC\n"); mfi->type = strdup("m4a"); mfi->codectype = strdup("mp4a"); mfi->description = strdup("AAC audio file"); break; case CODEC_ID_ALAC: DPRINTF(E_DBG, L_SCAN, "ALAC\n"); mfi->type = strdup("m4a"); mfi->codectype = strdup("alac"); mfi->description = strdup("AAC audio file"); break; case CODEC_ID_FLAC: DPRINTF(E_DBG, L_SCAN, "FLAC\n"); mfi->type = strdup("flac"); mfi->codectype = strdup("flac"); mfi->description = strdup("FLAC audio file"); extra_md_map = md_map_vorbis; break; case CODEC_ID_MUSEPACK7: case CODEC_ID_MUSEPACK8: DPRINTF(E_DBG, L_SCAN, "Musepack\n"); mfi->type = strdup("mpc"); mfi->codectype = strdup("mpc"); mfi->description = strdup("Musepack audio file"); break; case CODEC_ID_MPEG4: /* Video */ case CODEC_ID_H264: DPRINTF(E_DBG, L_SCAN, "MPEG4 video\n"); mfi->type = strdup("m4v"); mfi->codectype = strdup("mp4v"); mfi->description = strdup("MPEG-4 video file"); extra_md_map = md_map_tv; break; case CODEC_ID_MP3: DPRINTF(E_DBG, L_SCAN, "MP3\n"); mfi->type = strdup("mp3"); mfi->codectype = strdup("mpeg"); mfi->description = strdup("MPEG audio file"); extra_md_map = md_map_id3; break; case CODEC_ID_VORBIS: DPRINTF(E_DBG, L_SCAN, "VORBIS\n"); mfi->type = strdup("ogg"); mfi->codectype = strdup("ogg"); mfi->description = strdup("Ogg Vorbis audio file"); extra_md_map = md_map_vorbis; break; case CODEC_ID_WMAVOICE: DPRINTF(E_DBG, L_SCAN, "WMA Voice\n"); mfi->type = strdup("wma"); mfi->codectype = strdup("wmav"); mfi->description = strdup("WMA audio file"); break; case CODEC_ID_WMAPRO: DPRINTF(E_DBG, L_SCAN, "WMA Pro\n"); mfi->type = strdup("wmap"); mfi->codectype = strdup("wma"); mfi->description = strdup("WMA audio file"); break; case CODEC_ID_WMALOSSLESS: DPRINTF(E_DBG, L_SCAN, "WMA Lossless\n"); mfi->type = strdup("wma"); mfi->codectype = strdup("wmal"); mfi->description = strdup("WMA audio file"); break; case CODEC_ID_WMAV1: case CODEC_ID_WMAV2: DPRINTF(E_DBG, L_SCAN, "WMA V1/V2\n"); mfi->type = strdup("wma"); mfi->codectype = strdup("wma"); mfi->description = strdup("WMA audio file"); break; case CODEC_ID_PCM_S16LE ... CODEC_ID_PCM_F64LE: if (strcmp(ctx->iformat->name, "aiff") == 0) { DPRINTF(E_DBG, L_SCAN, "AIFF\n"); mfi->type = strdup("aif"); mfi->codectype = strdup("aif"); mfi->description = strdup("AIFF audio file"); break; } else if (strcmp(ctx->iformat->name, "wav") == 0) { DPRINTF(E_DBG, L_SCAN, "WAV\n"); mfi->type = strdup("wav"); mfi->codectype = strdup("wav"); mfi->description = strdup("WAV audio file"); break; } /* WARNING: will fallthrough to default case, don't move */ /* FALLTHROUGH */ default: DPRINTF(E_DBG, L_SCAN, "Unknown codec 0x%x (video: %s), format %s (%s)\n", codec_id, (mfi->has_video) ? "yes" : "no", ctx->iformat->name, ctx->iformat->long_name); mfi->type = strdup("unkn"); mfi->codectype = strdup("unkn"); if (mfi->has_video) { mfi->description = strdup("Unknown video file format"); extra_md_map = md_map_tv; } else mfi->description = strdup("Unknown audio file format"); break; } mdcount = 0; if ((!ctx->metadata) && (!audio_stream->metadata) && (video_stream && !video_stream->metadata)) { DPRINTF(E_WARN, L_SCAN, "ffmpeg reports no metadata\n"); goto skip_extract; } if (extra_md_map) { ret = extract_metadata(mfi, ctx, audio_stream, video_stream, extra_md_map); mdcount += ret; DPRINTF(E_DBG, L_SCAN, "Picked up %d tags with extra md_map\n", ret); } #if LIBAVFORMAT_VERSION_MAJOR < 53 av_metadata_conv(ctx, NULL, ctx->iformat->metadata_conv); #endif ret = extract_metadata(mfi, ctx, audio_stream, video_stream, md_map_generic); mdcount += ret; DPRINTF(E_DBG, L_SCAN, "Picked up %d tags with generic md_map, %d tags total\n", ret, mdcount); /* fix up TV metadata */ if (mfi->media_kind == 10) { /* I have no idea why this is, but iTunes reports a media kind of 64 for stik==10 (?!) */ mfi->media_kind = 64; } /* Unspecified video files are "Movies", media_kind 2 */ else if (mfi->has_video == 1) { mfi->media_kind = 2; } skip_extract: if (mdcount == 0) { /* ffmpeg doesn't support FLAC nor Musepack metadata, * and is buggy for some WMA variants, so fall back to the * legacy format-specific parsers until it gets fixed */ if ((codec_id == CODEC_ID_WMAPRO) || (codec_id == CODEC_ID_WMAVOICE) || (codec_id == CODEC_ID_WMALOSSLESS)) { DPRINTF(E_WARN, L_SCAN, "Falling back to legacy WMA scanner\n"); av_close_input_file(ctx); return (scan_get_wmainfo(file, mfi) ? 0 : -1); } #ifdef FLAC else if (codec_id == CODEC_ID_FLAC) { DPRINTF(E_WARN, L_SCAN, "Falling back to legacy FLAC scanner\n"); av_close_input_file(ctx); return (scan_get_flacinfo(file, mfi) ? 0 : -1); } #endif /* FLAC */ #ifdef MUSEPACK else if ((codec_id == CODEC_ID_MUSEPACK7) || (codec_id == CODEC_ID_MUSEPACK8)) { DPRINTF(E_WARN, L_SCAN, "Falling back to legacy Musepack scanner\n"); av_close_input_file(ctx); return (scan_get_mpcinfo(file, mfi) ? 0 : -1); } #endif /* MUSEPACK */ else DPRINTF(E_WARN, L_SCAN, "Could not extract any metadata\n"); } /* Just in case there's no title set ... */ if (mfi->title == NULL) mfi->title = strdup(mfi->fname); /* All done */ av_close_input_file(ctx); return 0; }
int scan_metadata_ffmpeg(char *file, struct media_file_info *mfi) { AVFormatContext *ctx; AVDictionary *options; const struct metadata_map *extra_md_map; struct http_icy_metadata *icy_metadata; #if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35) enum AVCodecID codec_id; enum AVCodecID video_codec_id; enum AVCodecID audio_codec_id; #else enum CodecID codec_id; enum CodecID video_codec_id; enum CodecID audio_codec_id; #endif AVStream *video_stream; AVStream *audio_stream; char *path; int mdcount; int i; int ret; ctx = NULL; options = NULL; path = strdup(file); #if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 3) # ifndef HAVE_FFMPEG // Without this, libav is slow to probe some internet streams if (mfi->data_kind == DATA_KIND_HTTP) { ctx = avformat_alloc_context(); ctx->probesize = 64000; } # endif if (mfi->data_kind == DATA_KIND_HTTP) { free(path); ret = http_stream_setup(&path, file); if (ret < 0) return -1; av_dict_set(&options, "icy", "1", 0); mfi->artwork = ARTWORK_HTTP; } ret = avformat_open_input(&ctx, path, NULL, &options); if (options) av_dict_free(&options); #else ret = av_open_input_file(&ctx, path, NULL, 0, NULL); #endif if (ret != 0) { DPRINTF(E_WARN, L_SCAN, "Cannot open media file '%s': %s\n", path, strerror(AVUNERROR(ret))); free(path); return -1; } free(path); #if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 3) ret = avformat_find_stream_info(ctx, NULL); #else ret = av_find_stream_info(ctx); #endif if (ret < 0) { DPRINTF(E_WARN, L_SCAN, "Cannot get stream info: %s\n", strerror(AVUNERROR(ret))); #if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 21) avformat_close_input(&ctx); #else av_close_input_file(ctx); #endif return -1; } #if 0 /* Dump input format as determined by ffmpeg */ av_dump_format(ctx, 0, file, 0); #endif DPRINTF(E_DBG, L_SCAN, "File has %d streams\n", ctx->nb_streams); /* Extract codec IDs, check for video */ #if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35) video_codec_id = AV_CODEC_ID_NONE; video_stream = NULL; audio_codec_id = AV_CODEC_ID_NONE; audio_stream = NULL; #else video_codec_id = CODEC_ID_NONE; video_stream = NULL; audio_codec_id = CODEC_ID_NONE; audio_stream = NULL; #endif for (i = 0; i < ctx->nb_streams; i++) { switch (ctx->streams[i]->codec->codec_type) { #if LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 64) case AVMEDIA_TYPE_VIDEO: #else case CODEC_TYPE_VIDEO: #endif #if LIBAVFORMAT_VERSION_MAJOR >= 55 || (LIBAVFORMAT_VERSION_MAJOR == 54 && LIBAVFORMAT_VERSION_MINOR >= 6) if (ctx->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) { DPRINTF(E_DBG, L_SCAN, "Found embedded artwork (stream %d)\n", i); mfi->artwork = ARTWORK_EMBEDDED; break; } #endif // We treat these as audio no matter what if (mfi->compilation || (mfi->media_kind & (MEDIA_KIND_PODCAST | MEDIA_KIND_AUDIOBOOK))) break; if (!video_stream) { DPRINTF(E_DBG, L_SCAN, "File has video (stream %d)\n", i); mfi->has_video = 1; video_stream = ctx->streams[i]; video_codec_id = video_stream->codec->codec_id; } break; #if LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 64) case AVMEDIA_TYPE_AUDIO: #else case CODEC_TYPE_AUDIO: #endif if (!audio_stream) { audio_stream = ctx->streams[i]; audio_codec_id = audio_stream->codec->codec_id; } break; default: break; } } #if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35) if (audio_codec_id == AV_CODEC_ID_NONE) #else if (audio_codec_id == CODEC_ID_NONE) #endif { DPRINTF(E_DBG, L_SCAN, "File has no audio streams, discarding\n"); #if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 21) avformat_close_input(&ctx); #else av_close_input_file(ctx); #endif return -1; } /* Common media information */ if (ctx->duration > 0) mfi->song_length = ctx->duration / (AV_TIME_BASE / 1000); /* ms */ if (ctx->bit_rate > 0) mfi->bitrate = ctx->bit_rate / 1000; else if (ctx->duration > AV_TIME_BASE) /* guesstimate */ mfi->bitrate = ((mfi->file_size * 8) / (ctx->duration / AV_TIME_BASE)) / 1000; DPRINTF(E_DBG, L_SCAN, "Duration %d ms, bitrate %d kbps\n", mfi->song_length, mfi->bitrate); /* Try to extract ICY metadata if http stream */ if (mfi->data_kind == DATA_KIND_HTTP) { icy_metadata = http_icy_metadata_get(ctx, 0); if (icy_metadata && icy_metadata->name) { DPRINTF(E_DBG, L_SCAN, "Found ICY metadata, name is '%s'\n", icy_metadata->name); if (mfi->title) free(mfi->title); if (mfi->artist) free(mfi->artist); if (mfi->album_artist) free(mfi->album_artist); mfi->title = strdup(icy_metadata->name); mfi->artist = strdup(icy_metadata->name); mfi->album_artist = strdup(icy_metadata->name); } if (icy_metadata && icy_metadata->description) { DPRINTF(E_DBG, L_SCAN, "Found ICY metadata, description is '%s'\n", icy_metadata->description); if (mfi->album) free(mfi->album); mfi->album = strdup(icy_metadata->description); } if (icy_metadata && icy_metadata->genre) { DPRINTF(E_DBG, L_SCAN, "Found ICY metadata, genre is '%s'\n", icy_metadata->genre); if (mfi->genre) free(mfi->genre); mfi->genre = strdup(icy_metadata->genre); } if (icy_metadata) http_icy_metadata_free(icy_metadata, 0); } /* Get some more information on the audio stream */ if (audio_stream) { if (audio_stream->codec->sample_rate != 0) mfi->samplerate = audio_stream->codec->sample_rate; /* Try sample format first */ #if LIBAVUTIL_VERSION_MAJOR >= 52 || (LIBAVUTIL_VERSION_MAJOR == 51 && LIBAVUTIL_VERSION_MINOR >= 4) mfi->bits_per_sample = 8 * av_get_bytes_per_sample(audio_stream->codec->sample_fmt); #elif LIBAVCODEC_VERSION_MAJOR >= 53 mfi->bits_per_sample = av_get_bits_per_sample_fmt(audio_stream->codec->sample_fmt); #else mfi->bits_per_sample = av_get_bits_per_sample_format(audio_stream->codec->sample_fmt); #endif if (mfi->bits_per_sample == 0) { /* Try codec */ mfi->bits_per_sample = av_get_bits_per_sample(audio_codec_id); } DPRINTF(E_DBG, L_SCAN, "samplerate %d, bps %d\n", mfi->samplerate, mfi->bits_per_sample); } /* Check codec */ extra_md_map = NULL; codec_id = (mfi->has_video) ? video_codec_id : audio_codec_id; switch (codec_id) { #if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35) case AV_CODEC_ID_AAC: #else case CODEC_ID_AAC: #endif DPRINTF(E_DBG, L_SCAN, "AAC\n"); mfi->type = strdup("m4a"); mfi->codectype = strdup("mp4a"); mfi->description = strdup("AAC audio file"); break; #if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35) case AV_CODEC_ID_ALAC: #else case CODEC_ID_ALAC: #endif DPRINTF(E_DBG, L_SCAN, "ALAC\n"); mfi->type = strdup("m4a"); mfi->codectype = strdup("alac"); mfi->description = strdup("Apple Lossless audio file"); break; #if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35) case AV_CODEC_ID_FLAC: #else case CODEC_ID_FLAC: #endif DPRINTF(E_DBG, L_SCAN, "FLAC\n"); mfi->type = strdup("flac"); mfi->codectype = strdup("flac"); mfi->description = strdup("FLAC audio file"); extra_md_map = md_map_vorbis; break; #if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35) case AV_CODEC_ID_MUSEPACK7: case AV_CODEC_ID_MUSEPACK8: #else case CODEC_ID_MUSEPACK7: case CODEC_ID_MUSEPACK8: #endif DPRINTF(E_DBG, L_SCAN, "Musepack\n"); mfi->type = strdup("mpc"); mfi->codectype = strdup("mpc"); mfi->description = strdup("Musepack audio file"); break; #if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35) case AV_CODEC_ID_MPEG4: /* Video */ case AV_CODEC_ID_H264: #else case CODEC_ID_MPEG4: /* Video */ case CODEC_ID_H264: #endif DPRINTF(E_DBG, L_SCAN, "MPEG4 video\n"); mfi->type = strdup("m4v"); mfi->codectype = strdup("mp4v"); mfi->description = strdup("MPEG-4 video file"); extra_md_map = md_map_tv; break; #if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35) case AV_CODEC_ID_MP3: #else case CODEC_ID_MP3: #endif DPRINTF(E_DBG, L_SCAN, "MP3\n"); mfi->type = strdup("mp3"); mfi->codectype = strdup("mpeg"); mfi->description = strdup("MPEG audio file"); extra_md_map = md_map_id3; break; #if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35) case AV_CODEC_ID_VORBIS: #else case CODEC_ID_VORBIS: #endif DPRINTF(E_DBG, L_SCAN, "VORBIS\n"); mfi->type = strdup("ogg"); mfi->codectype = strdup("ogg"); mfi->description = strdup("Ogg Vorbis audio file"); extra_md_map = md_map_vorbis; break; #if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35) case AV_CODEC_ID_WMAV1: case AV_CODEC_ID_WMAV2: case AV_CODEC_ID_WMAVOICE: #else case CODEC_ID_WMAV1: case CODEC_ID_WMAV2: case CODEC_ID_WMAVOICE: #endif DPRINTF(E_DBG, L_SCAN, "WMA Voice\n"); mfi->type = strdup("wma"); mfi->codectype = strdup("wmav"); mfi->description = strdup("WMA audio file"); break; #if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35) case AV_CODEC_ID_WMAPRO: #else case CODEC_ID_WMAPRO: #endif DPRINTF(E_DBG, L_SCAN, "WMA Pro\n"); mfi->type = strdup("wmap"); mfi->codectype = strdup("wma"); mfi->description = strdup("WMA audio file"); break; #if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35) case AV_CODEC_ID_WMALOSSLESS: #else case CODEC_ID_WMALOSSLESS: #endif DPRINTF(E_DBG, L_SCAN, "WMA Lossless\n"); mfi->type = strdup("wma"); mfi->codectype = strdup("wmal"); mfi->description = strdup("WMA audio file"); break; #if LIBAVCODEC_VERSION_MAJOR >= 55 || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 35) case AV_CODEC_ID_PCM_S16LE ... AV_CODEC_ID_PCM_F64LE: #else case CODEC_ID_PCM_S16LE ... CODEC_ID_PCM_F64LE: #endif if (strcmp(ctx->iformat->name, "aiff") == 0) { DPRINTF(E_DBG, L_SCAN, "AIFF\n"); mfi->type = strdup("aif"); mfi->codectype = strdup("aif"); mfi->description = strdup("AIFF audio file"); break; } else if (strcmp(ctx->iformat->name, "wav") == 0) { DPRINTF(E_DBG, L_SCAN, "WAV\n"); mfi->type = strdup("wav"); mfi->codectype = strdup("wav"); mfi->description = strdup("WAV audio file"); break; } /* WARNING: will fallthrough to default case, don't move */ /* FALLTHROUGH */ default: DPRINTF(E_DBG, L_SCAN, "Unknown codec 0x%x (video: %s), format %s (%s)\n", codec_id, (mfi->has_video) ? "yes" : "no", ctx->iformat->name, ctx->iformat->long_name); mfi->type = strdup("unkn"); mfi->codectype = strdup("unkn"); if (mfi->has_video) { mfi->description = strdup("Unknown video file format"); extra_md_map = md_map_tv; } else mfi->description = strdup("Unknown audio file format"); break; } mdcount = 0; if ((!ctx->metadata) && (!audio_stream->metadata) && (video_stream && !video_stream->metadata)) { DPRINTF(E_WARN, L_SCAN, "ffmpeg reports no metadata\n"); goto skip_extract; } if (extra_md_map) { ret = extract_metadata(mfi, ctx, audio_stream, video_stream, extra_md_map); mdcount += ret; DPRINTF(E_DBG, L_SCAN, "Picked up %d tags with extra md_map\n", ret); } ret = extract_metadata(mfi, ctx, audio_stream, video_stream, md_map_generic); mdcount += ret; DPRINTF(E_DBG, L_SCAN, "Picked up %d tags with generic md_map, %d tags total\n", ret, mdcount); /* fix up TV metadata */ if (mfi->media_kind == 10) { /* I have no idea why this is, but iTunes reports a media kind of 64 for stik==10 (?!) */ mfi->media_kind = MEDIA_KIND_TVSHOW; } /* Unspecified video files are "Movies", media_kind 2 */ else if (mfi->has_video == 1) { mfi->media_kind = MEDIA_KIND_MOVIE; } skip_extract: #if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 21) avformat_close_input(&ctx); #else av_close_input_file(ctx); #endif if (mdcount == 0) DPRINTF(E_WARN, L_SCAN, "ffmpeg/libav could not extract any metadata\n"); /* Just in case there's no title set ... */ if (mfi->title == NULL) mfi->title = strdup(mfi->fname); /* All done */ return 0; }