Wie funktioniert ein MP3-Encocer?



  • Wie funktioniert ein MP3-Encocer? Die wikipedia-Seiten (de/en) sind mir zu schwammig.



  • So wie jeder Encoder. Deine Frage ist zu schwammig.



  • Ich will nen Algorithmus sehen.



  • /*
     * libmad - MPEG audio decoder library
     * Copyright (C) 2000-2004 Underbit Technologies, Inc.
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 2 of the License, or
     * (at your option) any later version.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software
     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     *
     * $Id: decoder.c,v 1.22 2004/01/23 09:41:32 rob Exp $
     */
    
    # ifdef HAVE_CONFIG_H
    #  include "config.h"
    # endif
    
    # include "global.h"
    
    # ifdef HAVE_SYS_TYPES_H
    #  include <sys/types.h>
    # endif
    
    # ifdef HAVE_SYS_WAIT_H
    #  include <sys/wait.h>
    # endif
    
    # ifdef HAVE_UNISTD_H
    #  include <unistd.h>
    # endif
    
    # ifdef HAVE_FCNTL_H
    #  include <fcntl.h>
    # endif
    
    # include <stdlib.h>
    
    # ifdef HAVE_ERRNO_H
    #  include <errno.h>
    # endif
    
    # include "stream.h"
    # include "frame.h"
    # include "synth.h"
    # include "decoder.h"
    
    /*
     * NAME:	decoder->init()
     * DESCRIPTION:	initialize a decoder object with callback routines
     */
    void mad_decoder_init(struct mad_decoder *decoder, void *data,
    		      enum mad_flow (*input_func)(void *,
    						  struct mad_stream *),
    		      enum mad_flow (*header_func)(void *,
    						   struct mad_header const *),
    		      enum mad_flow (*filter_func)(void *,
    						   struct mad_stream const *,
    						   struct mad_frame *),
    		      enum mad_flow (*output_func)(void *,
    						   struct mad_header const *,
    						   struct mad_pcm *),
    		      enum mad_flow (*error_func)(void *,
    						  struct mad_stream *,
    						  struct mad_frame *),
    		      enum mad_flow (*message_func)(void *,
    						    void *, unsigned int *))
    {
      decoder->mode         = -1;
    
      decoder->options      = 0;
    
      decoder->async.pid    = 0;
      decoder->async.in     = -1;
      decoder->async.out    = -1;
    
      decoder->sync         = 0;
    
      decoder->cb_data      = data;
    
      decoder->input_func   = input_func;
      decoder->header_func  = header_func;
      decoder->filter_func  = filter_func;
      decoder->output_func  = output_func;
      decoder->error_func   = error_func;
      decoder->message_func = message_func;
    }
    
    int mad_decoder_finish(struct mad_decoder *decoder)
    {
    # if defined(USE_ASYNC)
      if (decoder->mode == MAD_DECODER_MODE_ASYNC && decoder->async.pid) {
        pid_t pid;
        int status;
    
        close(decoder->async.in);
    
        do
          pid = waitpid(decoder->async.pid, &status, 0);
        while (pid == -1 && errno == EINTR);
    
        decoder->mode = -1;
    
        close(decoder->async.out);
    
        decoder->async.pid = 0;
        decoder->async.in  = -1;
        decoder->async.out = -1;
    
        if (pid == -1)
          return -1;
    
        return (!WIFEXITED(status) || WEXITSTATUS(status)) ? -1 : 0;
      }
    # endif
    
      return 0;
    }
    
    # if defined(USE_ASYNC)
    static
    enum mad_flow send_io(int fd, void const *data, size_t len)
    {
      char const *ptr = data;
      ssize_t count;
    
      while (len) {
        do
          count = write(fd, ptr, len);
        while (count == -1 && errno == EINTR);
    
        if (count == -1)
          return MAD_FLOW_BREAK;
    
        len -= count;
        ptr += count;
      }
    
      return MAD_FLOW_CONTINUE;
    }
    
    static
    enum mad_flow receive_io(int fd, void *buffer, size_t len)
    {
      char *ptr = buffer;
      ssize_t count;
    
      while (len) {
        do
          count = read(fd, ptr, len);
        while (count == -1 && errno == EINTR);
    
        if (count == -1)
          return (errno == EAGAIN) ? MAD_FLOW_IGNORE : MAD_FLOW_BREAK;
        else if (count == 0)
          return MAD_FLOW_STOP;
    
        len -= count;
        ptr += count;
      }
    
      return MAD_FLOW_CONTINUE;
    }
    
    static
    enum mad_flow receive_io_blocking(int fd, void *buffer, size_t len)
    {
      int flags, blocking;
      enum mad_flow result;
    
      flags = fcntl(fd, F_GETFL);
      if (flags == -1)
        return MAD_FLOW_BREAK;
    
      blocking = flags & ~O_NONBLOCK;
    
      if (blocking != flags &&
          fcntl(fd, F_SETFL, blocking) == -1)
        return MAD_FLOW_BREAK;
    
      result = receive_io(fd, buffer, len);
    
      if (flags != blocking &&
          fcntl(fd, F_SETFL, flags) == -1)
        return MAD_FLOW_BREAK;
    
      return result;
    }
    
    static
    enum mad_flow send(int fd, void const *message, unsigned int size)
    {
      enum mad_flow result;
    
      /* send size */
    
      result = send_io(fd, &size, sizeof(size));
    
      /* send message */
    
      if (result == MAD_FLOW_CONTINUE)
        result = send_io(fd, message, size);
    
      return result;
    }
    
    static
    enum mad_flow receive(int fd, void **message, unsigned int *size)
    {
      enum mad_flow result;
      unsigned int actual;
    
      if (*message == 0)
        *size = 0;
    
      /* receive size */
    
      result = receive_io(fd, &actual, sizeof(actual));
    
      /* receive message */
    
      if (result == MAD_FLOW_CONTINUE) {
        if (actual > *size)
          actual -= *size;
        else {
          *size  = actual;
          actual = 0;
        }
    
        if (*size > 0) {
          if (*message == 0) {
    	*message = malloc(*size);
    	if (*message == 0)
    	  return MAD_FLOW_BREAK;
          }
    
          result = receive_io_blocking(fd, *message, *size);
        }
    
        /* throw away remainder of message */
    
        while (actual && result == MAD_FLOW_CONTINUE) {
          char sink[256];
          unsigned int len;
    
          len = actual > sizeof(sink) ? sizeof(sink) : actual;
    
          result = receive_io_blocking(fd, sink, len);
    
          actual -= len;
        }
      }
    
      return result;
    }
    
    static
    enum mad_flow check_message(struct mad_decoder *decoder)
    {
      enum mad_flow result;
      void *message = 0;
      unsigned int size;
    
      result = receive(decoder->async.in, &message, &size);
    
      if (result == MAD_FLOW_CONTINUE) {
        if (decoder->message_func == 0)
          size = 0;
        else {
          result = decoder->message_func(decoder->cb_data, message, &size);
    
          if (result == MAD_FLOW_IGNORE ||
    	  result == MAD_FLOW_BREAK)
    	size = 0;
        }
    
        if (send(decoder->async.out, message, size) != MAD_FLOW_CONTINUE)
          result = MAD_FLOW_BREAK;
      }
    
      if (message)
        free(message);
    
      return result;
    }
    # endif
    
    static
    enum mad_flow error_default(void *data, struct mad_stream *stream,
    			    struct mad_frame *frame)
    {
      int *bad_last_frame = data;
    
      switch (stream->error) {
      case MAD_ERROR_BADCRC:
        if (*bad_last_frame)
          mad_frame_mute(frame);
        else
          *bad_last_frame = 1;
    
        return MAD_FLOW_IGNORE;
    
      default:
        return MAD_FLOW_CONTINUE;
      }
    }
    
    static
    int run_sync(struct mad_decoder *decoder)
    {
      enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *);
      void *error_data;
      int bad_last_frame = 0;
      struct mad_stream *stream;
      struct mad_frame *frame;
      struct mad_synth *synth;
      int result = 0;
    
      if (decoder->input_func == 0)
        return 0;
    
      if (decoder->error_func) {
        error_func = decoder->error_func;
        error_data = decoder->cb_data;
      }
      else {
        error_func = error_default;
        error_data = &bad_last_frame;
      }
    
      stream = &decoder->sync->stream;
      frame  = &decoder->sync->frame;
      synth  = &decoder->sync->synth;
    
      mad_stream_init(stream);
      mad_frame_init(frame);
      mad_synth_init(synth);
    
      mad_stream_options(stream, decoder->options);
    
      do {
        switch (decoder->input_func(decoder->cb_data, stream)) {
        case MAD_FLOW_STOP:
          goto done;
        case MAD_FLOW_BREAK:
          goto fail;
        case MAD_FLOW_IGNORE:
          continue;
        case MAD_FLOW_CONTINUE:
          break;
        }
    
        while (1) {
    # if defined(USE_ASYNC)
          if (decoder->mode == MAD_DECODER_MODE_ASYNC) {
    	switch (check_message(decoder)) {
    	case MAD_FLOW_IGNORE:
    	case MAD_FLOW_CONTINUE:
    	  break;
    	case MAD_FLOW_BREAK:
    	  goto fail;
    	case MAD_FLOW_STOP:
    	  goto done;
    	}
          }
    # endif
    
          if (decoder->header_func) {
    	if (mad_header_decode(&frame->header, stream) == -1) {
    	  if (!MAD_RECOVERABLE(stream->error))
    	    break;
    
    	  switch (error_func(error_data, stream, frame)) {
    	  case MAD_FLOW_STOP:
    	    goto done;
    	  case MAD_FLOW_BREAK:
    	    goto fail;
    	  case MAD_FLOW_IGNORE:
    	  case MAD_FLOW_CONTINUE:
    	  default:
    	    continue;
    	  }
    	}
    
    	switch (decoder->header_func(decoder->cb_data, &frame->header)) {
    	case MAD_FLOW_STOP:
    	  goto done;
    	case MAD_FLOW_BREAK:
    	  goto fail;
    	case MAD_FLOW_IGNORE:
    	  continue;
    	case MAD_FLOW_CONTINUE:
    	  break;
    	}
          }
    
          if (mad_frame_decode(frame, stream) == -1) {
    	if (!MAD_RECOVERABLE(stream->error))
    	  break;
    
    	switch (error_func(error_data, stream, frame)) {
    	case MAD_FLOW_STOP:
    	  goto done;
    	case MAD_FLOW_BREAK:
    	  goto fail;
    	case MAD_FLOW_IGNORE:
    	  break;
    	case MAD_FLOW_CONTINUE:
    	default:
    	  continue;
    	}
          }
          else
    	bad_last_frame = 0;
    
          if (decoder->filter_func) {
    	switch (decoder->filter_func(decoder->cb_data, stream, frame)) {
    	case MAD_FLOW_STOP:
    	  goto done;
    	case MAD_FLOW_BREAK:
    	  goto fail;
    	case MAD_FLOW_IGNORE:
    	  continue;
    	case MAD_FLOW_CONTINUE:
    	  break;
    	}
          }
    
          mad_synth_frame(synth, frame);
    
          if (decoder->output_func) {
    	switch (decoder->output_func(decoder->cb_data,
    				     &frame->header, &synth->pcm)) {
    	case MAD_FLOW_STOP:
    	  goto done;
    	case MAD_FLOW_BREAK:
    	  goto fail;
    	case MAD_FLOW_IGNORE:
    	case MAD_FLOW_CONTINUE:
    	  break;
    	}
          }
        }
      }
      while (stream->error == MAD_ERROR_BUFLEN);
    
     fail:
      result = -1;
    
     done:
      mad_synth_finish(synth);
      mad_frame_finish(frame);
      mad_stream_finish(stream);
    
      return result;
    }
    
    # if defined(USE_ASYNC)
    static
    int run_async(struct mad_decoder *decoder)
    {
      pid_t pid;
      int ptoc[2], ctop[2], flags;
    
      if (pipe(ptoc) == -1)
        return -1;
    
      if (pipe(ctop) == -1) {
        close(ptoc[0]);
        close(ptoc[1]);
        return -1;
      }
    
      flags = fcntl(ptoc[0], F_GETFL);
      if (flags == -1 ||
          fcntl(ptoc[0], F_SETFL, flags | O_NONBLOCK) == -1) {
        close(ctop[0]);
        close(ctop[1]);
        close(ptoc[0]);
        close(ptoc[1]);
        return -1;
      }
    
      pid = fork();
      if (pid == -1) {
        close(ctop[0]);
        close(ctop[1]);
        close(ptoc[0]);
        close(ptoc[1]);
        return -1;
      }
    
      decoder->async.pid = pid;
    
      if (pid) {
        /* parent */
    
        close(ptoc[0]);
        close(ctop[1]);
    
        decoder->async.in  = ctop[0];
        decoder->async.out = ptoc[1];
    
        return 0;
      }
    
      /* child */
    
      close(ptoc[1]);
      close(ctop[0]);
    
      decoder->async.in  = ptoc[0];
      decoder->async.out = ctop[1];
    
      _exit(run_sync(decoder));
    
      /* not reached */
      return -1;
    }
    # endif
    
    /*
     * NAME:	decoder->run()
     * DESCRIPTION:	run the decoder thread either synchronously or asynchronously
     */
    int mad_decoder_run(struct mad_decoder *decoder, enum mad_decoder_mode mode)
    {
      int result;
      int (*run)(struct mad_decoder *) = 0;
    
      switch (decoder->mode = mode) {
      case MAD_DECODER_MODE_SYNC:
        run = run_sync;
        break;
    
      case MAD_DECODER_MODE_ASYNC:
    # if defined(USE_ASYNC)
        run = run_async;
    # endif
        break;
      }
    
      if (run == 0)
        return -1;
    
      decoder->sync = malloc(sizeof(*decoder->sync));
      if (decoder->sync == 0)
        return -1;
    
      result = run(decoder);
    
      free(decoder->sync);
      decoder->sync = 0;
    
      return result;
    }
    
    /*
     * NAME:	decoder->message()
     * DESCRIPTION:	send a message to and receive a reply from the decoder process
     */
    int mad_decoder_message(struct mad_decoder *decoder,
    			void *message, unsigned int *len)
    {
    # if defined(USE_ASYNC)
      if (decoder->mode != MAD_DECODER_MODE_ASYNC ||
          send(decoder->async.out, message, *len) != MAD_FLOW_CONTINUE ||
          receive(decoder->async.in, &message, len) != MAD_FLOW_CONTINUE)
        return -1;
    
      return 0;
    # else
      return -1;
    # endif
    }
    


  • 👍



  • Das ist der Decoder 👎



  • wenn den decoder algo. verstehst, kannst dir ja nen encoder dazu schreiben^^



  • Nein, kann ich nicht. Außerdem fehlt da der wichtigste Teil vom Decoder.




Anmelden zum Antworten