Пример #1
0
static void* avplay_thread(struct avplay_t* avplay)
{
  AVFormatContext *fmt_ctx = NULL;
  AVPacket pkt;
  int video_stream_idx = -1, audio_stream_idx = -1;
  int ret = 0;
  struct packet_t* packet;
  int msg;

  /* register all formats and codecs */
  av_register_all();

restart:
  /* Wait for a MSG_PLAY message */
  while (((msg = msgqueue_get(&avplay->msgqueue,10000)) != MSG_PLAY) && (!avplay->next_url));

  fprintf(stderr,"avplay: waiting for playback mutex\n");
  pthread_mutex_lock(&avplay->codecs->playback_mutex);
  fprintf(stderr,"avplay: gotplayback mutex\n");

  /* Resume sending packets to codecs */
  codec_new_channel(&avplay->codecs->vcodec);
  codec_new_channel(&avplay->codecs->acodec);
  avplay->codecs->acodec.first_packet = 1;
  avplay->codecs->vcodec.first_packet = 1;

  avplay->codecs->vcodec.is_running = 1;
  avplay->codecs->acodec.is_running = 1;

  avplay->url = strdup(avplay->next_url);
  avplay->next_url = NULL;

  /* open input file, and allocate format context */
  if (avformat_open_input(&fmt_ctx, avplay->url, NULL, NULL) < 0) {
    fprintf(stderr, "Could not open source file %s\n", avplay->url);
    return 1;
  }

  /* retrieve stream information */
  if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
    fprintf(stderr, "Could not find stream information\n");
    ret = 2;
    goto end;
  }

  /* dump input information to stderr */
  av_dump_format(fmt_ctx, 0, avplay->url, 0);

  if ((ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0)) >= 0) {
    video_stream_idx = ret;
  }

  if ((ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0)) >= 0) {
    audio_stream_idx = ret;
  }

  if (audio_stream_idx == -1 && video_stream_idx == -1) {
    fprintf(stderr, "Could not find audio or video stream in the input, aborting\n");
    ret = 3;
    goto end;
  }

  fprintf(stderr,"video_stream_idx=%d\n",video_stream_idx);
  fprintf(stderr,"audio_stream_idx=%d\n",audio_stream_idx);

  if ((avplay->codecs->vcodec.vcodectype = map_vcodec(fmt_ctx->streams[video_stream_idx]->codec->codec_id)) == -1) {
    fprintf(stderr,"Unsupported video codec\n");
    exit(1);
  }
  if ((avplay->codecs->acodec.acodectype = map_acodec(fmt_ctx->streams[audio_stream_idx]->codec->codec_id)) == -1) {
    fprintf(stderr,"Unsupported audio codec\n");
    exit(1);
  }

  if (fmt_ctx->streams[audio_stream_idx]->codec->codec_id == CODEC_ID_AAC) {
    AVCodecContext* c =  fmt_ctx->streams[audio_stream_idx]->codec;
    if (c->extradata_size != 2) {
      fprintf(stderr,"Unexpected AAC extradata size %d, aborting\n",c->extradata_size);
      exit(1);
    }

    packet = malloc(sizeof(*packet));
    packet->packet = malloc(2);
    packet->packetlength = 2;
    memcpy(packet->packet, c->extradata, 2);

    codec_queue_add_item(&avplay->codecs->acodec,packet,MSG_CODECDATA);
  }


  AVCodecContext* c =  fmt_ctx->streams[video_stream_idx]->codec;

  unsigned char* annexb_extradata = NULL;
  int annexb_extradata_size = 0;
  int nalsize = 0;

  if ((avplay->codecs->vcodec.vcodectype == OMX_VIDEO_CodingAVC) && (c->extradata)) {
    if ((c->extradata[0]==0) && (c->extradata[1]==0) && (c->extradata[2]==0) && (c->extradata[3]==1)) {
      fprintf(stderr,"Extradata is already in annexb format.\n");
      annexb_extradata = c->extradata;
      annexb_extradata_size = c->extradata_size;
    } else {
      int i,j,k;

      nalsize = (c->extradata[4] & 0x3) + 1;
      if (nalsize != 4) {
         fprintf(stderr,"Unsupported nalsize %d, aborting\n",nalsize);
         exit(1);
      }
      int sps_len = (c->extradata[6] << 8) | c->extradata[7];
      fprintf(stderr,"sps_len=%d\n",sps_len);
      annexb_extradata_size = sps_len + 4;

      int pps_count = c->extradata[8+sps_len];
      i = 9 + sps_len;
      for (j=0;j<pps_count;j++) {
        int pps_len = (c->extradata[i] << 8) | c->extradata[i+1];
        i += 2;
        fprintf(stderr,"pps_len=%d\n",pps_len);
        i += pps_len;
        annexb_extradata_size += 4 + pps_len;
      }

      fprintf(stderr,"annexb_extradata_size = %d\n",annexb_extradata_size);
      annexb_extradata = malloc(annexb_extradata_size);

      annexb_extradata[0] = 0;
      annexb_extradata[1] = 0;
      annexb_extradata[2] = 0;
      annexb_extradata[3] = 1;
      memcpy(annexb_extradata + 4, c->extradata+8, sps_len);
      k = sps_len + 4;
      i = 9 + sps_len;
      for (j=0;j<pps_count;j++) {
        int pps_len = (c->extradata[i] << 8) | c->extradata[i+1];
        i += 2;
        annexb_extradata[k] = 0;
        annexb_extradata[k+1] = 0;
        annexb_extradata[k+2] = 0;
        annexb_extradata[k+3] = 1;
        k += 4;
        memcpy(annexb_extradata + k, c->extradata+i, pps_len);
        i += pps_len;
      }
    }
  }

  /* initialize packet, set data to NULL, let the demuxer fill it */
  av_init_packet(&pkt);
  pkt.data = NULL;
  pkt.size = 0;

#ifdef DUMP_VIDEO
  int fd;
  static int track = 0;
  char filename[32];

  sprintf(filename,"video%03d.dump",++track);
  fd = open(filename,O_CREAT|O_TRUNC|O_RDWR,0666);
  if (fd < 0) {
    fprintf(stderr,"Could not create video.dump\n");
    exit(1);
  }
#endif

  int first_video = 1; 
  AVRational omx_timebase = {1,1000000};
  /* read frames from the file */
  while (1) {
    msg = msgqueue_get(&avplay->msgqueue,0);

    if (msg == MSG_STOP) {
      break;
    }

    if (av_read_frame(fmt_ctx, &pkt) < 0) {
      fprintf(stderr,"Error reading stream, ending\n");
      break;
    }

    //fprintf(stderr,"Read pkt - index=%d\n",pkt.stream_index);

    if ((pkt.stream_index == video_stream_idx) || (pkt.stream_index == audio_stream_idx)) {
      packet = malloc(sizeof(*packet));
      packet->PTS = av_rescale_q(pkt.pts, fmt_ctx->streams[pkt.stream_index]->time_base, omx_timebase);
      packet->DTS = -1;

      packet->packetlength = pkt.size;

      if ((pkt.stream_index == video_stream_idx) && (first_video) && (annexb_extradata_size > 0)) {
        /* Add extradata to first video frame */
        packet->packetlength += annexb_extradata_size;
        packet->packet = malloc(packet->packetlength);
        memcpy(packet->packet, annexb_extradata, annexb_extradata_size);
        if (nalsize > 0) {
          convert4(packet->packet+annexb_extradata_size,pkt.data,pkt.size);
        } else {
          memcpy(packet->packet+annexb_extradata_size,pkt.data,pkt.size);
        }
      } else {
        packet->packet = malloc(packet->packetlength);
        if ((pkt.stream_index == video_stream_idx) && (nalsize > 0)) {
          convert4(packet->packet,pkt.data,pkt.size);
        } else {
          memcpy(packet->packet,pkt.data,pkt.size);
        }
      }
      packet->buf = packet->packet;  /* This is what is free()ed */
      
      if (pkt.stream_index == video_stream_idx) {
#ifdef DUMP_VIDEO
        write(fd,packet->packet,packet->packetlength);
#endif
        //fprintf(stderr,"Adding video packet - PTS=%lld, size=%d\n",packet->PTS, packet->packetlength);
        first_video = 0;
        while (avplay->codecs->vcodec.queue_count > 100) { usleep(100000); }  // FIXME
        codec_queue_add_item(&avplay->codecs->vcodec,packet,MSG_PACKET);
      } else {
	  //fprintf(stderr,"Adding audio packet - PTS=%lld, size=%d\n",packet->PTS, packet->packetlength);
        while (avplay->codecs->acodec.queue_count > 1000) { usleep(100000); }  // FIXME
        codec_queue_add_item(&avplay->codecs->acodec,packet,MSG_PACKET);
      }
    }
  
    av_free_packet(&pkt);
  }

#ifdef DUMP_VIDEO
  close(fd);
#endif

end:
  codec_stop(&avplay->codecs->vcodec);
  codec_stop(&avplay->codecs->acodec);
  if (avplay->url) free(avplay->url);  /* This should never be null */
  pthread_mutex_unlock(&avplay->codecs->playback_mutex);
  avformat_close_input(&fmt_ctx);
  goto restart;

  return 0;
}
Пример #2
0
static void toccata_put(uaecptr addr, uae_u8 v)
{
	struct toccata_data *data = &toccata;
	int idx = data->ad1848_index & 15;

#if DEBUG_TOCCATA > 2
	if (addr & 0x4000)
		write_log(_T("TOCCATA PUT %08x %02x %d PC=%08X\n"), addr, v, idx, M68K_GETPC);
#endif

	if ((addr & 0x6801) == 0x6001) {
		// AD1848 register 0
		data->ad1848_index = v;
	} else if ((addr & 0x6801) == 0x6801) {
		// AD1848 register 1
		uae_u8 old = data->ad1848_regs[idx];
		data->ad1848_regs[idx] = v;
#if DEBUG_TOCCATA > 0
		write_log(_T("TOCCATA PUT reg %d = %02x PC=%08x\n"), idx, v, M68K_GETPC);
#endif
		switch(idx)
		{
			case 9:
			if (v & 8) // ACI enabled
				data->autocalibration = 50;
			if (!(old & 3) && (v & 3))
				codec_start();
			else if ((old & 3) && !(v & 3))
				codec_stop();
			break;

			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
			case 8:
				calculate_volume_toccata();
			break;

		}
	} else if ((addr & 0x6800) == 0x2000) {
		// FIFO input
		if (data->toccata_status & STATUS_FIFO_PLAY) {
			// 7202LA datasheet says fifo can't overflow
			if (((data->fifo_write_index + 1) % FIFO_SIZE) != data->fifo_read_index) {
				data->fifo[data->fifo_write_index] = v;
				data->fifo_write_index++;
				data->fifo_write_index %= FIFO_SIZE;
				data->data_in_fifo++;
			}
		}
		data->toccata_irq &= ~STATUS_READ_PLAY_HALF;
		data->fifo_half &= ~STATUS_FIFO_PLAY;
	} else if ((addr & 0x6800) == 0x0000) {
		// Board status
		if (v & STATUS_RESET) {
			codec_stop();
			data->toccata_status = 0;
			data->toccata_irq = 0;
			v = 0;
		}
		if (v == STATUS_ACTIVE) {
			data->fifo_write_index = 0;
			data->fifo_read_index = 0;
			data->data_in_fifo = 0;
			data->toccata_status = 0;
			data->toccata_irq = 0;
			data->fifo_half = 0;
		}
		data->toccata_status = v;
#if DEBUG_TOCCATA > 0
		write_log(_T("TOCCATA PUT STATUS %08x %02x %d PC=%08X\n"), addr, v, idx, M68K_GETPC);
#endif
	} else {
		write_log(_T("TOCCATA PUT UNKNOWN %08x\n"), addr);
	}
}
Пример #3
0
/* Call the codec's exit routine and close all references */
void codec_unload(void)
{
    codec_stop();
    LOGFQUEUE("audio >| codec Q_CODEC_UNLOAD");
    codec_queue_send(Q_CODEC_UNLOAD, 0);
}